fix: 修复 ffmpeg 合并视频 尺寸不对有黑边的bug
This commit is contained in:
parent
05a4834ec5
commit
e15a9d947b
|
|
@ -514,6 +514,26 @@ class VideoUtils:
|
|||
total_videos = len(media_paths)
|
||||
if total_videos == 0:
|
||||
raise ValueError("没有可以合并的视频源")
|
||||
|
||||
# 自动检测所有视频的宽高和音频流,找出最大值
|
||||
max_width = 0
|
||||
max_height = 0
|
||||
has_audio = []
|
||||
for media_path in media_paths:
|
||||
width, height = await VideoUtils.ffprobe_video_size_async(media_path)
|
||||
max_width = max(max_width, width)
|
||||
max_height = max(max_height, height)
|
||||
# 检查是否有音频流
|
||||
metadata = VideoUtils.ffprobe_media_metadata(media_path)
|
||||
audio_exists = any(stream.codec_type == "audio" for stream in metadata.streams)
|
||||
has_audio.append(audio_exists)
|
||||
logger.info(f"{media_path} - 音频流: {'存在' if audio_exists else '不存在'}")
|
||||
|
||||
# 使用检测到的最大宽高作为目标尺寸
|
||||
target_width = max_width
|
||||
target_height = max_height
|
||||
logger.info(f"检测到最大分辨率: {target_width}x{target_height}")
|
||||
|
||||
if not output_path:
|
||||
output_path = FileUtils.file_path_extend(media_paths[0], "concat")
|
||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||
|
|
@ -523,18 +543,22 @@ class VideoUtils:
|
|||
ffmpeg_cmd.input(input_path)
|
||||
# 2. 统一所有视频的格式、分辨率和帧率
|
||||
for i in range(total_videos):
|
||||
filter_complex.extend(
|
||||
[
|
||||
# 先缩放到统一分辨率,然后设置帧率和格式
|
||||
f"[{i}:v]scale={target_width}:{target_height}:force_original_aspect_ratio=decrease,"
|
||||
f"pad={target_width}:{target_height}:(ow-iw)/2:(oh-ih)/2,"
|
||||
f"setsar=1:1," # 新增强制设置SAR
|
||||
f"fps=30,format=yuv420p[v{i}]",
|
||||
# 修改音频过滤器,确保输出为AAC兼容格式
|
||||
# f"[{i}:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo[a{i}]",
|
||||
f"[{i}:a]aformat=sample_fmts=s16:sample_rates=44100:channel_layouts=stereo[a{i}]",
|
||||
]
|
||||
# 视频流处理
|
||||
filter_complex.append(
|
||||
f"[{i}:v]scale={target_width}:{target_height}:force_original_aspect_ratio=increase,"
|
||||
f"crop={target_width}:{target_height},"
|
||||
f"setsar=1:1,"
|
||||
f"fps=30,format=yuv420p[v{i}]"
|
||||
)
|
||||
# 音频流处理:如果有音频则使用原音频,否则生成静默音频
|
||||
if has_audio[i]:
|
||||
filter_complex.append(
|
||||
f"[{i}:a]aformat=sample_fmts=s16:sample_rates=44100:channel_layouts=stereo[a{i}]"
|
||||
)
|
||||
else:
|
||||
filter_complex.append(
|
||||
f"anullsrc=channel_layout=stereo:sample_rate=44100[a{i}]"
|
||||
)
|
||||
# 3. 准备处理后的视频流和音频流的连接字符串
|
||||
video_streams = "".join(f"[v{i}]" for i in range(total_videos))
|
||||
audio_streams = "".join(f"[a{i}]" for i in range(total_videos))
|
||||
|
|
@ -930,6 +954,20 @@ class VideoUtils:
|
|||
total_videos = len(media_paths)
|
||||
if total_videos == 0:
|
||||
raise ValueError("没有可以合并的视频源")
|
||||
|
||||
# 自动检测所有视频的宽高,找出最大值
|
||||
max_width = 0
|
||||
max_height = 0
|
||||
for media_path in media_paths:
|
||||
width, height = await VideoUtils.ffprobe_video_size_async(media_path)
|
||||
max_width = max(max_width, width)
|
||||
max_height = max(max_height, height)
|
||||
|
||||
# 使用检测到的最大宽高作为目标尺寸
|
||||
target_width = max_width
|
||||
target_height = max_height
|
||||
logger.info(f"检测到最大分辨率: {target_width}x{target_height}")
|
||||
|
||||
if not output_path:
|
||||
output_path = FileUtils.file_path_extend(media_paths[0], "concat_video_only")
|
||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||
|
|
@ -940,10 +978,10 @@ class VideoUtils:
|
|||
# 2. 统一所有视频的格式、分辨率和帧率(仅处理视频流)
|
||||
for i in range(total_videos):
|
||||
filter_complex.append(
|
||||
# 先缩放到统一分辨率,然后设置帧率和格式
|
||||
f"[{i}:v]scale={target_width}:{target_height}:force_original_aspect_ratio=decrease,"
|
||||
f"pad={target_width}:{target_height}:(ow-iw)/2:(oh-ih)/2,"
|
||||
f"setsar=1:1," # 强制设置SAR
|
||||
# 放大到目标尺寸并裁剪,保持不变形
|
||||
f"[{i}:v]scale={target_width}:{target_height}:force_original_aspect_ratio=increase,"
|
||||
f"crop={target_width}:{target_height},"
|
||||
f"setsar=1:1,"
|
||||
f"fps=30,format=yuv420p[v{i}]"
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue