aps-agent/video/build_video.py

50 lines
1.6 KiB
Python
Raw Normal View History

"""将幻灯片与配音逐段合成为 MP4,再拼接为完整视频。"""
import subprocess
import sys
from pathlib import Path
import imageio_ffmpeg
FFMPEG = imageio_ffmpeg.get_ffmpeg_exe()
WS = Path(__file__).resolve().parent
REPO_ROOT = WS.parent
PARTS = WS / "parts"
PARTS.mkdir(exist_ok=True)
N = 12
part_files = []
for i in range(1, N + 1):
slide = WS / "slides" / f"slide{i:02d}.png"
audio = WS / "audio" / f"seg{i:02d}.mp3"
part = PARTS / f"part{i:02d}.mp4"
cmd = [
FFMPEG, "-y",
"-loop", "1", "-framerate", "30", "-i", str(slide),
"-i", str(audio),
"-c:v", "libx264", "-preset", "medium", "-tune", "stillimage",
"-c:a", "aac", "-b:a", "192k",
"-pix_fmt", "yuv420p",
"-shortest", "-movflags", "+faststart",
str(part),
]
r = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
if r.returncode != 0 or not part.exists():
print(f"part{i:02d} 合成失败:\n{r.stderr[-800:]}")
sys.exit(1)
part_files.append(part)
print(f"part{i:02d}.mp4 ✓ ({part.stat().st_size // 1024} KB)")
lst = WS / "concat.txt"
lst.write_text("".join(f"file 'parts/{p.name}'\n" for p in part_files), encoding="utf-8")
final = REPO_ROOT / "APS智能体演示视频.mp4"
r = subprocess.run(
[FFMPEG, "-y", "-f", "concat", "-safe", "0", "-i", str(lst),
"-c", "copy", "-movflags", "+faststart", str(final)],
capture_output=True, text=True, timeout=600,
)
if r.returncode != 0 or not final.exists():
print("拼接失败:\n", r.stderr[-800:])
sys.exit(1)
print(f"\n最终视频: {final} ({final.stat().st_size / 1024 / 1024:.1f} MB)")