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

Ffmpeg ffprobe-从文件块获取视频信息,ffmpeg,mp4,ffprobe,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 n

在我的网站上,用户可以上传动态加密并存储在另一台服务器上的视频。我想存储视频比特率、帧速率等,但我无法直接访问它们,我不能仅使用以下命令:

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-atom是完整的


从包含moov atom的文件片段中获取视频元数据的正确方法是什么?从MDataAtom中获取信息怎么样?

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

对您来说,一种可能的解决方案是检测末尾有moov原子的文件,并通过使用ffmpeg和-movflags+faststart(或c/c++代码中类似的避免选项)重新移动moov原子,将其移动到开头。然后,您可以在moov原子之后截断文件,解析头仍然可以工作

[编辑]

因此,对于编写对mov解复用器的截断片段感知修改(请参见注释)的情况,您可以这样做。首先,尽量不要修改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) {
0x00003eb4是“moov”原子的字节大小,其中有一个称为“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)
如何将文件偏移量设置到该点取决于您:

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

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

如果我可以在整个文件上使用ffmpeg,我不会问问题。如果您从未将整个文件保存在磁盘上,我认为ffmpeg无法帮助您。你可以在你的最后一个片段上尝试mplayer,尽管我怀疑它会做得更好。或者,您可以使用ffmpeg解复用器中的相关代码编写自己的头解析器。(我的印象是服务器可以访问未加密的文件,因为您可以访问最后一个片段。)实际上,考虑到这一点,您甚至可以添加一个额外的“moov fragment demuxer”,忽略块,只扫描moov原子,并使用从moov fragment demuxer调用的ffmpeg中现有的moov解析代码。然后将其注册为ffmpeg解复用器。这样您就可以编写最少的代码。如果你对这种方法感兴趣,我可以给你更多的提示。好的,我想这样做。我下载了ffmpeg源代码,我将编辑本机moov解复用器(libavformat/mov.c),而不是注册自己的。我应该修改mov_read_default(),对吗?谢谢,它可以工作。在linux上,当我编辑一行时,编译整个FFmpeg需要15分钟。您可能知道如何快速编译和轻松调试代码吗?
$ 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)