MP4 檔案格式
MPEG-4 Part 14,網路影音的標準 ISO-BMFF 容器。
- MIME 類型
- video/mp4
- 副檔名
- .mp4
- 分類
- 影片
Magic number(檔案簽章)
| 0x00000004 | 66747970 | ftyp | ISO-BMFF 'ftyp' box |
| 0x00000008 | 69736F6D | isom | a major brand, e.g. 'isom'/'mp42' |
關於 MP4 格式
MP4 是串流與下載影片最主流的封裝容器,通常裝的是 H.264、H.265 或 AV1 視訊搭配 AAC 音訊。它不是一串影格,而是一棵 box 樹,每個 box 都是一個大端序 32 位元大小加上四字元類型,而 ISO/IEC 14496-12 規定 FileTypeBox 必須排在第一個。這就是為什麼認得出來的 ASCII 'ftyp' 坐在位移 4 而不是位移 0:前面那四個位元組是它所引導的那個 box 的大小。播放器解碼需要的一切 — 軌列表、編碼參數、樣本表、時間戳 — 都住在 'moov' box 裡,壓縮後的樣本本身則住在一個或多個 'mdat' box 裡。格式本身沒有規定這兩者誰先誰後,而這個沒被限制的排序決定,正是大家用 MP4 時多數實務麻煩的源頭。
檔頭結構,一個位元組一個位元組看
| 位移 | 長度 | 欄位 | 意義 |
|---|---|---|---|
| 0 | 4 | ftyp box size | 整個 FileTypeBox 的位元組數,大端序,含這四個位元組本身。00 00 00 20 是 32 個位元組,足夠放一個主要品牌識別、一個次版本號和四個相容品牌識別。大小是 1 代表類型後面跟著 64 位元的 largesize;大小是 0 代表這個 box 一路延伸到檔案結尾。這兩個逃生口從來不會用在 ftyp 上。 |
| 4 | 4 | Box type 'ftyp' | 66 74 79 70。這才是每個 ISO base media 檔案真正的 magic number,而它刻意不在位移 0,因為這個格式裡每個 box 都把自己的長度擺在名字前面。 |
| 8 | 4 | Major brand | 四字元代碼,指名這個檔案宣稱遵循的規格:isom、iso2、iso5、iso6、mp41、mp42、avc1,分段串流則是 dash。MP4 跟 MOV、M4V、M4A、3GP、AVIF、HEIC 的分野就在這段位元組,因為它們前面那個 ftyp box 長得一模一樣。 |
| 12 | 4 | Minor version | 一個大端序 32 位元數字,純資訊用 — 規格明文說讀取端不得因為它而拒收檔案。ffmpeg 在 isom 品牌識別旁邊寫 00 00 02 00,而網路上極大比例的檔案帶著這個值,沒有什麼更好的理由。 |
| 16 | variable | Compatible brands | 一串四字元的品牌識別,每個四個位元組,把 box 剩下的空間填滿。看不懂主要品牌識別的播放器,只要認得這裡任何一筆就可以繼續處理 — 一個 dash 分段或 avc1 檔案,能在只認得 isom 的解碼器裡打開,靠的就是這個。 |
| 32 | 8 | Second box header | ftyp 之後那個 box 的大小與類型 — 'moov'、'mdat'、'free' 或 'wide'。ftyp box 是 32 個位元組時它就落在位移 32,這很常見但不是規則:請去讀位移 0 的大小,不要假設位置。 |
怎麼跟長得像的格式分開
| 容易搞混的 | 怎麼分 |
|---|---|
| QuickTime Movie | 前八個位元組一個不差,唯一分得開它們的是位移 8 的主要品牌識別:'qt ' 後面帶兩個空格、也就是 71 74 20 20,代表 QuickTime。還有第二種情況是純比對品牌識別會完全漏掉的 — 大約 2004 年以前寫出來的 QuickTime 檔案根本沒有 ftyp box,位移 4 直接就是 'moov'、'mdat'、'free'、'skip'、'wide' 或 'pnot'。 |
| M4V | 同樣的 box、同樣的排版,位移 8 的品牌識別是 'M4V '(4D 34 56 20,注意尾隨的空格)。沒有保護的 M4V 各方面都就是 MP4,改個副檔名就行;播不了的那些是有 FairPlay 保護的,而那件事要在檔案更深處的加密樣本項目裡才看得到,不在標頭這裡。 |
| 3GP | 位移 8 的品牌識別是 3gp4、3gp5 或 3gp6 — 33 67 70 後面接一個數字。3GP 是同一個容器針對手機收斂出來的受限設定檔,所以它裡面每個 box 都是合法的 MP4,反過來卻不成立:一個裝著 H.265 或 AC-3 的 MP4 不是合法的 3GP 檔案,即使剖析器可以很順地走完它。 |
| AVIF | 它一樣有 ftyp box,品牌識別是 'avif' 或 'avis',一樣塞滿了名字相同的 box — 但它是靜態影像,圖放在 'meta' box 裡而不是放在帶時間軸的軌上。HEIC 也是同一回事,品牌識別是 'heic'、'heix' 或 'mif1'。任何只憑 'ftyp' 下判斷的工具,都會很開心地把一張照片叫成影片。 |
| WebM | 完全無關:WebM 和 Matroska 是 EBML 檔案,位移 0 就是 1A 45 DF A3。會混淆是副檔名害的、不是位元組害的,因為兩邊都裝得下 AV1 和 Opus、也都能在瀏覽器裡播,所以檔案就被人在兩種副檔名之間亂改,然後打不開。 |
常見的壞法
- moov box 不見了。電池沒電當場中斷的錄影、或匯出到一半被砍掉的檔案,留下的是 mdat 裡每一格影像都在、索引卻從來沒寫出來的檔案 — 因為多數封裝器是在記憶體裡建 moov,最後才附加到檔尾。這種檔案很大,在 hex dump 裡明顯全是影片資料,卻完全播不出來;要救就得拿同一台裝置錄的另一個完好檔案,把樣本表重建出來。
- moov box 在檔尾,而檔案是用串流方式送的。這裡其實什麼都沒壞,但透過 HTTP 抓檔的播放器必須下載到最後才能開始播,在慢速連線上看起來就跟壞檔一模一樣。把這個 box 搬到前面正是 faststart 旗標做的事,而它只是改寫位移,不會重新編碼任何東西。
- 下載被截斷。因為 box 會先宣告自己的長度,剖析器走到最後一個完整的 box 之後,會碰到一個承諾的位元組數超過剩餘量的大小欄位。寫得好的讀取端會停下來、把手上有的播完;其他的則直接把檔案報成損壞,即使大部分內容都解得好好的。
- box 大小在說謊。小於 8 的大小不可能存在,因為光是大小和類型欄位就佔 8 個位元組,但一個壞掉的位元組就能生出這種值 — 而天真的剖析器把大小加到游標上之後,會在同一個位移上永遠迴圈下去。當一個檔案不是讓工具報錯而是讓它卡死時,值得手動查一下這個。
- 前面被塞了位元組。一頁被存成 .mp4 名字的 HTML 錯誤訊息,或是真正資料前面多出來的 BOM,都會把 'ftyp' 擠離位移 4。moov box 裡每一個 chunk 位移都是從檔案開頭量的,所以就算把垃圾認出來了,也必須真的把它刪掉、而不只是跳過去,檔案才播得動。
這個格式現在還在用嗎
網路上的影片,實際上就是 MP4。HLS 和 DASH 以分段形式送的是它,每支手機錄的是它,全世界每個瀏覽器和每顆硬體解碼器播的都是裝在它裡面的 H.264,每套剪輯軟體匯入的也是它。它的專利處境正是 WebM 存在的理由,而在開放網路上跑免權利金的 AV1 與 VP9 這件事上,WebM 確實搶到了實質的份額;Matroska 則拿下典藏用途,因為它處理多條字幕與音軌時麻煩少得多。讓 MP4 仍然是第一選擇的還是硬體:MP4 裡的一條 H.264 軌,在過去十五年做出來的幾乎每一支手機、每一台電視和每一台筆電上,都是由專用電路解的 — 對任何靠電池跑的裝置來說,這比壓縮率贏一點更值錢。它也是 Safari 和 iOS 唯一當成一等公民對待的容器,這一點對任何要把影片送給一般大眾的人來說,就已經把爭論結束掉了。
在這個站上打開 MP4 檔
這些全部在你的瀏覽器裡跑,檔案不會離開你的電腦。
相關格式
容易和 MP4 搞混的格式,可以比對它們的開頭位元組。
| 格式 | 開頭位元組 | 副檔名 |
|---|---|---|
| QuickTime Movie | 66 74 79 70 | .mov |
| M4V | 66 74 79 70 | .m4v |
| M4A | 66 74 79 70 | .m4a |
| WebM | 1A 45 DF A3 | .webm |
| AVIF | 66 74 79 70 | .avif |