|
@@ -108,7 +108,121 @@ class FFmpeg():
|
|
|
str(pw_duration), '-pix_fmt', 'yuv420p', '-c:a', 'aac', '-strict', 'experimental', '-shortest',
|
|
|
'-vf', f"scale=320x480,{background_cmd},{subtitle_cmd}", pw_path]
|
|
|
subprocess.run(ffmpeg_cmd)
|
|
|
- return pw_path
|
|
|
+ return pw_path
|
|
|
+
|
|
|
+
|
|
|
+ """
|
|
|
+ 设置统一格式拼接视频
|
|
|
+ """
|
|
|
+ @classmethod
|
|
|
+ def concatenate_videos(cls, video_files, concatenated_video_path):
|
|
|
+ # 拼接视频
|
|
|
+ VIDEO_COUNTER = 0
|
|
|
+ FF_INPUT = ""
|
|
|
+ FF_SCALE = ""
|
|
|
+ FF_FILTER = ""
|
|
|
+ ffmpeg_cmd = ["ffmpeg"]
|
|
|
+ for videos in video_files:
|
|
|
+ # 添加输入文件
|
|
|
+ FF_INPUT += f" -i {videos}"
|
|
|
+ # 为每个视频文件统一长宽,并设置SAR(采样宽高比)
|
|
|
+ FF_SCALE += f"[{VIDEO_COUNTER}:v]scale=320x480,setsar=1[v{VIDEO_COUNTER}];"
|
|
|
+ # 为每个视频文件创建一个输入流,并添加到-filter_complex参数中
|
|
|
+ FF_FILTER += f"[v{VIDEO_COUNTER}][{VIDEO_COUNTER}:a]"
|
|
|
+ # 增加视频计数器
|
|
|
+ VIDEO_COUNTER += 1
|
|
|
+ # 构建最终的FFmpeg命令
|
|
|
+ ffmpeg_cmd.extend(FF_INPUT.split())
|
|
|
+ ffmpeg_cmd.extend(["-filter_complex", f"{FF_SCALE}{FF_FILTER}concat=n={VIDEO_COUNTER}:v=1:a=1[v][a]",
|
|
|
+ "-map", "[v]", "-map", "[a]", concatenated_video_path])
|
|
|
+ subprocess.run(ffmpeg_cmd)
|
|
|
+
|
|
|
+ return concatenated_video_path
|
|
|
+
|
|
|
+
|
|
|
+ """
|
|
|
+ 单个视频拼接
|
|
|
+ """
|
|
|
+ @classmethod
|
|
|
+ def single_video(cls):
|
|
|
+ text_ptah = cls.bk_text_folders(mark)
|
|
|
+ video_files = cls.concat_videos_with_subtitles(videos, audio_duration, platform, mark)
|
|
|
+ with open(text_ptah, 'w') as f:
|
|
|
+ for file in video_files:
|
|
|
+ f.write(f"file '{file}'\n")
|
|
|
+ if video_files == "":
|
|
|
+ return ""
|
|
|
+ if os.path.exists(s_path):
|
|
|
+ # subtitle_cmd = f"subtitles={s_path}:force_style='Fontsize=11,Fontname=Hiragino Sans GB,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000'"
|
|
|
+ subtitle_cmd = f"subtitles={s_path}:force_style='Fontsize=12,Fontname=wqy-zenhei,Bold=1,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000'"
|
|
|
+ else:
|
|
|
+ # subtitle_cmd = "drawtext=text='分享、转发给群友':fontsize=28:fontcolor=black:x=(w-text_w)/2:y=h-text_h-15"
|
|
|
+ subtitle_cmd = "drawtext=text='分享、转发给群友':x=(w-text_w)/2:y=h-text_h-15:fontsize=28:fontcolor=black:fontfile=/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc"
|
|
|
+ # 背景色参数
|
|
|
+ background_cmd = "drawbox=y=ih-65:color=yellow@1.0:width=iw:height=0:t=fill"
|
|
|
+ # 多线程数
|
|
|
+ num_threads = 4
|
|
|
+ # 构建 FFmpeg 命令,生成视频
|
|
|
+ ffmpeg_cmd_oss = [
|
|
|
+ "ffmpeg",
|
|
|
+ "-f", "concat",
|
|
|
+ "-safe", "0",
|
|
|
+ "-i", f"{text_ptah}", # 视频文件列表
|
|
|
+ "-i", audio_video, # 音频文件
|
|
|
+ "-c:v", "libx264",
|
|
|
+ "-c:a", "aac",
|
|
|
+ "-threads", str(num_threads),
|
|
|
+ "-vf", f"scale=320x480,{background_cmd},{subtitle_cmd}", # 添加背景色和字幕
|
|
|
+ "-t", str(int(audio_duration)), # 保持与音频时长一致
|
|
|
+ "-map", "0:v:0", # 映射第一个输入的视频流
|
|
|
+ "-map", "1:a:0", # 映射第二个输入的音频流
|
|
|
+ "-y", # 覆盖输出文件
|
|
|
+ v_oss_path
|
|
|
+ ]
|
|
|
+ try:
|
|
|
+ subprocess.run(ffmpeg_cmd_oss)
|
|
|
+ print("视频处理完成!")
|
|
|
+ if os.path.isfile(text_ptah):
|
|
|
+ os.remove(text_ptah)
|
|
|
+ except subprocess.CalledProcessError as e:
|
|
|
+ print(f"视频处理失败:{e}")
|
|
|
+ print(f"{mark}:视频拼接成功啦~~~")
|
|
|
+ return video_files
|
|
|
+
|
|
|
+ # 计算需要拼接的视频
|
|
|
+ @classmethod
|
|
|
+ def concat_videos_with_subtitles(cls, videos, audio_duration, platform, mark):
|
|
|
+ # 计算视频文件列表总时长
|
|
|
+ if platform == "baokuai":
|
|
|
+ total_video_duration = sum(cls.get_video_duration(video_file) for video_file in videos)
|
|
|
+ else:
|
|
|
+ total_video_duration = sum(cls.get_video_duration(video_file[3]) for video_file in videos)
|
|
|
+ if platform == "koubo" or platform == "zhannei" or platform == "baokuai":
|
|
|
+ # 视频时长大于音频时长
|
|
|
+ if total_video_duration > audio_duration:
|
|
|
+ return videos
|
|
|
+ # 计算音频秒数与视频秒数的比率,然后加一得到需要的视频数量
|
|
|
+ video_audio_ratio = audio_duration / total_video_duration
|
|
|
+ videos_needed = int(video_audio_ratio) + 2
|
|
|
+ trimmed_video_list = videos * videos_needed
|
|
|
+ return trimmed_video_list
|
|
|
+ else:
|
|
|
+ # 如果视频总时长小于音频时长,则不做拼接
|
|
|
+ if total_video_duration < audio_duration:
|
|
|
+ return ""
|
|
|
+ # 如果视频总时长大于音频时长,则截断视频
|
|
|
+ trimmed_video_list = []
|
|
|
+ remaining_duration = audio_duration
|
|
|
+ for video_file in videos:
|
|
|
+ video_duration = cls.get_video_duration(video_file[3])
|
|
|
+ if video_duration <= remaining_duration:
|
|
|
+ # 如果视频时长小于或等于剩余时长,则将整个视频添加到列表中
|
|
|
+ trimmed_video_list.append(video_file)
|
|
|
+ remaining_duration -= video_duration
|
|
|
+ else:
|
|
|
+ trimmed_video_list.append(video_file)
|
|
|
+ break
|
|
|
+ return trimmed_video_list
|
|
|
|
|
|
|
|
|
|