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

保存视频帧时出现非单调递增DTS复用器报错问题咨询

解决Accord.Video保存视频时的"Invalid argument"错误(DTS不单调递增)

我帮你拆解这个问题——你遇到的这个错误本质是FFmpeg(Accord.Video底层依赖的库)的视频复用器要求时间戳必须严格单调递增,而你的帧出现了重复的DTS(解码时间戳)值(控制台提示的512 >= 512就是明证),哪怕是相等的DTS也不符合复用器的要求。

先明确报错的核心原因

FFmpeg的复用器对输入帧的时间戳有硬性规则:每一个后续帧的DTS必须严格大于前一帧的DTS,不允许相等,更不允许倒退。你的情况就是某帧的DTS和上一帧完全一样,触发了这个校验逻辑,抛出了Error -22: Invalid argument。

可能的触发场景&对应的解决方案

1. 缓冲区帧的时间戳本身重复

如果你的缓冲区里存在同一时间戳的重复帧,或者时间戳没有按预期递增,就会出问题。解决办法是维护一个记录上一帧DTS的变量,强制保证当前帧DTS严格大于上一帧:

// 初始化时记录上一帧的DTS,设为一个极小值
long lastFrameDts = -1;
// 假设你遍历缓冲区帧的逻辑
foreach (var bufferedFrame in yourFrameBuffer)
{
    long currentDts = bufferedFrame.TimeStamp;
    // 检查当前DTS是否不符合严格递增要求
    if (currentDts <= lastFrameDts)
    {
        // 根据帧率计算合理的递增步长(单位:微秒,Accord.Video要求的时间戳单位)
        int frameRate = (int)yourVideoWriter.FrameRate;
        long step = 1000000 / frameRate;
        // 强制设置为上一帧DTS + 步长
        currentDts = lastFrameDts + step;
    }
    // 写入调整后的帧
    yourVideoWriter.WriteVideoFrame(bufferedFrame.Bitmap, currentDts);
    // 更新上一帧DTS记录
    lastFrameDts = currentDts;
}

2. 时间戳单位搞错了

Accord.Video的WriteVideoFrame方法要求时间戳的单位是微秒,如果你传入的是毫秒、帧序号或者其他单位,就会导致时间戳增长过慢甚至重复。比如你原本的时间戳是毫秒,需要乘以1000转成微秒:

// 假设原时间戳是毫秒,转换为微秒
long correctDts = bufferedFrame.TimeStampInMs * 1000;

3. 帧率设置与时间戳步长不匹配

如果初始化VideoWriter时设置的帧率,和你实际帧的时间戳递增步长不匹配,也容易出现DTS重复的问题。比如帧率设为30fps,那么每帧的DTS应该比前一帧大约33333微秒(1000000 / 30),确保这个步长和你的时间戳增长逻辑一致。

4. 缓冲区存在重复帧

检查你的缓冲区是否意外存入了同一帧(比如重复读取了同一个缓冲区位置),如果是,需要先对缓冲区的帧按时间戳去重,再进行写入操作。

总结

这个问题的核心就是满足FFmpeg复用器的严格单调递增DTS要求,只要保证每一个后续帧的DTS都比前一帧大,就能解决这个错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:51:33