ByteScope

Matroska 檔案格式

Matroska,一個幾乎能容納任何編碼的開放多媒體容器。

MIME 類型
video/x-matroska
副檔名
.mkv
分類
影片

Magic number(檔案簽章)

0x000000001A45DFA3·E··EBML header

開頭附近的 EBML DocType 字串是 'matroska'。

關於 Matroska 格式

Matroska 是一開始就打算什麼都裝得下的開放容器:任何視訊編碼、任何音訊編碼、數量不限的字幕軌、章節、附件、標籤,以及每條軌各自的語言,全部裝在同一個檔案裡。它建立在 EBML 之上 — 一種形狀像 XML 的二進位編碼,每個元素是一個變動長度的識別碼,接一個變動長度的大小,然後不是一個值就是巢狀的元素。因為大小是明講而不是推導出來的,剖析器可以在完全看不懂任何一個元素的情況下把整個 Matroska 檔案走完,不認得的東西直接跳過。WebM 是同一套編碼配上一份比較小的編碼清單,所以兩者的前二十一個位元組完全相同,唯一的差別是指名格式的那個 DocType 字串。

檔頭結構,一個位元組一個位元組看

位移長度欄位意義
04EBML master element ID1A 45 DF A3,magic number,也是這個檔案裡唯一由規格、而不是由慣例釘死位置的欄位。WebM 這裡是一模一樣的四個位元組。
41EBML header size一個變動長度整數,開頭那個 1 位元表示它只有一個位元組長,剩下七個位元給出標頭本體的大小。Matroska 檔案是 A3、也就是 35,WebM 則是 9F、也就是 31 — 差的那四個位元組正是 'matroska' 比 'webm' 多出來的長度。寫入端可以把這個整數補到多達八個位元組。
54EBMLVersion element42 86 81 01 — 元素識別碼、大小 1、值 1。這份標頭裡每個元素都有預設值、也都可以合法省略,所以下面這些位移描述的是一般寫入端實際吐出來的樣子,不是規格保證的排版。
94EBMLReadVersion element42 F7 81 01。讀取端至少要實作到哪個 EBML 版本才剖析得了這個檔案。它從來沒離開過 1。
134EBMLMaxIDLength element42 F2 81 04。這個檔案裡任何地方用到的最長元素識別碼,實務上是四個位元組,剖析器可以據此在開工前把緩衝區大小定下來。
174EBMLMaxSizeLength element42 F3 81 08。這個檔案裡最長的大小欄位。八是常見值,也是即時寫入的 Segment 上那個未知大小標記寬度是八個位元組的原因。
212DocType element ID42 82。指名這個檔案實際上是哪一種以 EBML 為基礎的格式,也是 Matroska 檔案光看前二十個位元組跟 WebM 分不出來的唯一原因。
231DocType length88 — 一個位元組的變動長度整數,值是 8,也就是後面那個字串的長度。WebM 這裡是 84,因為它的名字只有四個字元,而從這裡開始,兩種格式後面每個位移都差四。
248DocType value6D 61 74 72 6F 73 6B 61,ASCII 的 matroska。決定格式的就是這個欄位,也是為什麼檔案類型檢查至少得讀三十二個位元組、不能只讀四個。
324DocTypeVersion element42 87 81 04。寫入端用的是 Matroska 元素集的哪一個版次 — 4 涵蓋了現在多數封裝器依賴的新增內容。讀取端被期待跳過不熟悉的元素,而不是拒收檔案。
364DocTypeReadVersion element42 85 81 02。要能剖析這個檔案,至少需要哪個版次 — 這個數字刻意比上面那個版本低,好讓比較舊的讀取端不會被關在門外。
404Segment element ID18 53 80 67,裝著整個檔案本體的 master 元素:軌定義、一團團的影格 cluster、cue 索引、章節、標籤和附件。它的大小緊接在後,而在還在寫入中的檔案裡,它是未知大小形式。

怎麼跟長得像的格式分開

容易搞混的怎麼分
WebM同一套編碼,位移 24 換個名字:'matroska' 對上 'webm'。早一個位元組的判別更快 — 位移 23 的 DocType 長度這裡是 88、那裡是 84 — 而位移 4 的 EBML 標頭大小也因為同一個原因不同,A3 對上 9F。真正重要的是編碼:Matroska 裝得下 H.264、HEVC、AC-3、DTS 和 TrueHD,而這些從一個標成 WebM 的檔案裡拿出來,瀏覽器一個都不會解。
MKA.mka 是只裝音訊的 Matroska 檔案,.mks 只裝字幕,.mk3d 則是立體視覺的。沒有一個帶著可供分辨的標頭位元組 — DocType 每次讀到的都是 'matroska' — 所以副檔名只是寫入端對內容的宣稱,而真相唯一被記錄下來的地方是 Tracks 元素。
MP4結構上毫無關係:MP4 是一棵 box 樹,大小是大端序 32 位元,位移 4 是 'ftyp';Matroska 是 EBML,識別碼和大小都是變動長度,magic 在位移 0。它們老是被拿來比較,是因為兩邊都裝得下 H.264 和 AAC,而且互相重新封裝是無損複製,但它們的位元組沒有任何共通之處。
AVIMatroska 當初就是為了取代它而生的容器。AVI 是 RIFF,大小是小端序,開頭是 52 49 46 46、位移 8 是 'AVI ',而且它對變動影格率、現代音訊、字幕或每軌語言都沒有像樣的支援。把舊 AVI 重新封裝成 MKV,壓縮後的影格一個位元組都不變,卻把上面那些全部拿到手。

常見的壞法

  • 未知的 Segment 大小從來沒被補回去。封裝器寫進管線或即時來源時,會把 Segment 大小整數的每個值位元都設起來 — 那是 EBML 正是為此定義的全 1 形式 — 並且照理應該在收工時回頭寫上真正的長度。中途被砍掉,它就永遠沒寫 — 留下一個從頭播得動、報不出長度、也不能 seek 的檔案。
  • 少了 Cues 元素。這個 seek 索引通常放在 Segment 的頭或尾,而即時擷取的東西根本不會有它。播放器只能退回去掃 cluster,在大檔案上又慢又不準;單純重新封裝一次就會寫出一份像樣的索引,而且一格畫面都不必重壓。
  • 截斷。每個元素都寫明自己的長度,所以讀取端會乾淨地走到最後一個完整的 cluster,然後碰上一個承諾了不存在的位元組的大小。有些播放器把到那個點為止的東西播完就停;有些則說整個檔案壞了 — 所以一個下載到一半的 MKV 才會在某個工具裡打得開、在另一個裡打不開。
  • 字幕文字編碼不對。容器會記錄每條軌的 CodecID 和語言,但對比較舊的文字格式來說,並不會記錄一個可靠的字元編碼。一條用 Big5、GBK 或 Shift-JIS 寫的字幕軌被當成 UTF-8 讀,就會出來一堆亂碼,而影片和音訊的每個位元組都好好的。
  • 元素識別碼壞掉。因為識別碼和大小都是變動長度的,大小欄位裡翻掉一個位元組,就能讓剖析器跳進某個影格中間、把垃圾當成下一個元素來讀。這種檔案往往還是播得動,因為 cluster 會重新同步,但嚴格的剖析器會停在翻掉的那個點,把後面全部報成讀不了。

這個格式現在還在用嗎

Matroska 是影片拿來保存、而不是拿來交付的地方。任何帶多國語言音軌、好幾條字幕軌、章節和內嵌字型的東西都是 MKV,因為沒有別的容器能毫無怨言地處理這種組合,而且重新封裝進去只是把影格無損複製一次,不是重新編碼。它也是多數編碼工具的工作格式,所以就算內容明明塞得進 MP4,從那些工具出來的檔案照樣是 .mkv。它輸的地方是覆蓋率:沒有瀏覽器播得動它,iOS 和多數電視拒收,硬體播放器的支援又參差不齊,所以只要東西是要寄給別人的,安全答案仍然是 MP4。慣例做法是用 Matroska 典藏、匯出成 MP4,而因為裡面的影片完全沒被動過,那個匯出只是換容器,不是畫質損失。

在這個站上打開 Matroska 檔

這些全部在你的瀏覽器裡跑,檔案不會離開你的電腦。

相關格式

容易和 Matroska 搞混的格式,可以比對它們的開頭位元組。

格式開頭位元組副檔名
WebM1A 45 DF A3.webm
MP466 74 79 70.mp4
AVI52 49 46 46.avi

常見問題

檔案的 magic number 是什麼?

檔案開頭的前幾個位元組,不管檔名寫什麼,它標明的是真正的格式。PNG 一定以 89 50 4E 47 開頭,ZIP 則是 50 4B 03 04。作業系統、瀏覽器和 file 指令讀的都是這幾個位元組,而不是相信副檔名 — 這就是為什麼把檔案改名並不會改變它實際上是什麼。

我要怎麼自己檢查 magic number?

在 macOS 或 Linux 上,xxd -l 16 檔名 會印出前 16 個位元組;在 Windows 上,PowerShell 的 Format-Hex -Path 檔名 -Count 16。或者把檔案丟進本站的檔案類型辨識工具,它會在本機讀取位元組並告訴你是什麼格式,不會上傳任何東西。

為什麼兩種格式的 magic number 會一樣?

因為其中一種是建立在另一種之上。docx、xlsx、pptx、apk、jar 與 epub 骨子裡都是 ZIP 壓縮檔,所以全都以 ZIP 的簽章開頭;要分辨它們得看裡面的項目。Java class 檔和 macOS 的通用二進位檔都以 CA FE BA BE 開頭,靠緊接其後的欄位區分。

有完全沒有 magic number 的檔案嗎?

有。XML、HTML、JSON、SVG、CSV 這類以文字為基礎的格式沒有固定的位元組簽章,所以改用結構來辨識:開頭的 <?xml 宣告、<svg 元素,或是 { 後面接著帶引號的鍵。這種偵測是合理推測而非確定,因此本參考頁會把這些格式標示為結構偵測。

magic number 相符就代表檔案安全嗎?

不代表。它告訴你的是格式,不是內容是否無害 — 一個貨真價實的 PDF 或 docx 仍然可能夾帶惡意內容。辨識真實類型是有用的第一道檢查,尤其在副檔名和位元組不一致的時候,但它不是惡意軟體掃描。

手上有檔案可能是 Matroska?用檔案類型辨識工具查出來 — 它在本機讀取 magic number,不上傳任何東西。或者瀏覽所有格式。