#!/usr/bin/env python3.9 import argparse import logging import subprocess import sys from pathlib import Path def parse_args(argv: list[str]): arger = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) arger.add_argument("files", nargs="+", type=Path, help="Video paths") arger.add_argument("-o", dest="output_path", type=Path, help="Output path", required=True) if len(argv) == 0: arger.print_help() exit(1) return arger.parse_args(argv) def combine_videos(videos: list[Path], save_path: Path) -> Path: """ Combine multiple videos into one. :param videos: List of video paths. :param save_path: Path to save the combined video. :return: Path to the combined video. """ # file '/path/to/file1' # file '/path/to/file2' # file '/path/to/file3' # # $ ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4 # ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4 stdin = "\n".join(f"file '{video.absolute()}'" for video in videos if video.is_file()) # fmt: off args = [ 'ffmpeg', '-protocol_whitelist', 'file,pipe', '-f', 'concat', '-safe', '0', '-i', '-', '-c', 'copy', str(save_path), ] # fmt: on logging.info(f"calling ffmpeg with {args=} and {stdin=}") subprocess.run(args, input=stdin.encode(), check=True) return save_path def main(): logging.basicConfig(level=logging.INFO) args = parse_args(sys.argv[1:]) paths = [Path(f) for f in args.files] combine_videos(videos=paths, save_path=args.output_path) if __name__ == "__main__": main()