You've already forked FrameTour-RenderWorker
perf(render_video): 优化视频编码的关键帧间隔策略
- 根据视频总帧数动态计算 GOP 大小,避免关键帧过多 - 短视频使用全部帧数作为 GOP,确保只在开头有关键帧 - 正常视频保持 2 秒一个关键帧的策略 - 添加强制第一帧为关键帧的设置 - 优化关键帧最小间隔参数,提升编码效率
This commit is contained in:
@@ -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')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user