You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FFmpeg转码H264 MP4视频卡顿问题排查求助

Windows下FFmpeg采集编码卡顿排查与音频PTS处理建议

视频卡顿的核心排查方向

1. 采集源的时间戳问题

gdigrab和dshow采集的原始帧经常会出现时间戳无效或不统一的情况——比如dshow的视频帧时间戳可能是系统时钟的微秒,gdigrab可能直接用帧率估算的假时间戳,直接丢给编码器会导致PTS混乱。

  • 打印采集到的AVFrame的pts、pkt_dts字段,确认是否连续且符合29.97fps的间隔(大概每帧33367微秒)。如果原始帧pts是AV_NOPTS_VALUE,得手动基于采集顺序+帧率生成,但别硬套固定间隔,要和实际采集节奏匹配。

2. 滤镜链的配置问题

你用了fps和setpts滤镜,但顺序和参数错了也会出问题:

  • 正确的顺序应该是先fps=fps=29.97强制帧率,再用setpts=PTS-STARTPTS重置起始时间戳,避免开头的时间戳偏移。如果反过来,可能会导致丢帧/重复帧的PTS不连贯。
  • 打印滤镜输出帧的PTS,用av_frame_get_best_effort_timestamp()查看,确保相邻帧的时间差稳定在33367微秒左右。

3. 编码器参数的锅

H264编码器参数没调好,编码速度跟不上采集速度,帧积压就会卡顿:

  • preset别设太“慢”,Windows下libx264用preset=fast或medium就行,平衡质量和速度;
  • 开启thread_count,设成和CPU核心数一致,提升编码效率;
  • 编码器的time_base要和输出流匹配:29.97fps对应的time_base应该是AVRational{1, 30000}(因为30000/1001=29.97),输出流的time_base也要对应上,别搞混单位。

4. 音视频同步问题

哪怕视频帧率显示正常,音频PTS和视频PTS不匹配,播放器会为了同步丢帧/重复帧,表现出来就是卡顿。比如音频PTS涨得太快,播放器会加速视频,看起来就卡;反之则减速卡顿。

音频PTS的正确计算方式

别依赖采集到的音频帧PTS,dshow的音频时间戳经常有偏移或不连续,自己算才靠谱:

  • 维护一个累计采样数的变量,每收到一帧音频,就把frame->nb_samples加进去;
  • PTS公式:pts = (累计采样数 * AV_TIME_BASE) / 采样率,比如采样率44100Hz,每帧1024个采样点,那每帧的PTS增量就是1024 * AV_TIME_BASE / 44100 ≈ 23219微秒;
  • 输出音频流的time_base建议设为AVRational{1, AV_TIME_BASE},编码器的time_base也要对应,最后用av_packet_rescale_ts()把编码后的packet时间戳转换成流的time_base。

代码排查的关键节点

  1. 采集阶段:打印每个采集帧的pts、pkt_dts、duration,确认有没有无效值(比如AV_NOPTS_VALUE),时间间隔是否稳定;
  2. 滤镜处理阶段:打印滤镜输出帧的PTS,看是否连续、符合帧率要求;
  3. 编码阶段:检查编码器输出的AVPacket的pts、dts是否递增,有没有跳变或负数;同时监控编码队列长度,如果一直涨,说明编码速度跟不上,得调参数;
  4. 封装阶段:确认MP4封装时,音视频流的time_base设置正确,编码后的packet已经用av_packet_rescale_ts()转换过时间戳。

快速验证方法

  • 先把滤镜全去掉,直接采集编码,看还卡不卡。如果不卡,说明滤镜链有问题;如果还卡,就查采集或编码器参数;
  • 用FFmpeg命令行测相同的采集源:比如采集桌面用ffmpeg -f gdigrab -framerate 29.97 -i desktop -c:v libx264 -preset fast -crf 23 output.mp4,看命令行生成的视频卡不卡。如果命令行正常,就对比你的代码和命令行的参数差异,肯定是哪里配置不一样。

内容的提问来源于stack exchange,提问作者Expressingx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 16:45:23