FFmpeg中如何同时叠加frame_num与timecode动态文本?
问题描述
当同时使用frame_num(帧号1..n)和timecode(时间码hh:mm:ss:frame)属性时,FFmpeg的drawtext文本叠加功能异常:仅timecode会动态递增,frame_num显示为静态文本。如何实现两者的同时动态叠加?
相关命令示例
不生效的命令(仅timecode递增,frame_num为静态)
ffmpeg.exe -hide_banner -nostats ^ -i "video_25fps.mp4" -threads 4 -preset fast ^ -c:v libx264 -profile:v main -level 4.0 -s:v 640x360 -b:v 512k -pix_fmt yuv420p ^ -refs 3 -bf 3 -g 50 -keyint_min 25 -b_strategy 1 -flags +cgop -sc_threshold 0 ^ -movflags "negative_cts_offsets+faststart" ^ -vf "drawtext=fontfile=/fonts/Roboto-Regular.ttf:fontcolor=White:fontsize=38:box=1:boxcolor=black:x=(w-text_w)/2:y=text_h-line_h+60:text='H264\ 640x360\ 512k\ frame\: %{frame_num}\ ':start_number=1:timecode=00\\:00\\:00\\:00:rate=25" ^ -an -sn -t 30 -y output.mp4
仅使用frame_num生效的命令
-vf "drawtext=fontfile=/fonts/Roboto-Regular.ttf:fontcolor=White:fontsize=38:box=1:boxcolor=black:x=(w-text_w)/2:y=text_h-line_h+60:text='H264\ 640x360\ 512k\ frame\: %{frame_num}':start_number=1"
仅使用timecode生效的命令
-vf "drawtext=fontfile=/fonts/Roboto-Regular.ttf:fontcolor=White:fontsize=38:box=1:boxcolor=black:x=(w-text_w)/2:y=text_h-line_h+60:text='H264\ 640x360\ 512k\ ':timecode='00\:00\:00\:00':rate=25"
解决方案
问题根源在于drawtext的参数逻辑:当指定timecode参数时,滤镜会切换到时间码专属模式,此时内置的%{frame_num}变量会被屏蔽,仅渲染timecode内容。要同时显示动态帧号和时间码,需放弃timecode参数,通过表达式手动计算并生成时间码,这样%{frame_num}就能正常动态更新。
针对25fps的视频,修正后的完整命令如下:
ffmpeg.exe -hide_banner -nostats ^ -i "video_25fps.mp4" -threads 4 -preset fast ^ -c:v libx264 -profile:v main -level 4.0 -s:v 640x360 -b:v 512k -pix_fmt yuv420p ^ -refs 3 -bf 3 -g 50 -keyint_min 25 -b_strategy 1 -flags +cgop -sc_threshold 0 ^ -movflags "negative_cts_offsets+faststart" ^ -vf "drawtext=fontfile=/fonts/Roboto-Regular.ttf:fontcolor=White:fontsize=38:box=1:boxcolor=black:x=(w-text_w)/2:y=text_h-line_h+60:text='H264 640x360 512k frame\: %{frame_num} | timecode\: %{eif:floor(t/3600):d+2}:%{eif:floor((t%3600)/60):d+2}:%{eif:floor(t%60):d+2}:%{eif:mod(t*25,25):d+2}':start_number=1" ^ -an -sn -t 30 -y output.mp4
表达式说明
上述命令中生成时间码的表达式基于当前时间t(单位:秒)和帧率25计算:
%{eif:floor(t/3600):d+2}:计算小时数,强制格式化为两位数字(不足补0)%{eif:floor((t%3600)/60):d+2}:计算分钟数,强制格式化为两位数字%{eif:floor(t%60):d+2}:计算秒数,强制格式化为两位数字%{eif:mod(t*25,25):d+2}:计算当前帧在秒内的位置(0-24),强制格式化为两位数字
如果你的视频帧率不是25,只需将所有25替换为对应帧率即可。
内容的提问来源于stack exchange,提问作者Whome
相关产品推荐
相关产品推荐

