diff --git a/handlers/render_video.py b/handlers/render_video.py index 2369522..638b932 100644 --- a/handlers/render_video.py +++ b/handlers/render_video.py @@ -275,12 +275,24 @@ class RenderSegmentVideoHandler(BaseHandler): cmd.extend(['-vf', ','.join(filters)]) + # 计算总帧数,动态调整 GOP + total_frames = int(actual_duration_sec * fps) + if total_frames <= 1: + gop_size = 1 + elif total_frames < fps: + gop_size = total_frames + else: + gop_size = fps * 2 # 正常情况,2 秒一个关键帧 + # 编码参数 cmd.extend([ '-c:v', 'libx264', '-preset', 'fast', '-crf', '18', '-r', str(fps), + '-g', str(gop_size), + '-keyint_min', str(min(gop_size, fps // 2 or 1)), + '-force_key_frames', 'expr:eq(n,0)', '-an', # 无音频 output_file ]) @@ -357,16 +369,28 @@ class RenderSegmentVideoHandler(BaseHandler): fps = output_spec.fps cmd.extend(['-r', str(fps)]) - # GOP 大小(关键帧间隔) - gop_size = fps * 2 # 2秒一个关键帧 - cmd.extend(['-g', str(gop_size)]) - cmd.extend(['-keyint_min', str(gop_size)]) - # 时长(包含 overlap 区域) total_duration_ms = duration_ms + overlap_head_ms + overlap_tail_ms duration_sec = total_duration_ms / 1000.0 cmd.extend(['-t', str(duration_sec)]) + # 动态调整 GOP 大小:对于短视频,GOP 不能大于总帧数 + total_frames = int(duration_sec * fps) + if total_frames <= 1: + gop_size = 1 + elif total_frames < fps: + # 短于 1 秒的视频,使用全部帧数作为 GOP(整个视频只有开头一个关键帧) + gop_size = total_frames + else: + # 正常情况,2 秒一个关键帧 + gop_size = fps * 2 + + cmd.extend(['-g', str(gop_size)]) + cmd.extend(['-keyint_min', str(min(gop_size, fps // 2 or 1))]) + + # 强制第一帧为关键帧 + cmd.extend(['-force_key_frames', 'expr:eq(n,0)']) + # 无音频(视频片段不包含音频) cmd.append('-an')