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

使用Accord.Video.FFMPEG处理长视频时读取帧返回空值求助

问题分析与解决方案

你遇到的问题核心是Accord.Video.FFMPEG返回的FrameCount与视频实际可读取的帧数不匹配,长视频中这种帧计数偏差会被放大,导致循环后期ReadVideoFrame()已经读完所有帧返回null,但你的循环还在基于FrameCount继续执行,最终触发空引用问题。

解决思路

放弃依赖FrameCount控制循环,改为以ReadVideoFrame()的返回值是否为null作为终止条件,精准匹配实际可读帧数量;同时优化帧提取逻辑,避免冗余判断。

优化后的代码示例

using (var vReader = new VideoFileReader())
{
    vReader.Open(files[0]);
    TotalFrame = vReader.FrameCount; // 仅用于统计,不再控制循环
    countin = Convert.ToInt32(TotalFrame / Convert.ToDouble(countAsset));
    Fps = vReader.FrameRate.Value;                                
    int frameIndex = 0;
    int savedCount = 0;
    Bitmap currentFrame;
    Bitmap lastFrame = null;

    // 循环读取所有实际存在的帧,直到返回null
    while ((currentFrame = vReader.ReadVideoFrame()) != null)
    {
        frameIndex++;
        lastFrame = currentFrame;
        
        // 每10帧保存一次
        if (frameIndex % 10 == 0)
        {
            savedCount++;
            currentFrame.Save($@"{dirVideo.FullName}\{savedCount}.jpeg", ImageFormat.Jpeg);
            // 保存后立即释放当前帧资源
            currentFrame.Dispose();
            lastFrame = null;
        }
    }

    // 确保最后一帧即使不是10的倍数也能保存(和原逻辑一致)
    if (lastFrame != null)
    {
        savedCount++;
        lastFrame.Save($@"{dirVideo.FullName}\{savedCount}.jpeg", ImageFormat.Jpeg);
        lastFrame.Dispose();
    }
}

关键改动说明

  1. 循环逻辑调整:用while循环替代for循环,直接以ReadVideoFrame()的返回值判断是否还有帧可读,彻底避免FrameCount不准导致的多读问题。
  2. 资源管理优化:每保存完帧立即释放资源,避免长视频中内存占用过高;同时记录最后一帧,确保符合你原代码中强制保存末尾帧的需求。
  3. 代码简化:用字符串插值替代string.Format,去掉冗余的分支判断,代码更简洁易维护。

额外注意事项

  • 确保目标保存目录存在,可提前添加Directory.CreateDirectory(dirVideo.FullName);避免保存失败。
  • 尝试更新Accord.Video.FFMPEG到最新稳定版,旧版本对部分编码的长视频帧读取存在兼容性bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 07:40:35