add new video edit scripts for combine video and spliting video
This commit is contained in:
1 parent
ee93c06f7d
commit
856ab439f7
10 files changed
+199
-32
No files matched your search
@@ -1,129 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Combine multiple video files into one file using FFmpeg.
|
||||
|
||||
Example:
|
||||
python helper_files/combine_videos.py output.mp4 video1.mp4 video2.mp4 video3.mp4
|
||||
python helper_files/combine_videos.py --output merged.mp4 --inputs video1.mp4 video2.mp4
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def build_concat_list(input_files, list_path):
|
||||
with open(list_path, "w", encoding="utf-8") as f:
|
||||
for path in input_files:
|
||||
f.write(f"file '{os.path.abspath(path)}'\n")
|
||||
|
||||
|
||||
def run_ffmpeg(cmd):
|
||||
print("Running:", " ".join(cmd))
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
print(result.stdout)
|
||||
print(result.stderr)
|
||||
raise RuntimeError(f"FFmpeg failed with exit code {result.returncode}")
|
||||
print("✅ Finished successfully.")
|
||||
|
||||
|
||||
def concat_videos_copy(input_files, output_path):
|
||||
list_path = Path(output_path).with_suffix(".concat.txt")
|
||||
build_concat_list(input_files, list_path)
|
||||
|
||||
cmd = [
|
||||
"ffmpeg",
|
||||
"-y",
|
||||
"-f", "concat",
|
||||
"-safe", "0",
|
||||
"-i", str(list_path),
|
||||
"-c", "copy",
|
||||
str(output_path),
|
||||
]
|
||||
run_ffmpeg(cmd)
|
||||
list_path.unlink(missing_ok=True)
|
||||
|
||||
|
||||
def concat_videos_reencode(input_files, output_path):
|
||||
inputs = []
|
||||
filter_parts = []
|
||||
audio_parts = []
|
||||
|
||||
for i, video_path in enumerate(input_files):
|
||||
inputs.extend(["-i", str(video_path)])
|
||||
filter_parts.append(f"[{i}:v]scale=trunc(iw/2)*2:trunc(ih/2)*2,setpts=PTS-STARTPTS[v{i}]")
|
||||
audio_parts.append(f"[{i}:a]aresample=async=1[a{i}]")
|
||||
|
||||
concat_filter = ",".join(filter_parts + audio_parts)
|
||||
map_parts = []
|
||||
for i in range(len(input_files)):
|
||||
map_parts.append(f"[v{i}]")
|
||||
map_parts.append(f"[a{i}]")
|
||||
|
||||
# Join the video and audio streams in order and concatenate them.
|
||||
# This works well when the clips are similar enough in format.
|
||||
filter_complex = f"{','.join(filter_parts)};{';'.join(audio_parts)};"
|
||||
filter_complex += "".join(f"[{i}:v][{i}:a]" for i in range(len(input_files)))
|
||||
filter_complex += f"concat=n={len(input_files)}:v=1:a=1[outv][outa]"
|
||||
|
||||
cmd = [
|
||||
"ffmpeg",
|
||||
"-y",
|
||||
*inputs,
|
||||
"-filter_complex",
|
||||
filter_complex,
|
||||
"-map",
|
||||
"[outv]",
|
||||
"-map",
|
||||
"[outa]",
|
||||
"-c:v",
|
||||
"libx264",
|
||||
"-c:a",
|
||||
"aac",
|
||||
"-movflags",
|
||||
"+faststart",
|
||||
str(output_path),
|
||||
]
|
||||
run_ffmpeg(cmd)
|
||||
|
||||
|
||||
def merge_videos(input_files, output_path):
|
||||
input_files = [str(Path(p).expanduser().resolve()) for p in input_files]
|
||||
output_path = str(Path(output_path).expanduser().resolve())
|
||||
|
||||
if len(input_files) < 2:
|
||||
raise ValueError("You need at least 2 video files to merge.")
|
||||
|
||||
for path in input_files:
|
||||
if not os.path.exists(path):
|
||||
raise FileNotFoundError(f"File not found: {path}")
|
||||
|
||||
output_dir = Path(output_path).parent
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
try:
|
||||
concat_videos_copy(input_files, output_path)
|
||||
except Exception as exc:
|
||||
print(f"Fast copy method failed: {exc}")
|
||||
print("Retrying with re-encode fallback...")
|
||||
concat_videos_reencode(input_files, output_path)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Join two or more video files together with FFmpeg.")
|
||||
parser.add_argument("output_file", help="Path to the merged output video")
|
||||
parser.add_argument("input_files", nargs="+", help="Two or more videos to concatenate")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
merge_videos(args.input_files, args.output_file)
|
||||
print(f"Merged video saved to: {args.output_file}")
|
||||
except Exception as exc:
|
||||
print(f"Error: {exc}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user