# -*- coding: utf-8 -*- """视频合成模块 使用 MoviePy 将图片背景 + 音频 + 字幕合成为最终视频。 """ import os from moviepy.editor import ( ImageClip, AudioFileClip, CompositeVideoClip, concatenate_videoclips, ColorClip, ) from moviepy.video.tools.subtitles import SubtitlesClip from moviepy.editor import TextClip def _make_bg(size, duration, color=(20, 20, 40)): """生成纯色背景片段""" return ColorClip(size=size, color=color, duration=duration) def _make_subtitle_clip(text: str, size, duration: float): """生成一段字幕文本片段""" w, h = size try: txt = TextClip(text, fontsize=48, color="white", font="Arial", size=(w - 100, None), method="caption") except Exception: # 若系统找不到字体,退化为默认字体 txt = TextClip(text, fontsize=48, color="white", size=(w - 100, None), method="caption") txt = txt.set_position(("center", h - 180)).set_duration(duration) return txt def compose_video(scenes: list, audio_paths: list, durations: list, out_path: str, resolution=(1280, 720)) -> str: """合成最终视频。 Args: scenes: 场景列表 audio_paths: 每个场景对应的音频路径 durations: 每个场景的时长 out_path: 输出 mp4 路径 resolution: (width, height) Returns: str: 输出文件路径 """ os.makedirs(os.path.dirname(out_path), exist_ok=True) clips = [] for scene, audio, dur in zip(scenes, audio_paths, durations): bg = _make_bg(resolution, dur) sub = _make_subtitle_clip(scene["text"], resolution, dur) audio_clip = AudioFileClip(audio) clip = CompositeVideoClip([bg, sub]).set_audio(audio_clip) clips.append(clip) final = concatenate_videoclips(clips, method="compose") final.write_videofile(out_path, fps=24, codec="libx264", audio_codec="aac") return out_path if __name__ == "__main__": print("请通过 cli.py 或 app.py 调用")