Skip to content

Instantly share code, notes, and snippets.

@meequrox
Last active November 28, 2023 05:39
Show Gist options
  • Save meequrox/5856bc76787645957ce890b70e494171 to your computer and use it in GitHub Desktop.
Save meequrox/5856bc76787645957ce890b70e494171 to your computer and use it in GitHub Desktop.
The only correct way to concatenate media files using ffmpeg
#!/usr/bin/env python3
import sys
import pathlib
def get_video_files() -> list[str]:
video_formats: set = {
".mp4", ".mkv", ".webm", ".flv", ".avi", ".mts", ".mpg", ".m2ts", ".ts",
".mov", ".wmv", ".m4v", ".3gp", ".mpeg"
}
cwd = pathlib.Path(".")
return sorted([
f.name
for f in cwd.iterdir()
if f.is_file() and f.suffix.lower() in video_formats
])
def build_ffmpeg_command(files: list[str],
output_file: str,
resize_height: None | int = None):
n = len(files)
if n == 0:
print("No video files in current working directory")
return ""
vfilter = f"scale=-1:{resize_height}" if resize_height else "null"
cmd = "ffmpeg"
for file in files:
cmd += f" -i {file}"
cmd += ' -filter_complex "'
for i in range(0, n):
cmd += f"[{i}:v:0]{vfilter}[v{i}];"
for i in range(0, n):
cmd += f"[v{i}][{i}:a:0]"
cmd += f'concat=n={n}:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" {output_file}'
return cmd
def usage():
print(f"Usage: {sys.argv[0]} <RESULT_FILENAME> [RESIZE_HEIGHT]")
print("Examples:")
print(f"\t{sys.argv[0]} result.mp4")
print(f"\t{sys.argv[0]} output.mkv 720")
print(f"\t{sys.argv[0]} video.mov 576")
def main():
files = get_video_files()
if len(sys.argv) == 2:
cmd = build_ffmpeg_command(files, sys.argv[1])
elif len(sys.argv) == 3:
cmd = build_ffmpeg_command(files, sys.argv[1], int(sys.argv[2]))
else:
usage()
exit(1)
print(cmd)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment