Skip to content

Instantly share code, notes, and snippets.

@samdobson
Last active March 26, 2020 10:13
Show Gist options
  • Save samdobson/f68f941cefdebf9bc529450d4eeb19ed to your computer and use it in GitHub Desktop.
Save samdobson/f68f941cefdebf9bc529450d4eeb19ed to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
"""
Generate a (Windows) ffmpeg script to create a video montage from multiple sources
Author: S Dobson
Date: 25/03/2020
"""
import sys
##### CONFIGURATION #####
# Input files
num_vids = 37 # Number of videos to be included
input_filename = 'videos\sevillanos' # Must be followed by ' (1)', ' (2)', ' (3)' etc.
input_filetype = 'mp4' # File extension of input files
# Grid settings
num_cols = 13 # Number of columns in the grid
num_rows = 3 # Number of rows in the grid
gaps = [(2, 12), (2, 13)] # Grid positions where a gap should be left
# Output settings
save = True # If False, play
output_filename = 'muntatge-2.mp4'
length = 125 # Duration of the video in seconds
quality = 'qqvga' # Quality (160x120)
##### SCRIPT GENERATION #####
# Define inputs
for x in range(num_vids):
print(f'-ss 00:00:00.0000 -i "{input_filename} ({x+1}).{input_filetype}" ^')
# Sense check and create layout
num_gaps_required = (num_cols*num_rows) - num_vids
if len(gaps) != num_gaps_required:
print(f'Configuration error: a {num_cols}x{num_rows} grid to fit {num_vids} videos requires {num_gaps_required} gaps, not {len(gaps)}')
sys.exit()
layout = []
widths = [f'w{x}' for x in range(num_cols)]
heights = [f'h{x}' for x in range(num_rows)]
for r in range(num_rows):
for c in range(num_cols):
if (r, c) in gaps:
continue
w = '+'.join(widths[:c]) if c > 0 else '0'
h = '+'.join(heights[:r]) if r > 0 else '0'
layout.append(f'{w}_{h}')
# Print the completed script for use with ffmpeg
output = output_filename if save else '- | ffplay -autoexit -left 30 -top 30 - '
print('ffmpeg ^')
print('-filter_complex "' + ''.join([f'[{x}:v] setpts=PTS-STARTPTS, scale={quality} [a{x}];'
for x in range(num_vids)]) + \
''.join([f'[a{x}]' for x in range(num_vids)]) + f'xstack=inputs={num_vids}:layout=' + '|'.join(layout) + f'[out]" -map "[out]" -c:v libx264 -t {length} -f matroska ' + output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment