|
@@ -243,62 +243,12 @@ class FFmpeg():
|
|
|
return int(duration)
|
|
|
return 0
|
|
|
|
|
|
- """
|
|
|
- 生成片尾视频
|
|
|
- """
|
|
|
- @classmethod
|
|
|
- def pw_video(cls, jpg_path, file_path, pw_mp3_path, pw_srt):
|
|
|
- # 添加音频到图片
|
|
|
- """
|
|
|
- jpg_url 图片地址
|
|
|
- pw_video 提供的片尾视频
|
|
|
- pw_duration 提供的片尾视频时长
|
|
|
- new_video_path 视频位置
|
|
|
- subtitle_cmd 字幕
|
|
|
- pw_url 生成视频地址
|
|
|
- :return:
|
|
|
- """
|
|
|
- pw_srt_path = file_path + 'pw_video.srt'
|
|
|
- with open(pw_srt_path, 'w') as f:
|
|
|
- f.write(pw_srt)
|
|
|
- pw_url_path = file_path + 'pw_video.mp4'
|
|
|
- try:
|
|
|
- pw_duration = cls.get_mp3_duration(pw_mp3_path)
|
|
|
- if pw_duration == 0:
|
|
|
- return pw_url_path
|
|
|
- time.sleep(2)
|
|
|
- # 添加字幕 wqy-zenhei Hiragino Sans GB
|
|
|
- height = 1080
|
|
|
- margin_v = int(height) // 8 # 可根据需要调整字幕和背景之间的距离
|
|
|
- subtitle_cmd = f"subtitles={pw_srt_path}:force_style='Fontsize=13,Fontname=wqy-zenhei,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000,Bold=1,MarginV={margin_v}'"
|
|
|
- bg_position_offset = (int(360) - 360 // 8) / 1.75
|
|
|
- background_cmd = f"drawbox=y=(ih-{int(360)}/2-{bg_position_offset}):color=yellow@1.0:width=iw:height={int(360)}/4:t=fill"
|
|
|
-
|
|
|
- cls.asyncio_run_subprocess([
|
|
|
- 'ffmpeg',
|
|
|
- '-loop', '1',
|
|
|
- '-i', jpg_path, # 输入的图片文件
|
|
|
- '-i', pw_mp3_path, # 输入的音频文件
|
|
|
- '-c:v', 'libx264', # 视频编码格式
|
|
|
- '-t', str(pw_duration), # 输出视频的持续时间,与音频持续时间相同
|
|
|
- '-pix_fmt', 'yuv420p', # 像素格式
|
|
|
- '-c:a', 'aac', # 音频编码格式
|
|
|
- '-strict', 'experimental', # 使用实验性编码器
|
|
|
- '-shortest', # 确保输出视频的长度与音频一致
|
|
|
- '-vf', f"{background_cmd},{subtitle_cmd}", # 视频过滤器,设置分辨率和其他过滤器
|
|
|
- pw_url_path # 输出的视频文件路径
|
|
|
- ], timeout=500)
|
|
|
- if os.path.exists(pw_srt_path):
|
|
|
- os.remove(pw_srt_path)
|
|
|
- return pw_url_path
|
|
|
- except Exception as e:
|
|
|
- return pw_url_path
|
|
|
|
|
|
"""
|
|
|
生成片尾视频
|
|
|
"""
|
|
|
@classmethod
|
|
|
- def nrfx_pw_video(cls, jpg_path, file_path, pw_mp3_path, pw_srt):
|
|
|
+ def pw_video(cls, jpg_path, file_path, pw_mp3_path, pw_srt):
|
|
|
# 添加音频到图片
|
|
|
"""
|
|
|
jpg_url 图片地址
|
|
@@ -324,27 +274,43 @@ class FFmpeg():
|
|
|
subtitle_cmd = f"subtitles={pw_srt_path}:force_style='Fontsize=13,Fontname=wqy-zenhei,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000,Bold=1,MarginV={margin_v}'"
|
|
|
bg_position_offset = (int(360) - 360//8) / 1.75
|
|
|
background_cmd = f"drawbox=y=(ih-{int(360)}/2-{bg_position_offset}):color=yellow@1.0:width=iw:height={int(360)}/4:t=fill"
|
|
|
- pw_path_txt = file_path + 'pw_path_video.txt'
|
|
|
- with open(pw_path_txt, 'w') as f:
|
|
|
- f.write(f"file '{jpg_path}'\n")
|
|
|
- cls.asyncio_run_subprocess([
|
|
|
- "ffmpeg",
|
|
|
- "-f", "concat",
|
|
|
- "-safe", "0",
|
|
|
- "-i", f"{pw_path_txt}", # 视频序列输入的文本文件
|
|
|
- "-i", pw_mp3_path, # 音频文件
|
|
|
- "-c:v", "libx264", # 视频编码格式
|
|
|
- "-t", str(pw_duration), # 输出视频的持续时间
|
|
|
- "-c:a", "aac", # 音频编码格式
|
|
|
- "-b:v", "260k", # 视频比特率
|
|
|
- "-b:a", "96k", # 音频比特率
|
|
|
- "-threads", "2", # 线程数
|
|
|
- "-vf", f"{background_cmd},{subtitle_cmd}", # 视频过滤器(背景和字幕)
|
|
|
- "-map", "0:v:0", # 映射视频流来自第一个输入文件(视频)
|
|
|
- "-map", "1:a:0", # 映射音频流来自第二个输入文件(音频)
|
|
|
- "-y", # 强制覆盖输出文件
|
|
|
- pw_url_path # 输出文件路径
|
|
|
- ], timeout=500)
|
|
|
+ if "mp4" in jpg_path:
|
|
|
+ pw_path_txt = file_path + 'pw_path_video.txt'
|
|
|
+ with open(pw_path_txt, 'w') as f:
|
|
|
+ f.write(f"file '{jpg_path}'\n")
|
|
|
+ cls.asyncio_run_subprocess([
|
|
|
+ "ffmpeg",
|
|
|
+ "-f", "concat",
|
|
|
+ "-safe", "0",
|
|
|
+ "-i", f"{pw_path_txt}", # 视频序列输入的文本文件
|
|
|
+ "-i", pw_mp3_path, # 音频文件
|
|
|
+ "-c:v", "libx264", # 视频编码格式
|
|
|
+ "-t", str(pw_duration), # 输出视频的持续时间
|
|
|
+ "-c:a", "aac", # 音频编码格式
|
|
|
+ "-b:v", "260k", # 视频比特率
|
|
|
+ "-b:a", "96k", # 音频比特率
|
|
|
+ "-threads", "2", # 线程数
|
|
|
+ "-vf", f"{background_cmd},{subtitle_cmd}", # 视频过滤器(背景和字幕)
|
|
|
+ "-map", "0:v:0", # 映射视频流来自第一个输入文件(视频)
|
|
|
+ "-map", "1:a:0", # 映射音频流来自第二个输入文件(音频)
|
|
|
+ "-y", # 强制覆盖输出文件
|
|
|
+ pw_url_path # 输出文件路径
|
|
|
+ ], timeout=500)
|
|
|
+ else:
|
|
|
+ cls.asyncio_run_subprocess([
|
|
|
+ 'ffmpeg',
|
|
|
+ '-loop', '1',
|
|
|
+ '-i', jpg_path, # 输入的图片文件
|
|
|
+ '-i', pw_mp3_path, # 输入的音频文件
|
|
|
+ '-c:v', 'libx264', # 视频编码格式
|
|
|
+ '-t', str(pw_duration), # 输出视频的持续时间,与音频持续时间相同
|
|
|
+ '-pix_fmt', 'yuv420p', # 像素格式
|
|
|
+ '-c:a', 'aac', # 音频编码格式
|
|
|
+ '-strict', 'experimental', # 使用实验性编码器
|
|
|
+ '-shortest', # 确保输出视频的长度与音频一致
|
|
|
+ '-vf', f"{background_cmd},{subtitle_cmd}", # 视频过滤器,设置分辨率和其他过滤器
|
|
|
+ pw_url_path # 输出的视频文件路径
|
|
|
+ ], timeout=500)
|
|
|
if os.path.exists(pw_srt_path):
|
|
|
os.remove(pw_srt_path)
|
|
|
return pw_url_path
|