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

使用libavcodec/libavformat编码多流时的PTS/DTS问题排查

解决FFmpeg编码MOV时DTS非单调递增的问题

问题原因

你手动给AVPacket设置DTS的方式存在两个核心问题:

  1. MPEG2编码器本身会根据帧类型(I/P/B帧)生成正确的DTS/PTS,手动覆盖会破坏编码器的时间戳逻辑;
  2. 你试图跨流(视频用偶数DTS、音频用奇数DTS)强制交错,但MOV封装要求每个独立流的DTS必须单调递增,这种跨流的DTS分配会导致单一流内部的DTS顺序混乱。

解决步骤

1. 移除手动设置的DTS和不必要标志

不要手动设置videoPkt.dts、audioPkt.dts,也不要随意添加AV_PKT_FLAG_KEY(编码器会自动为关键帧设置该标志)。

2. 正确转换时间戳

编码器输出的Packet时间戳基于自身的time_base,需要转换为输出流的time_base后再写入封装器,使用av_packet_rescale_ts完成转换。

3. 修正后的代码示例

视频编码部分

// 按编码器time_base递增pts,假设fps为25,每帧+1对应1/25秒
videoFrame->pts = frameCounter;

if(avcodec_send_frame(videoContext, videoFrame) < 0)
{
    std::cout << "Failed to send video frame " << frameCounter << std::endl;
    return;
}

AVPacket videoPkt;
av_init_packet(&videoPkt);
videoPkt.data = nullptr;
videoPkt.size = 0;
videoPkt.stream_index = 0;

// 注意:avcodec_receive_packet可能返回多个packet(比如B帧),需循环接收
while(avcodec_receive_packet(videoContext, &videoPkt) == 0)
{
    // 将时间戳从编码器time_base转换为输出流time_base
    av_packet_rescale_ts(&videoPkt, videoContext->time_base, outputFormatContext->streams[0]->time_base);
    if(av_interleaved_write_frame(outputFormatContext, &videoPkt) != 0)
    {
        std::cout << "Failed to write video packet" << std::endl;
    }
    av_packet_unref(&videoPkt);
}

音频编码部分

// 音频pts按编码器time_base递增,比如采样率48000,每帧含1024样本,则每次+1024
audioFrame->pts = audioFrameCounter;

if(avcodec_send_frame(audioContext, audioFrame) < 0)
{
    std::cout << "Failed to send audio frame " << audioFrameCounter << std::endl;
    return;
}

AVPacket audioPkt;
av_init_packet(&audioPkt);
audioPkt.data = nullptr;
audioPkt.size = 0;
audioPkt.stream_index = 1;

while(avcodec_receive_packet(audioContext, &audioPkt) == 0)
{
    av_packet_rescale_ts(&audioPkt, audioContext->time_base, outputFormatContext->streams[1]->time_base);
    if(av_interleaved_write_frame(outputFormatContext, &audioPkt) != 0)
    {
        std::cout << "Failed to write audio packet" << std::endl;
    }
    av_packet_unref(&audioPkt);
}

4. 额外注意事项

  • 音视频的time_base要分别正确设置:视频编码器time_base设为AVRational{1, fps},音频编码器time_base设为AVRational{1, sample_rate};
  • 依赖av_interleaved_write_frame自动处理音视频帧的交错,无需手动干预时间戳的跨流顺序;
  • 确保每个流的pts是连续递增的,视频按帧计数递增,音频按样本数递增。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:25:33