有人能告诉我常用视频文件格式的元数据存储在哪里吗?以及它是否位于文件的开头,或者分散在各处。
我正在使用一个包含大量视频文件的远程对象存储,我想从这些文件中提取元数据,特别是视频持续时间和视频维度,而无需将整个文件内容流式传输到本地机器。
我希望这些元数据将存储在文件的前X个字节中,这样我就可以从一开始获取一个字节范围,而不是整个文件,将部分文件数据传递给ffprobe
。
出于测试目的,我创建了一个22MB的MP4文件,并使用以下命令仅向ffprobe提供前1MB的数据:
head -c1024K '2013-07-04 12.20.07.mp4' | ffprobe -
它打印:
avprobe version 0.8.6-4:0.8.6-0ubuntu0.12.04.1, Copyright (c) 2007-2013 the Libav developers
built on Apr 2 2013 17:02:36 with gcc 4.6.3
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x1a6b7a0] stream 0, offset 0x10beab: partial file
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'pipe:':
Metadata:
major_brand : isom
minor_version : 0
compatible_brands: isom3gp4
creation_time : 1947-07-04 11:20:07
Duration: 00:00:09.84, start: 0.000000, bitrate: N/A
Stream #0.0(eng): Video: h264 (High), yuv420p, 1920x1080, 20028 kb/s, PAR 65536:65536 DAR 16:9, 29.99 fps, 30 tbr, 90k tbn, 180k tbc
Metadata:
creation_time : 1947-07-04 11:20:07
Stream #0.1(eng): Audio: aac, 48000 Hz, stereo, s16, 189 kb/s
Metadata:
creation_time : 1947-07-04 11:20:07
因此,我看到前1MB足以提取9.84秒的视频持续时间和1920x1080的视频尺寸,尽管ffprobe打印了关于检测到部分文件的警告。如果我提供的内存不足1MB,它将完全失败。
这种方法是否适用于其他常见的视频文件格式以可靠地提取元数据,或者任何常见的格式是否将元数据分散在整个文件中?
我知道容器格式的概念,可以使用各种编解码器来表示这些容器中的音频/视频数据。不过我对细节并不熟悉。所以我想这个问题可能适用于容器+编解码器的常见组合?提前谢谢。
在深入研究了MP4、3GP和AVI的规格后,我可以回答我自己的问题了。。。
AVI
根据AVI文件格式规范,元数据位于AVI文件的开头。
视频持续时间不会逐字存储在AVI文件中,而是按dwMicroSecPerFrame x dwTotalFrames计算(以微秒为单位)。
从规范的行与行之间读取,似乎可以直接从AVI文件中的偏移量读取许多元数据项,而无需进行任何解析。但是规范没有明确提到这些偏移,所以使用这个经验法则可能会有风险。
偏移32:dwMicroSecPerFrame,偏移48:dwTotalFrames,偏移64:dwWidth,偏移68:dwHeight。
因此,对于AVI,可以仅使用文件的前X个字节提取此元数据。
MP4、3GP(3GPP)、3G2(3GPP2)
所有这些文件格式都基于称为ISO/IEC 14496-12(MPEG-4第12部分)的ISO基本媒体文件格式。
这种格式允许元数据存储在文件中的任何位置,但在实践中,它要么在开始,要么在结束,因为原始捕获的音频/视频数据被连续地保存在在中间。(然而,一个例外是"碎片化"的MP4文件,这是罕见的。)
只有在开始时存储了元数据的文件才能通过渐进式下载播放,但这取决于捕获设备或解码器是否支持。
AFAICT这意味着要从这些文件中提取元数据,只需要文件的前X个字节,并且根据该信息可以确定可能还需要最后X个字节。但是中间的字节是不需要的。