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

C+FFmpeg处理音视频流时DTS非单调递增错误解决

FFmpeg转码MP4时DTS非单调递增错误的解决方法

这个错误的核心原因是:MP4封装器要求每个输出流的DTS(解码时间戳)必须严格单调递增,多流共同处理时,若未正确维护各流独立的时间戳基准、未按全局时间顺序输出数据包,就会触发该校验错误。以下是针对性的解决步骤:


1. 为每个输出流维护独立的时间戳偏移基准

视频和音频流的原始时间戳起始点往往不同,转码时需各自重置时间戳基准,确保每个流的时间戳从合理值开始递增:

  • 给每个输出流定义专属的偏移变量,比如在自定义的OutputStream结构体中加入pts_offset、dts_offset和first_pkt标记:
    typedef struct OutputStream {
        AVStream *stream;
        AVCodecContext *codec_ctx;
        int64_t pts_offset;
        int64_t dts_offset;
        int first_pkt; // 标记是否为当前流的第一个数据包
    } OutputStream;
    
  • 处理当前流的第一个数据包时,将其PTS/DTS设为偏移基准,后续数据包的时间戳都减去该基准:
    if (out_stream->first_pkt) {
        out_stream->pts_offset = out_pkt->pts;
        out_stream->dts_offset = out_pkt->dts;
        out_stream->first_pkt = 0;
    }
    out_pkt->pts -= out_stream->pts_offset;
    out_pkt->dts -= out_stream->dts_offset;
    

2. 严格按输出流的时间基准转换时间戳

转码后的数据包不能直接复用解码器输出的时间戳,必须转换为输出流的time_base:

out_pkt->pts = av_rescale_q_rnd(out_pkt->pts, 
                                out_stream->codec_ctx->time_base, 
                                out_stream->stream->time_base, 
                                AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
out_pkt->dts = av_rescale_q_rnd(out_pkt->dts, 
                                out_stream->codec_ctx->time_base, 
                                out_stream->stream->time_base, 
                                AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
out_pkt->duration = av_rescale_q(out_pkt->duration, 
                                 out_stream->codec_ctx->time_base, 
                                 out_stream->stream->time_base);
out_pkt->pos = -1; // 重置位置标记,交给封装器自动处理

3. 按全局时间顺序输出数据包

不能交替处理完视频/音频数据包后直接写入封装器,需要先缓存转码后的所有数据包,再按全局时间戳排序后输出:

  • 用队列存储转码后的数据包,每个数据包携带流索引和全局时间戳(转换为同一时间基准,比如微秒)
  • 每次从队列中取出时间最早的数据包,调用av_interleaved_write_frame写入封装器(该函数也会自动做部分交错处理,但手动排序更可靠)

4. 修正编码器的时间基准设置

确保编码器的time_base配置符合对应流的规范:

  • 视频编码器:通常设置为帧率的倒数
    out_video_codec_ctx->time_base = av_inv_q(in_video_stream->r_frame_rate);
    
  • 音频编码器:设置为采样率的倒数
    out_audio_codec_ctx->time_base = (AVRational){1, out_audio_codec_ctx->sample_rate};
    

5. 重置数据包的流索引

转码后的数据包必须设置正确的stream_index为输出流的索引,而非输入流的索引:

out_pkt->stream_index = out_stream->stream->index;

按上述步骤调整后,每个流的时间戳会保持严格单调递增,同时全局数据包按时间顺序写入封装器,即可解决DTS校验错误。

内容的提问来源于stack exchange,提问作者M.Hakim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 04:26:15