ffprobe - 从文件块获取视频信息

时间:2015-09-06 13:38:50

标签: ffmpeg mp4 ffprobe

在我的网站上,用户可以上传视频,这些视频即时加密并存储在另一台服务器上。我想存储视频比特率,帧率等,但我没有直接访问它们,我不能只使用以下命令:

ffprobe -show_streams -i file.mp4

我尝试在我的服务器上保存最后一个块,其中包含moov atom,但是ffprobe正在输出:

Format mov,mp4,m4a,3gp,3g2,mj2 detected only with low score of 1, misdetection possible!
moov atom not found
C:\file.mp4: Invalid data found when processing input

我检查并截断至少一个字节导致这个,虽然moov原子是完整的。

从包含moov atom的文件片段中获取视频元数据的正确方法是什么?如何从mdata原子获取信息呢?

1 个答案:

答案 0 :(得分:7)

我不认为ffmpeg解析器知道如何找到分块文件的moov原子。它按块解析(读取或跳过)mp4文件块,直到它找到moov原子,如果你切断了开头的一部分,块结构被破坏,因此它不会找到moov原子。

一种可能的解决方案是检测末尾有moov原子的文件,并通过使用-movflags + faststart(或c / c ++代码中的类似AVOptions)与ffmpeg重新混合,将moov原子移动到开头。然后你可以在moov原子之后截断文件并解析标题仍然有用。

[编辑]

因此,对于将截断片段感知修改写入mov demuxer的情况(请参阅注释),这里是您的选择。首先,尽量不要修改mov_read_default(),它是中央递归引擎,这里的任何更改都可能会破坏大多数常规功能。相反,对mov_read_header()进行更改(因为你只关心这里的头解析,而不是帧的解复用)。您将找到此代码:

if (mov->moov_retry)
    avio_seek(pb, 0, SEEK_SET);
if ((err = mov_read_default(mov, pb, atom)) < 0) {
    av_log(s, AV_LOG_ERROR, "error reading header\n");
    mov_read_close(s);
    return err;
}
} while (pb->seekable && !mov->found_moov && !mov->moov_retry++);
if (!mov->found_moov) {

这是尝试解码头树结构,其中moov是上层原子。在文件中,它会查找如下序列:

$ hexdump -n 32 -s 41934133 -C somefile.mov 
027fdd35  00 00 3e b4 6d 6f 6f 76  00 00 00 6c 6d 76 68 64  |..>.moov...lmvhd|
027fdd45  00 00 00 00 c9 6b 7b f5  c9 6b 7c 02 00 00 02 58  |.....k{..k|....X|

0x00003eb4是&#39; moov&#39;的大小,以字节为单位。原子,在其中是一个称为“mvhd”的亚原子。大小为0x0000006c字节(树结构在此之后会持续一段时间)。如果在解压缩文件时将文件指针设置为此精确偏移量,则它将正确解码:

$ tail -c +41934134 somefile.mov > /tmp/hdr.mov
$ ffprobe  /tmp/hdr.mov
[..]
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f871b002a00] stream 0, offset 0x3f3e: partial file
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f871b002a00] Could not find codec parameters for stream 0 (Video: h264 (avc1 / 0x31637661), none(bt709), 1280x720, 10695 kb/s): unspecified pixel format
[..]
    Stream #0:0(und): Video: h264 (avc1 / 0x31637661), none(bt709), 1280x720, 10695 kb/s, 29.97 fps, 29.97 tbr, 600 tbn, 1200 tbc (default)
[..]
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 63 kb/s (default)

如何获得该文件的偏移量取决于您:

  • 您可以向mov_read_header()添加一些代码,以扫描文件中的“moov&#39; (0x6d6f6f76)并将文件指针设置为
  • 之前的4个字节
  • 您可以在创建此片段的代码中扫描moov并在将该片段保存到文件之前将moov原子之前的前导垃圾切掉

如果您要更改ffmpeg并将其放入您用于其他功能的ffmpeg版本中,我建议您将其置于某种选项之下,这样就不会启用默认文件读取。否则,您将面临常规mov / mp4文件解析将无法正常工作的风险。