|
@@ -126,39 +126,37 @@ class VideoStitching():
|
|
|
|
|
|
# 视频拼接
|
|
# 视频拼接
|
|
@classmethod
|
|
@classmethod
|
|
- def concatenate_videos(cls, videos, audio, srt):
|
|
|
|
|
|
+ def concatenate_videos(cls, videos, audio, srt, output_path):
|
|
|
|
+ # 设置最大可使用内存限制(单位:字节)
|
|
|
|
+ memory_limit = 4 * 1024 * 1024 * 1024 # 4GB
|
|
|
|
+ resource.setrlimit(resource.RLIMIT_AS, (memory_limit, memory_limit))
|
|
|
|
+
|
|
clips = []
|
|
clips = []
|
|
- total_duration = 0
|
|
|
|
included_videos = []
|
|
included_videos = []
|
|
- # 设置最大可使用的内存限制(单位:字节)
|
|
|
|
- memory_limit = 2 * 1024 * 1024 * 1024 # 2GB
|
|
|
|
- resource.setrlimit(resource.RLIMIT_AS, (memory_limit, memory_limit))
|
|
|
|
|
|
+ total_duration = 0
|
|
|
|
+
|
|
# 提取视频的音频
|
|
# 提取视频的音频
|
|
- Common.logger().info(f"开始提取视频的音频{audio}")
|
|
|
|
- video1 = VideoFileClip(audio)
|
|
|
|
|
|
+ video1 = editor.VideoFileClip(audio)
|
|
mp3 = video1.audio
|
|
mp3 = video1.audio
|
|
- Common.logger().info(f"提取视频的音频成功")
|
|
|
|
|
|
|
|
# 获取音频时长(以秒为单位)
|
|
# 获取音频时长(以秒为单位)
|
|
duration_limit = mp3.duration
|
|
duration_limit = mp3.duration
|
|
|
|
+ Common.logger().info(f"音频时长为:{duration_limit}")
|
|
|
|
|
|
# 遍历每个视频并计算总时长
|
|
# 遍历每个视频并计算总时长
|
|
for i, video in enumerate(videos):
|
|
for i, video in enumerate(videos):
|
|
- clip = VideoFileClip(video[3])
|
|
|
|
|
|
+ clip = editor.VideoFileClip(video[3])
|
|
clips.append(clip)
|
|
clips.append(clip)
|
|
total_duration += clip.duration
|
|
total_duration += clip.duration
|
|
if total_duration >= duration_limit:
|
|
if total_duration >= duration_limit:
|
|
break
|
|
break
|
|
- # 处理完毕后释放视频剪辑对象
|
|
|
|
- clip.close()
|
|
|
|
- Common.logger().info(f"处理完毕后释放视频剪辑对象")
|
|
|
|
|
|
|
|
# 如果总时长小于等于目标时长,则不做视频拼接
|
|
# 如果总时长小于等于目标时长,则不做视频拼接
|
|
if total_duration <= duration_limit:
|
|
if total_duration <= duration_limit:
|
|
- Common.logger().info(f"时长小于等于目标时长,不做视频拼接")
|
|
|
|
|
|
+ Common.logger().info(f"总时长小于等于目标时长,则不做视频拼接")
|
|
|
|
+
|
|
return ""
|
|
return ""
|
|
else:
|
|
else:
|
|
- Common.logger().info(f"总时长大于目标时长")
|
|
|
|
remaining_time = duration_limit
|
|
remaining_time = duration_limit
|
|
final_clips = []
|
|
final_clips = []
|
|
|
|
|
|
@@ -172,64 +170,69 @@ class VideoStitching():
|
|
final_clips.append(clip.subclip(0, remaining_time))
|
|
final_clips.append(clip.subclip(0, remaining_time))
|
|
included_videos.append(video)
|
|
included_videos.append(video)
|
|
break
|
|
break
|
|
- final_clip = concatenate_videoclips(final_clips)
|
|
|
|
- final_clip = final_clip.set_audio(mp3)
|
|
|
|
- # 统一设置视频分辨率
|
|
|
|
- final_width = 480
|
|
|
|
- final_height = 720
|
|
|
|
- final_clip = final_clip.resize((final_width, final_height))
|
|
|
|
- # 设置背景色
|
|
|
|
- color_clip = editor.ColorClip(size=(final_width, 120),
|
|
|
|
- color=(255, 255, 0)).set_duration(duration_limit)
|
|
|
|
- final_clip = editor.CompositeVideoClip([final_clip, color_clip.set_position(("center", final_height - 100))])
|
|
|
|
- # 处理SRT字幕文件
|
|
|
|
- subtitle_file = f"./video_stitching/video/{srt}.srt"
|
|
|
|
- Common.logger().info(f"处理SRT字幕文件")
|
|
|
|
- if os.path.isfile(subtitle_file):
|
|
|
|
- with open(subtitle_file, 'r') as file:
|
|
|
|
- subtitles = file.read().strip().split('\n\n')
|
|
|
|
- # 从SRT字幕文件中获取字幕
|
|
|
|
- subtitle_clips = []
|
|
|
|
- for subtitle in subtitles:
|
|
|
|
- # 按行分割字幕内容
|
|
|
|
- subtitle_lines = subtitle.strip().split('\n')
|
|
|
|
- # 提取时间轴信息和字幕文本
|
|
|
|
- if len(subtitle_lines) >= 3:
|
|
|
|
- times, text = subtitle_lines[1], '\n'.join(subtitle_lines[2:])
|
|
|
|
- start, end = map(cls.srt_to_seconds, times.split(' --> '))
|
|
|
|
- start = editor.cvsecs(start)
|
|
|
|
- end = editor.cvsecs(end)
|
|
|
|
- text = cls.split_text(text, 10)
|
|
|
|
- # /System/Library/Fonts/Hiragino Sans GB.ttc 本地字体
|
|
|
|
- Common.logger().info(f"字幕:{text}")
|
|
|
|
-
|
|
|
|
- sub = editor.TextClip(text, font="/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
|
|
|
|
- fontsize=30, color="black").set_duration(end - start).set_start(
|
|
|
|
- start).set_position(
|
|
|
|
- ("center", final_height - 80)).set_opacity(0.8)
|
|
|
|
- subtitle_clips.append(sub)
|
|
|
|
- Common.logger().info(f"将字幕添加到视频上")
|
|
|
|
- # 将字幕添加到视频上
|
|
|
|
- video_with_subtitles = editor.CompositeVideoClip([final_clip] + subtitle_clips)
|
|
|
|
- else:
|
|
|
|
- text_clip = (
|
|
|
|
- editor.TextClip("分享、转发给群友", font="/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
|
|
|
|
- fontsize=30, color="black").
|
|
|
|
- set_position(("center", final_height - 80)).
|
|
|
|
- set_duration(duration_limit).
|
|
|
|
- set_opacity(0.8)
|
|
|
|
- )
|
|
|
|
- # 把 `文本剪贴板` 贴在视频上
|
|
|
|
- video_with_subtitles = editor.CompositeVideoClip([final_clip, text_clip])
|
|
|
|
-
|
|
|
|
- # 生成视频
|
|
|
|
- video_with_subtitles.write_videofile(output_path, codec='libx264', fps=24)
|
|
|
|
- if os.path.isfile(output_path):
|
|
|
|
- Common.logger().info("视频生成成功!生成路径为:", output_path)
|
|
|
|
- return included_videos
|
|
|
|
- else:
|
|
|
|
- Common.logger().info("视频生成失败,请检查代码和文件路径。")
|
|
|
|
- return ""
|
|
|
|
|
|
+
|
|
|
|
+ final_clip = editor.concatenate_videoclips(final_clips)
|
|
|
|
+ final_clip = final_clip.set_audio(mp3)
|
|
|
|
+
|
|
|
|
+ # 统一设置视频分辨率
|
|
|
|
+ final_width = 480
|
|
|
|
+ final_height = 720
|
|
|
|
+ final_clip = final_clip.resize((final_width, final_height))
|
|
|
|
+
|
|
|
|
+ # 设置背景色
|
|
|
|
+ color_clip = editor.ColorClip(size=(final_width, 120), color=(255, 255, 0)).set_duration(duration_limit)
|
|
|
|
+ final_clip = editor.CompositeVideoClip(
|
|
|
|
+ [final_clip, color_clip.set_position(("center", final_height - 100))])
|
|
|
|
+
|
|
|
|
+ # 处理SRT字幕文件
|
|
|
|
+ Common.logger().info(f"处理SRT字幕文件")
|
|
|
|
+ subtitle_file = f"./video_stitching/video/{srt}.srt"
|
|
|
|
+ if os.path.isfile(subtitle_file):
|
|
|
|
+ with open(subtitle_file, 'r') as file:
|
|
|
|
+ subtitles = file.read().strip().split('\n\n')
|
|
|
|
+ # 从SRT字幕文件中获取字幕
|
|
|
|
+ subtitle_clips = []
|
|
|
|
+ for subtitle in subtitles:
|
|
|
|
+ # 按行分割字幕内容
|
|
|
|
+ subtitle_lines = subtitle.strip().split('\n')
|
|
|
|
+ # 提取时间轴信息和字幕文本
|
|
|
|
+ if len(subtitle_lines) >= 3:
|
|
|
|
+ times, text = subtitle_lines[1], '\n'.join(subtitle_lines[2:])
|
|
|
|
+ start, end = map(cls.srt_to_seconds, times.split(' --> '))
|
|
|
|
+ start = editor.cvsecs(start)
|
|
|
|
+ end = editor.cvsecs(end)
|
|
|
|
+ text = cls.split_text(text, 10)
|
|
|
|
+
|
|
|
|
+ sub = editor.TextClip(text, font="/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
|
|
|
|
+ fontsize=30, color="black").set_duration(end - start).set_start(
|
|
|
|
+ start).set_position(
|
|
|
|
+ ("center", final_height - 80)).set_opacity(0.8)
|
|
|
|
+ subtitle_clips.append(sub)
|
|
|
|
+
|
|
|
|
+ # 将字幕添加到视频上
|
|
|
|
+ video_with_subtitles = editor.CompositeVideoClip([final_clip] + subtitle_clips)
|
|
|
|
+ else:
|
|
|
|
+ text_clip = (
|
|
|
|
+ editor.TextClip("分享、转发给群友", font="/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
|
|
|
|
+ fontsize=30, color="black").
|
|
|
|
+ set_position(("center", final_height - 80)).
|
|
|
|
+ set_duration(duration_limit).
|
|
|
|
+ set_opacity(0.8)
|
|
|
|
+ )
|
|
|
|
+ # 把 `文本剪贴板` 贴在视频上
|
|
|
|
+ video_with_subtitles = editor.CompositeVideoClip([final_clip, text_clip])
|
|
|
|
+
|
|
|
|
+ # 生成视频
|
|
|
|
+ Common.logger().info(f"开始生成视频")
|
|
|
|
+ video_with_subtitles.write_videofile(output_path, codec='libx264', fps=24, temp_audiofile="temp-audio.m4a",
|
|
|
|
+ remove_temp=True, audio_codec="aac")
|
|
|
|
+
|
|
|
|
+ if os.path.isfile(output_path):
|
|
|
|
+ Common.logger().info("视频生成成功!生成路径为:", output_path)
|
|
|
|
+ return included_videos
|
|
|
|
+ else:
|
|
|
|
+ Common.logger().info("视频生成失败,请检查代码和文件路径。")
|
|
|
|
+ return ""
|
|
|
|
|
|
|
|
|
|
|
|
|