forked from LiveCarta/ContentGeneration
86 lines
2.2 KiB
Python
86 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Concatenate merged_*.mp4 files into a single output using ffmpeg concat demuxer."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import logging
|
|
import re
|
|
import subprocess
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
from logging_config import configure_logging, debug_log_lifecycle
|
|
|
|
|
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
DEFAULT_BASE_DIR = SCRIPT_DIR.parents[1]
|
|
DEFAULT_MERGED_DIR = DEFAULT_BASE_DIR / "merged"
|
|
DEFAULT_OUTPUT = DEFAULT_BASE_DIR / "results" / "run_3" / "final_output.mp4"
|
|
|
|
LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
def shot_number(path: Path) -> int:
|
|
match = re.search(r"merged_(\d+)\.mp4$", path.name)
|
|
return int(match.group(1)) if match else -1
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--merged-dir", type=Path, default=DEFAULT_MERGED_DIR)
|
|
parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
|
|
parser.add_argument(
|
|
"--log-level",
|
|
default=None,
|
|
help="Logging level (overrides LOG_LEVEL env var)",
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
@debug_log_lifecycle
|
|
def main() -> int:
|
|
args = parse_args()
|
|
configure_logging(args.log_level)
|
|
|
|
videos = sorted(args.merged_dir.glob("merged_*.mp4"), key=shot_number)
|
|
if not videos:
|
|
LOGGER.warning("No merged videos found in %s", args.merged_dir)
|
|
return 1
|
|
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as tmp:
|
|
filelist = Path(tmp.name)
|
|
for video in videos:
|
|
tmp.write(f"file '{video}'\\n")
|
|
|
|
try:
|
|
LOGGER.info("Concatenating the following files:\n%s", filelist.read_text().rstrip())
|
|
|
|
subprocess.run(
|
|
[
|
|
"ffmpeg",
|
|
"-f",
|
|
"concat",
|
|
"-safe",
|
|
"0",
|
|
"-i",
|
|
str(filelist),
|
|
"-c",
|
|
"copy",
|
|
"-y",
|
|
str(args.output),
|
|
],
|
|
check=True,
|
|
)
|
|
finally:
|
|
filelist.unlink(missing_ok=True)
|
|
|
|
LOGGER.info("Done")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|