AVI 檔案格式
Audio Video Interleave,Microsoft 經典的 RIFF 視訊容器。
- MIME 類型
- video/x-msvideo
- 副檔名
- .avi
- 分類
- 影片
Magic number(檔案簽章)
| 0x00000000 | 52494646 | RIFF | RIFF container |
| 0x00000008 | 41564920 | AVI | 'AVI ' form type |
關於 AVI 格式
AVI 是 Microsoft 在 1992 年推出的視訊容器,建立在 RIFF 之上 — 跟 WAV 同一套分塊結構,每個 chunk 是一個四字元識別碼、一個小端序 32 位元長度,然後是那麼多位元組的酬載。這個設計簡單到一頁程式碼就剖析得完,而那份簡單也就是它的全部故事:AVI 沒有像樣的變動影格率概念,容器層級不支援現代音訊,沒有字幕軌,沒有每軌語言,而那個 32 位元的大小欄位在 OpenDML 擴充繞過它之前,替檔案長度訂了一個硬上限。它真正有的東西是一份完全固定的標頭,因為規格要求 'hdrl' 清單排第一、主標頭 chunk 又必須排在那份清單的第一個,所以一個 AVI 的寬、高和影格率永遠落在同樣的位元組位移上。
檔頭結構,一個位元組一個位元組看
| 位移 | 長度 | 欄位 | 意義 |
|---|---|---|---|
| 0 | 4 | RIFF signature | 52 49 46 46,ASCII 的 RIFF 四個字母。它和 WAV、WebP 以及幾種同期的 Microsoft 格式共用,所以光靠它只能認出這是分塊結構,認不出是哪一種格式。 |
| 4 | 4 | RIFF chunk size | 這個欄位之後所有東西的位元組數,小端序 — 也就是檔案大小減八。AVI 裡每個大小都是小端序,這也是判斷「你看的不是 QuickTime 檔案」最快的方法。 |
| 8 | 4 | Form type 'AVI ' | 41 56 49 20,尾巴那個 ASCII 空格是四字元代碼的一部分。就是這個欄位讓檔案成為 AVI 而不是 WAV 或 WebP,而那個空格也是為什麼隨手寫的字串比較會漏掉它。 |
| 12 | 4 | LIST identifier | 4C 49 53 54。RIFF 會把 chunk 分組成 list,而規格要求標頭 list 必須是檔案裡的第一個,這正是下面每個位移都可以預測的原因。 |
| 16 | 4 | LIST size | 標頭 list 的長度,小端序,含後面那個四字元的 list 類型,但不含這四個位元組本身。它涵蓋主標頭,以及每條軌一組的串流標頭區塊。 |
| 20 | 4 | List type 'hdrl' | 68 64 72 6C。指名這份 list 是標頭 list。規格要求它必須排在任何資料之前,跟 MP4 的安排剛好相反 — 這也是為什麼被截斷的 AVI 仍然報得出正確尺寸。 |
| 24 | 4 | Chunk identifier 'avih' | 61 76 69 68,AVI 的主標頭。它必須是 'hdrl' 裡的第一個 chunk,所以在格式正確的檔案裡,它永遠在這個位移上。 |
| 28 | 4 | avih chunk size | 小端序,而且固定是 38 00 00 00 — 56 個位元組,也就是後面那十四個 32 位元欄位。這裡出現任何其他值,都代表標頭壞了,或寫入端產出了不合標準的東西。 |
| 32 | 4 | Microseconds per frame | 小端序,也是容器層級唯一交代影格率的地方。00 01 86 A0 用小端序讀是 100000,也就是每秒十格。AVI 根本沒有辦法表達變動的影格率,這是這個格式後果最嚴重的限制。 |
| 36 | 4 | Maximum bytes per second | 這個檔案預期需要的尖峰資料率,單位是每秒位元組數。它原本是要讓播放器判斷媒體跟不跟得上的,今天實際上只是參考用。 |
| 40 | 4 | Padding granularity | 資料 chunk 要補齊到幾個位元組對齊 — 為 CD-ROM 播放而寫的檔案是 2048,其他幾乎所有地方是零,代表不補。這裡會列出它,是因為省略掉就會在表格裡留下一段沒有交代的四位元組空隙。 |
| 44 | 4 | Flags | 一個位元欄位:位元 4 表示檔案有索引 chunk,位元 5 表示應該用索引決定播放順序,位元 8 表示檔案是交錯排列的,位元 16 表示它是即時擷取的。真正重要的是索引那個位元,因為沒有它,seek 就退化成線性掃描。 |
| 48 | 4 | Total frames | 這個檔案的影格總數,小端序。它是編碼結束之後才寫的,所以被中斷的錄影會在這裡留下零或一個過期的值,於是即使影格全都在,播放器報出來的長度也是錯的。 |
| 52 | 4 | Initial frames | 在交錯排列的檔案裡,音訊比視訊超前幾格。只要不是從即時來源擷取的,它就是零;而一個被播放器忽略的非零值,正是整支檔案音訊固定偏移的成因之一。 |
| 56 | 4 | Stream count | 'hdrl' 裡面接著有幾組串流標頭區塊。一般情況是二,一條視訊一條音訊;格式允許更多,而舊檔案有時會帶第三條,裝著現在已經沒有東西解得開的文字或 MIDI 串流。 |
| 60 | 4 | Suggested buffer size | 寫入端認為播放器需要多大的讀取緩衝區,單位是位元組,通常是檔案裡最大那個 chunk 的大小。純參考用,而且常常是隨手填個整數 MB,而不是真的量出來的。 |
| 64 | 4 | Width in pixels | 小端序。這是容器對畫面尺寸的宣稱,而它不一定等於視訊串流自己講的 — 這兩者對不起來,在舊擷取硬體產出的檔案裡是真實存在的現象。 |
| 68 | 4 | Height in pixels | 小端序,編碼方式和寬度一模一樣。它加上位移 64 這八個位元組,是讀出 AVI 尺寸最快又可靠的方式,因為在每個合規檔案裡它們都落在固定位置。 |
| 72 | 16 | Reserved | 四個 32 位元字組,全部是零。它們把 56 個位元組的主標頭收尾,所以下一個 chunk 從位移 88 開始 — 通常是裝著第一條串流標頭的 'strl' list。 |
怎麼跟長得像的格式分開
| 容易搞混的 | 怎麼分 |
|---|---|
| WAV | 同一個 RIFF 容器,位移 8 的格式類型不同:是 'WAVE'(57 41 56 45)而不是 'AVI '(41 56 49 20)。到位移 7 為止完全相同,所以只檢查前四個位元組,你只知道這是 RIFF。格式類型之後的排版就完全分岔了 — WAV 直接進 'fmt ' chunk,AVI 則開一個 'hdrl' list。 |
| WebP | 也是 RIFF,位移 8 是 'WEBP'(57 45 42 50)。這個重疊乍看真的很容易搞混,因為三者的 hex dump 開頭都是同樣四個 ASCII 字母加一個小端序長度,而分開一段影片、一個音訊檔和一張靜態圖的,只有位移 8 那幾個位元組。 |
| Matroska | 毫無共通之處:Matroska 位移 0 是 1A 45 DF A3,而且從頭到尾用變動長度的大小。值得把這兩者放在一起認識,是因為把舊 AVI 重新封裝成 MKV 是影格的無損複製,同時換到變動影格率、字幕軌和一份像樣的索引。 |
| OpenDML AVI 2.0 | 把實質上的 2 GB 與 4 GB 上限解除掉的擴充。這種檔案開頭同樣是 'RIFF' 和 'AVI ',跟上面講的一字不差,差別在後面:多出來的最上層 RIFF chunk,格式類型是 'AVIX' 而不是 'AVI ',每一個接續前面的串流。走完第一個 RIFF chunk 就停下來的讀取端,在大檔案上只會播出開頭那一段,然後把它報成「比較短」而不是「壞掉」。 |
常見的壞法
- idx1 索引 chunk 不見了或被截斷。它住在檔案結尾,所以被打斷的下載或被切掉的擷取,第一個掉的就是它。影片從頭播得動,因為 chunk 本身是自我描述的,而 seek 不是直接失敗,就是退化成線性掃描,跳一次要好幾秒。
- 2 GB 與 4 GB 那兩道牆。位移 4 的 RIFF 大小欄位是 32 位元的,所以從來不寫 OpenDML AVIX 擴充的寫入端,在檔案長過上限時就直接繞回去了。結果是一個格式正確、數字卻錯的檔案:播放器讀到的大小遠小於磁碟上的實際檔案,於是提早停住。
- 位移 48 的影格總數寫錯。它是編碼結束時才寫的,所以當掉或被強制關閉的擷取,會留下零、或寫入端當初隨便猜的數字。每一格都在、也播得動,秀出來的長度卻是胡說八道 — 這是修標頭的事,不必重新編碼。
- 音訊和視訊愈跑愈開。AVI 是把固定速率的 chunk 交錯排列的,所以用變動位元率編的音訊 — 這個容器從來沒為它設計過 — 會在一支長片裡對著視訊一路累積誤差。第一分鐘完全聽不出來,到第二十分鐘已經嚴重不同步,而標頭裡沒有任何線索。
- 已經沒有人有的編碼。每條串流標頭裡的四字元代碼寫著 DIVX、XVID、MP42 或 IV50 這類東西,而其中許多解碼器早就隨著當年出貨它們的作業系統一起消失了。容器完好、每個位移也都讀得對;檔案播不出來是因為解碼器沒了,解法是轉檔而不是修復。
這個格式現在還在用嗎
AVI 是一個死不肯消失的老格式,而它至少十五年前就已經不該用在新工作上了。它的限制是結構性的、不是意外造成的 — 只有固定影格率、沒有字幕軌、沒有每軌語言、沒有現代音訊,還有一個靠擴充硬糊過去的 32 位元大小欄位 — 而 MP4 和 Matroska 把這些全部解決掉了。你還會遇到它的地方是檔案庫:攝錄影機的擷取檔、老擷取卡錄的螢幕影片、從錄影帶數位化來的影片,以及那些韌體寫完就再也沒人回頭看的科學與工業用相機。未壓縮和輕度壓縮的 AVI 在少數擷取流程裡也還在當暫存格式,因為「寫一個 chunk 加一個長度」大概是一台裝置能即時做的最便宜的事。任何需要保存下來的東西,重新封裝進 Matroska 就好:影格原封不動地複製過去,而這個容器缺的東西全部補齊。
在這個站上打開 AVI 檔
這些全部在你的瀏覽器裡跑,檔案不會離開你的電腦。
相關格式
容易和 AVI 搞混的格式,可以比對它們的開頭位元組。