mirror of
https://github.com/linyqh/NarratoAI.git
synced 2025-12-12 03:02:48 +00:00
- 新增 test_moviepy_merge.py,实现视频合并功能 - 新增 test_moviepy_speed.py,实现视频加速处理- 添加 VideoMerger 和 VideoSpeedProcessor 类,分别用于视频合并和速度处理 - 测试脚本展示了如何使用 moviepy 进行视频编辑
144 lines
4.5 KiB
Python
144 lines
4.5 KiB
Python
"""
|
|
使用 moviepy 合并视频、音频、字幕和背景音乐
|
|
"""
|
|
|
|
from moviepy.editor import (
|
|
VideoFileClip,
|
|
AudioFileClip,
|
|
TextClip,
|
|
CompositeVideoClip,
|
|
concatenate_videoclips
|
|
)
|
|
# from moviepy.config import change_settings
|
|
import os
|
|
|
|
# 设置字体文件路径(用于中文字幕显示)
|
|
FONT_PATH = "../../resource/fonts/STHeitiMedium.ttc" # 请确保此路径下有对应字体文件
|
|
# change_settings(
|
|
# {"IMAGEMAGICK_BINARY": r"C:\Program Files\ImageMagick-7.1.1-Q16\magick.exe"}) # Windows系统需要设置 ImageMagick 路径
|
|
|
|
|
|
class VideoMerger:
|
|
"""视频合并处理类"""
|
|
|
|
def __init__(self, output_path: str = "../../resource/videos/merged_video.mp4"):
|
|
"""
|
|
初始化视频合并器
|
|
参数:
|
|
output_path: 输出文件路径
|
|
"""
|
|
self.output_path = output_path
|
|
self.video_clips = []
|
|
self.background_music = None
|
|
self.subtitles = []
|
|
|
|
def add_video(self, video_path: str, start_time: str = None, end_time: str = None) -> None:
|
|
"""
|
|
添加视频片段
|
|
参数:
|
|
video_path: 视频文件路径
|
|
start_time: 开始时间 (格式: "MM:SS")
|
|
end_time: 结束时间 (格式: "MM:SS")
|
|
"""
|
|
video = VideoFileClip(video_path)
|
|
if start_time and end_time:
|
|
video = video.subclip(self._time_to_seconds(start_time),
|
|
self._time_to_seconds(end_time))
|
|
self.video_clips.append(video)
|
|
|
|
def add_audio(self, audio_path: str, volume: float = 1.0) -> None:
|
|
"""
|
|
添加背景音乐
|
|
参数:
|
|
audio_path: 音频文件路径
|
|
volume: 音量大小 (0.0-1.0)
|
|
"""
|
|
self.background_music = AudioFileClip(audio_path).volumex(volume)
|
|
|
|
def add_subtitle(self, text: str, start_time: str, end_time: str,
|
|
position: tuple = ('center', 'bottom'), fontsize: int = 24) -> None:
|
|
"""
|
|
添加字幕
|
|
参数:
|
|
text: 字幕文本
|
|
start_time: 开始时间 (格式: "MM:SS")
|
|
end_time: 结束时间 (格式: "MM:SS")
|
|
position: 字幕位置
|
|
fontsize: 字体大小
|
|
"""
|
|
subtitle = TextClip(
|
|
text,
|
|
font=FONT_PATH,
|
|
fontsize=fontsize,
|
|
color='white',
|
|
stroke_color='black',
|
|
stroke_width=2
|
|
)
|
|
|
|
subtitle = subtitle.set_position(position).set_duration(
|
|
self._time_to_seconds(end_time) - self._time_to_seconds(start_time)
|
|
).set_start(self._time_to_seconds(start_time))
|
|
|
|
self.subtitles.append(subtitle)
|
|
|
|
def merge(self) -> None:
|
|
"""合并所有媒体元素并导出视频"""
|
|
if not self.video_clips:
|
|
raise ValueError("至少需要添加一个视频片段")
|
|
|
|
# 合并视频片段
|
|
final_video = concatenate_videoclips(self.video_clips)
|
|
|
|
# 如果有背景音乐,设置其持续时间与视频相同
|
|
if self.background_music:
|
|
self.background_music = self.background_music.set_duration(final_video.duration)
|
|
final_video = final_video.set_audio(self.background_music)
|
|
|
|
# 添加字幕
|
|
if self.subtitles:
|
|
final_video = CompositeVideoClip([final_video] + self.subtitles)
|
|
|
|
# 导出最终视频
|
|
final_video.write_videofile(
|
|
self.output_path,
|
|
fps=24,
|
|
codec='libx264',
|
|
audio_codec='aac'
|
|
)
|
|
|
|
# 释放资源
|
|
final_video.close()
|
|
for clip in self.video_clips:
|
|
clip.close()
|
|
if self.background_music:
|
|
self.background_music.close()
|
|
|
|
@staticmethod
|
|
def _time_to_seconds(time_str: str) -> float:
|
|
"""将时间字符串转换为秒数"""
|
|
minutes, seconds = map(int, time_str.split(':'))
|
|
return minutes * 60 + seconds
|
|
|
|
|
|
def test_merge_video():
|
|
"""测试视频合并功能"""
|
|
merger = VideoMerger()
|
|
|
|
# 添加两个视频片段
|
|
merger.add_video("../../resource/videos/cut_video.mp4", "00:00", "01:00")
|
|
merger.add_video("../../resource/videos/demo.mp4", "00:00", "00:30")
|
|
|
|
# 添加背景音乐
|
|
merger.add_audio("../../resource/songs/output000.mp3", volume=0.3)
|
|
|
|
# 添加字幕
|
|
merger.add_subtitle("第一个精彩片段", "00:00", "00:05")
|
|
merger.add_subtitle("第二个精彩片段", "01:00", "01:05")
|
|
|
|
# 合并并导出
|
|
merger.merge()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_merge_video()
|