在之前文章中已經介紹過了 MP4 标準的來源以及它的格式定義,基本上就是由一個個 Box 組成的,大緻的結構如下:
ftyp
moov
mvhd
trak
tkhd
mdia
trak
tkhd
mdia
mdat
之前文章:
重學音視訊?認識 MP4 視訊(上)
重學音視訊?認識 MP4 視訊(下)
接下來我們就要去手動解析 MP4 檔案,注意這可不是用 FFmpeg 來解封裝,而是從 MP4 檔案中一個一個位元組讀取資訊并解析它的含義獲得想要的内容。
平常一看到字尾是
.mp4
的檔案,腦海裡一想到的就是視訊,但其實不管字尾如何,它也還是一個二進制檔案,可以按照二進制的方式進行讀取和寫入。
解析 MP4 檔案擷取資訊
舉個例子,在 Mac 上用
010 Editor
軟體去檢視一個 MP4 檔案,以 16 進制顯示,效果如下:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiQDOxEzX3xCZlhXam9VbsUmepNXZy9CXwJWZ3xCdh1mcvZ2Lc1zaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLwIzX39GZhh2csATMflHLwEzX4xSZz91ZsAzMfRHLGZkRGZkRfJ3bs92YskmNhVTYykVNQJVMRhXVEF1X0hXZ0xiNx8VZ6l2cssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyAzN2EmZwImMxYjYyEDNzYzX5QDO0UTM4AzLcBTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
從圖中箭頭訓示處可以看到
ftyp
和
mvhd
兩個 Box 類型,另外也還有
moov
和
tkhd
這些 Box 類型。
之是以能夠顯示出 Box 類型的字元串,是因為把十六進制資料轉換成 ASCII 碼了,比如 61 對應就是字母 a ,這應該在計算機基礎書中都有講過的。
在
mvhd
Box中存儲着視訊檔案的時長資訊,想要擷取到這個資訊,直接從 Box 中讀取就好,至于為什麼會這樣,見下圖:
上圖展示了 mvhd Box 的資料結構,它繼承自 FullBox,在讀取時先讀取 FullBox 的字段,然後在讀取 mvhd Box 自己的(取 version == 0 時的資料結構排布)。
關于 mvhd box 和 full box 的資料結構文檔以及 MP4 中所有 Box 的類型資料,已經在知識星球中給出了,可以加入星球在資料中找到,文末有優惠券。
FullBox 的資料結構如上所示,由位元組位數可以算出,在 box type 之後偏移 12 位元組可以得到 timescale 字段内容,偏移 16 位元組可以得到 duration 字段内容。
其中 timescale 為 0x000003E8,對應十進制資料 1000 。
duration 為 0x000086E6,對應十進制資料 34534。
用 duration 除以 timescale 就是視訊的時長了,十六進制相除後的結果是 0x22,轉換成十進制就是 34,和用十進制資料相除得到的 34.534 基本一緻了(時長機關是秒)。
以上隻是個簡單例子,說明完全可以去手動解析 MP4 檔案擷取它的格式資訊。