|
@@ -235,51 +235,63 @@ class AgcVidoe():
|
|
video_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/"
|
|
video_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/"
|
|
# srt 目录
|
|
# srt 目录
|
|
s_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/srt/"
|
|
s_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/srt/"
|
|
- # txt 目录
|
|
|
|
- t_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/txt/"
|
|
|
|
# oss 目录
|
|
# oss 目录
|
|
v_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/oss/"
|
|
v_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/oss/"
|
|
|
|
|
|
-
|
|
|
|
if not os.path.exists(video_path_url):
|
|
if not os.path.exists(video_path_url):
|
|
os.makedirs(video_path_url)
|
|
os.makedirs(video_path_url)
|
|
if not os.path.exists(s_path_url):
|
|
if not os.path.exists(s_path_url):
|
|
os.makedirs(s_path_url)
|
|
os.makedirs(s_path_url)
|
|
- if not os.path.exists(t_path_url):
|
|
|
|
- os.makedirs(t_path_url)
|
|
|
|
if not os.path.exists(v_path_url):
|
|
if not os.path.exists(v_path_url):
|
|
os.makedirs(v_path_url)
|
|
os.makedirs(v_path_url)
|
|
# srt 文件地址
|
|
# srt 文件地址
|
|
s_path = s_path_url + mark + ".srt"
|
|
s_path = s_path_url + mark + ".srt"
|
|
- # txt 文件地址
|
|
|
|
- t_path = t_path_url + mark + ".txt"
|
|
|
|
# 最终生成视频地址
|
|
# 最终生成视频地址
|
|
v_path = v_path_url + mark + ".mp4"
|
|
v_path = v_path_url + mark + ".mp4"
|
|
|
|
+ v_oss_path = v_path_url + mark + "oss.mp4"
|
|
|
|
+ if os.path.isfile(v_oss_path):
|
|
|
|
+ os.remove(v_oss_path)
|
|
if os.path.isfile(v_path):
|
|
if os.path.isfile(v_path):
|
|
os.remove(v_path)
|
|
os.remove(v_path)
|
|
- if os.path.isfile(t_path):
|
|
|
|
- os.remove(t_path)
|
|
|
|
if os.path.isfile(s_path):
|
|
if os.path.isfile(s_path):
|
|
os.remove(s_path)
|
|
os.remove(s_path)
|
|
# 清空所有mp4数据
|
|
# 清空所有mp4数据
|
|
cls.clear_mp4_files(video_path_url)
|
|
cls.clear_mp4_files(video_path_url)
|
|
- return s_path, t_path, v_path, video_path_url
|
|
|
|
|
|
+ return s_path, v_path, video_path_url, v_oss_path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 视频拼接
|
|
# 视频拼接
|
|
@classmethod
|
|
@classmethod
|
|
- def concatenate_videos(cls, videos, audio_duration, audio_video, platform, s_path, v_path, mark, t_path):
|
|
|
|
|
|
+ def concatenate_videos(cls, videos, audio_duration, audio_video, platform, s_path, v_path, mark, v_oss_path ):
|
|
|
|
+
|
|
video_files = cls.concat_videos_with_subtitles(videos, audio_duration, platform, mark)
|
|
video_files = cls.concat_videos_with_subtitles(videos, audio_duration, platform, mark)
|
|
Common.logger("video").info(f"{mark}的{platform}渠道待生成视频为:{video_files}")
|
|
Common.logger("video").info(f"{mark}的{platform}渠道待生成视频为:{video_files}")
|
|
if video_files == "":
|
|
if video_files == "":
|
|
return ""
|
|
return ""
|
|
print(f"{mark}的{platform}:开始拼接视频喽~~~")
|
|
print(f"{mark}的{platform}:开始拼接视频喽~~~")
|
|
Common.logger("video").info(f"{mark}的{platform}:开始拼接视频喽~~~")
|
|
Common.logger("video").info(f"{mark}的{platform}:开始拼接视频喽~~~")
|
|
- # 将使用视频写入文件中
|
|
|
|
- with open(f'{t_path}', 'w') as f:
|
|
|
|
- for video_file in video_files:
|
|
|
|
- f.write(f"file '{video_file[3]}'\n")
|
|
|
|
|
|
+ VIDEO_COUNTER = 0
|
|
|
|
+ # 初始化FFmpeg的-filter_complex参数
|
|
|
|
+ FF_INPUT = ""
|
|
|
|
+ FF_SCALE = ""
|
|
|
|
+ FF_FILTER = ""
|
|
|
|
+ ffmpeg_cmd = ["ffmpeg"]
|
|
|
|
+ for videos in video_files:
|
|
|
|
+ print(videos)
|
|
|
|
+ # 添加输入文件
|
|
|
|
+ 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]", v_path])
|
|
|
|
+ subprocess.run(ffmpeg_cmd)
|
|
|
|
|
|
# 字幕参数
|
|
# 字幕参数
|
|
if os.path.exists(s_path):
|
|
if os.path.exists(s_path):
|
|
@@ -292,44 +304,27 @@ class AgcVidoe():
|
|
|
|
|
|
# 背景色参数
|
|
# 背景色参数
|
|
background_cmd = "drawbox=y=ih-65:color=yellow@1.0:width=iw:height=0:t=fill"
|
|
background_cmd = "drawbox=y=ih-65:color=yellow@1.0:width=iw:height=0:t=fill"
|
|
- # 分辨率参数
|
|
|
|
- resolution_cmd = "-s", "320x480"
|
|
|
|
# 多线程数
|
|
# 多线程数
|
|
num_threads = 8
|
|
num_threads = 8
|
|
# 构建 FFmpeg 命令,生成视频
|
|
# 构建 FFmpeg 命令,生成视频
|
|
- ffmpeg_cmd = [
|
|
|
|
|
|
+ ffmpeg_cmd_oss = [
|
|
"ffmpeg",
|
|
"ffmpeg",
|
|
- "-f", "concat",
|
|
|
|
- "-safe", "0",
|
|
|
|
- "-i", f"{t_path}", # 视频文件列表
|
|
|
|
|
|
+ "-i", v_path, # 视频文件列表
|
|
"-i", audio_video, # 音频文件
|
|
"-i", audio_video, # 音频文件
|
|
- "-pix_fmt", "yuv420p",
|
|
|
|
- "-movflags", "faststart",
|
|
|
|
- "-keyint_min", str(30),
|
|
|
|
- "-g", str(60),
|
|
|
|
- "-sc_threshold", "0",
|
|
|
|
- "-strict", "experimental",
|
|
|
|
|
|
+ "-c:v", "libx264", # 复制视频流
|
|
|
|
+ "-c:a", "aac", # 编码音频流为AAC
|
|
"-threads", str(num_threads),
|
|
"-threads", str(num_threads),
|
|
- "-c:v", "libx264",
|
|
|
|
- "-c:a", "aac",
|
|
|
|
- "-vf", f"scale=320x480,{background_cmd},{subtitle_cmd}", # 添加背景色和字幕
|
|
|
|
- *resolution_cmd, # 添加分辨率参数
|
|
|
|
- "-b:v", "5M", # 设置可变比特率
|
|
|
|
- "-maxrate", "10M", # 设置最大比特率
|
|
|
|
- "-bufsize", "5M", # 设置缓冲大小
|
|
|
|
- "-crf", "22", # 设置CRF(恒定质量)
|
|
|
|
- "-r", "30", # 设置帧率为30帧每秒
|
|
|
|
- "-vsync", "vfr", # 设置视频同步策略为可变帧率
|
|
|
|
|
|
+ "-vf", f"{background_cmd},{subtitle_cmd}", # 添加背景色和字幕
|
|
"-t", str(int(audio_duration)), # 保持与音频时长一致
|
|
"-t", str(int(audio_duration)), # 保持与音频时长一致
|
|
"-map", "0:v:0", # 映射第一个输入的视频流
|
|
"-map", "0:v:0", # 映射第一个输入的视频流
|
|
"-map", "1:a:0", # 映射第二个输入的音频流
|
|
"-map", "1:a:0", # 映射第二个输入的音频流
|
|
"-y", # 覆盖输出文件
|
|
"-y", # 覆盖输出文件
|
|
- v_path
|
|
|
|
|
|
+ v_oss_path
|
|
]
|
|
]
|
|
- # 构建 FFmpeg 命令,添加字幕
|
|
|
|
- # 执行 FFmpeg 命令
|
|
|
|
try:
|
|
try:
|
|
subprocess.run(ffmpeg_cmd, check=True)
|
|
subprocess.run(ffmpeg_cmd, check=True)
|
|
|
|
+ if os.path.isfile(v_path):
|
|
|
|
+ subprocess.run(ffmpeg_cmd_oss, check=True)
|
|
print("视频处理完成!")
|
|
print("视频处理完成!")
|
|
except subprocess.CalledProcessError as e:
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"视频处理失败:{e}")
|
|
print(f"视频处理失败:{e}")
|
|
@@ -361,7 +356,7 @@ class AgcVidoe():
|
|
|
|
|
|
|
|
|
|
# 如果没有该文件目录则创建,有文件目录的话 则删除文件
|
|
# 如果没有该文件目录则创建,有文件目录的话 则删除文件
|
|
- s_path, t_path, v_path, video_path_url= cls.create_folders(mark)
|
|
|
|
|
|
+ s_path, v_path, video_path_url, v_oss_path = cls.create_folders(mark)
|
|
|
|
|
|
kb_count = int(result[1][1])
|
|
kb_count = int(result[1][1])
|
|
channel = ['douyin', 'kuaishou', 'koubo']
|
|
channel = ['douyin', 'kuaishou', 'koubo']
|
|
@@ -410,7 +405,7 @@ class AgcVidoe():
|
|
# 获取音频秒数
|
|
# 获取音频秒数
|
|
audio_duration = cls.get_audio_duration(audio_video)
|
|
audio_duration = cls.get_audio_duration(audio_video)
|
|
Common.logger("video").info(f"{mark}的{platform}渠道获取需要拼接的音频秒数为:{audio_duration}")
|
|
Common.logger("video").info(f"{mark}的{platform}渠道获取需要拼接的音频秒数为:{audio_duration}")
|
|
- video_files = cls.concatenate_videos(videos, audio_duration, audio_video, platform, s_path, v_path, mark, t_path)
|
|
|
|
|
|
+ video_files = cls.concatenate_videos(videos, audio_duration, audio_video, platform, s_path, v_path, mark, v_oss_path)
|
|
if video_files == "":
|
|
if video_files == "":
|
|
Common.logger("video").info(f"{mark}的{platform}渠道使用拼接视频为空")
|
|
Common.logger("video").info(f"{mark}的{platform}渠道使用拼接视频为空")
|
|
return ""
|
|
return ""
|
|
@@ -429,7 +424,7 @@ class AgcVidoe():
|
|
return ""
|
|
return ""
|
|
# 上传 oss
|
|
# 上传 oss
|
|
Common.logger("video").info(f"{mark}的{platform}渠道上传到 OSS 生成视频id为:{oss_id}")
|
|
Common.logger("video").info(f"{mark}的{platform}渠道上传到 OSS 生成视频id为:{oss_id}")
|
|
- oss_object_key = Oss.stitching_sync_upload_oss(v_path, oss_id)
|
|
|
|
|
|
+ oss_object_key = Oss.stitching_sync_upload_oss(v_oss_path, oss_id)
|
|
status = oss_object_key.get("status")
|
|
status = oss_object_key.get("status")
|
|
if status == 200:
|
|
if status == 200:
|
|
# 获取 oss 视频地址
|
|
# 获取 oss 视频地址
|