mtmd: Video input silently fails if MOOV atom is at end of MP4 file

当 MP4 文件的 MOOV 原子位于文件末尾时(ffmpeg 默认输出格式),llama.cpp 的 mtmd 视频输入会静默失败,模型收到 0 帧。优先排查输入视频是否由 ffmpeg 生成且未加 -movflags +faststart ,可先尝试用 ffmpeg 重处理视频。

快速结论:当 MP4 文件的 MOOV 原子位于文件末尾时(ffmpeg 默认输出格式),llama.cpp 的 mtmd 视频输入会静默失败,模型收到 0 帧。优先排查输入视频是否由 ffmpeg 生成且未加 -movflags +faststart,可先尝试用 ffmpeg 重处理视频。

适用环境:llama.cpp 版本 9586(build 76da2450a),GNU 15.2.0,Linux x86_64,使用 mtmd 工具处理视频输入。

最快修复方案:Issue 中已验证的修复是修改 tools/mtmd/mtmd-helper.cpp,在 ffmpeg 命令中加入 -read_ahead_limit -1 参数(仅内存输入模式)。此补丁已由维护者 @ngxson 提交 PR #27596,可在官方合并后更新代码。

注意事项:临时文件方案(写入磁盘)虽可解决但会损耗 SSD 寿命,且 Windows 平台缺少纯内存方案;-read_ahead_limit -1 补丁仅验证了 Linux 构建,Windows/macOS 尚未确认。

问题场景

用户在 Linux 上运行 llama.cpp(版本 9586)的 mtmd 工具,使用本地 MP4 文件作为视频输入时,模型静默收到 0 帧,无任何报错提示。进一步排查发现,所有由 ffmpeg 默认生成的 MP4 文件(MOOV 原子在文件末尾)都会触发此问题。有用户反馈,微信转码的视频可以正常处理,但经 ffmpeg 处理过的视频虽然能输入,长视频分析却接近上下文上限。

报错原文

mtmd: Video input silently fails if MOOV atom is at end of MP4 file

原因分析

ffmpeg 读取 MOOV 原子位于文件末尾的 MP4 文件时,需要可寻址(seekable)的输入流。当前 mtmd 实现通过管道(pipe)将视频数据传给 ffmpeg,管道默认的 read_ahead_limit 为 64KB,而 moov-at-end 的 MP4 文件需要更大的预读范围才能定位到 MOOV 原子,导致 ffmpeg 无法正确解析容器结构,静默返回 0 帧。

可能原因:cache:pipe:0 虽然包装了可寻址的内存缓存,但 read_ahead_limit 限制了向后查找 MOOV 原子的能力。

环境排查

  • llama.cpp 版本:9586(76da2450a)
  • 编译器:GNU 15.2.0,Linux x86_64
  • 操作系统:Linux(Windows 未验证)
  • 确认输入视频是否为 ffmpeg 生成:ffprobe -show_entries format=format_name -of json input.mp4
  • 检查 MOOV 原子位置:ffprobe -v trace -i input.mp4 2>&1 | grep -i moov
  • 确认 mtmd 模型配置(如 Qwen3.6-35b-Q4_K_M)与上下文窗口设置

解决步骤

  1. 临时方案(已验证):用 ffmpeg 重处理视频,将 MOOV 原子移到文件开头:ffmpeg -i input.mp4 -c copy -movflags +faststart output.mp4,然后使用 output.mp4 作为输入。
  2. 补丁修复(推荐):修改 tools/mtmd/mtmd-helper.cpp,在 cmd.push_back("-nostdin") 之后加入:
    if (is_buf_input()) {
        // 默认 read_ahead_limit 为 64KB;moov-at-end MP4 需要更大预读,提升为无限
        cmd.push_back("-read_ahead_limit");
        cmd.push_back("-1");
    }
  3. 等待官方合并:该修复已提交 PR #27596,合并后可更新 llama.cpp 代码。
  4. 备选方案(有损耗):将视频写入临时文件再传给 ffmpeg,替换 ctx->input_buf.assign(buf, buf + len)ctx->path = <临时文件路径>,并在析构函数中清理文件。此方案会写入磁盘,可能影响 SSD 寿命。
  5. 验证补丁有效性:在 Linux 构建上测试 moov-at-end 的 MP4 文件,确认模型能收到正确帧数。

验证方法

使用 ffmpeg 生成一个 MOOV 原子在文件末尾的测试视频(不添加 -movflags +faststart),通过 mtmd 处理并观察输出帧数。若帧数 > 0,说明修复生效。也可用 ffprobe -v trace 确认 MOOV 原子位置后,对比修复前后的输入结果。

参考来源

ggml-org/llama.cpp #24394

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 20096

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注