Last active
March 26, 2020 10:13
-
-
Save samdobson/f68f941cefdebf9bc529450d4eeb19ed to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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