ByteScope

WebM 檔案格式

以 Matroska/EBML 為基礎、開放且免授權金的視訊容器。

MIME 類型
video/webm
副檔名
.webm
分類
影片

Magic number(檔案簽章)

0x000000001A45DFA3·E··EBML header

開頭附近的 EBML DocType 字串是 'webm'(MKV 則是 'matroska')。

關於 WebM 格式

WebM 是 Google 為 HTML5 video 定義的免權利金容器,把 VP8、VP9 或 AV1 的畫面搭配 Vorbis 或 Opus 的聲音。與其說它是新格式,不如說它是被刻意收窄的格式:WebM 就是 Matroska 把編碼清單砍到只剩不必授權就能出貨的那些,而兩者的 EBML 編碼一個位元組都不差。EBML 是 XML 的二進位表親 — 每個元素是一個變動長度的識別碼、接一個變動長度的大小,然後不是一個值就是更多元素 — 這代表 WebM 檔案除了最前面幾個位元組之外沒有固定排版,剖析器只能一路走過去,不能直接跳著索引。檔案以 EBML 標頭開場,那是一個描述其餘部分怎麼編碼的小型 master 元素,而裡面的 DocType 字串,是唯一把 WebM 和純 Matroska 分開的欄位。

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

位移長度欄位意義
04EBML master element ID1A 45 DF A3。這就是全部的 magic number,而且和 Matroska 完全共用;它也是檔案裡唯一保證落在固定位置的位元組串。
41EBML header size一個變動長度整數:開頭那個 1 位元表示它只有一個位元組長,剩下七個位元是值。9F 是 31,也就是後面那段標頭本體的位元組數。寫入端可以把這個整數補到多達八個位元組,所以請把它當成一到八個位元組,而不是剛好一個。
54EBMLVersion element42 86 81 01 — 兩個位元組的元素識別碼、一個位元組的大小 1,以及值 1。EBML 標頭裡每個元素都有預設值、也都可以整個省略,所以從這裡往下的位移,是典型寫入端會產出的樣子,而不是規格釘死的位置。
94EBMLReadVersion element42 F7 81 01。讀取端至少要實作到哪個版本,才有辦法看懂這個檔案。從這個格式發表以來它一直是 1。
134EBMLMaxIDLength element42 F2 81 04。這個檔案裡最長的元素識別碼有幾個位元組。四是通用值,剖析器可以拿它來決定緩衝區大小。
174EBMLMaxSizeLength element42 F3 81 08。這個檔案裡最長的大小欄位有幾個位元組。八是標準值,也是下面講的那個「未知大小」編碼寬度是八個位元組的原因。
212DocType element ID42 82。指名這其實是哪一種以 EBML 為基礎的格式的元素,也是 WebM 檔案和 MKV 檔案光看前二十個位元組分不出來的原因。
231DocType length84 — 一個位元組的變動長度整數,值是 4,也就是後面那個字串的長度。在 Matroska 檔案裡這個位元組讀到的是 88,因為 'matroska' 有八個字元,而它後面每個位移都往後移四。
244DocType value77 65 62 6D,ASCII 的 webm 四個字母。決定格式的就是這個欄位。它前面的東西在 Matroska 檔案裡完全相同,它後面的東西排法也完全一樣。
284DocTypeVersion element42 87 81 02。寫入端用的是 WebM 元素集的哪一個版次。支援版次較低的讀取端,被期待的行為是跳過它不認得的元素,而不是直接失敗。
324DocTypeReadVersion element42 85 81 02。讀取端至少要到哪個版次才有辦法剖析這個檔案 — 這跟「看懂裡面每一個元素」是兩回事。
364Segment element ID18 53 80 67,裝著這個檔案裡每一條軌、每個 cluster、cue 和 tag 的容器,實際上就是整份內容。它的大小欄位緊接在後,而在一個正在即時寫入的檔案裡,那個大小是全部位元皆為 1 的未知形式。

怎麼跟長得像的格式分開

容易搞混的怎麼分
Matroska兩者是同一套編碼,差別只在位移 24 的 DocType 字串:'webm' 對上 'matroska'。還有一個更早就看得到的捷徑,在位移 4 — 因為 Matroska 的 DocType 多四個字元,那裡的 EBML 標頭大小位元組讀到的是 A3(35),WebM 則是 9F(31)。實務上的差別在編碼:Matroska 檔案可以裝 H.264、HEVC、AC-3 或 DTS,這些都不該出現在 WebM 裡,而瀏覽器即使剖析得動容器,也一樣會拒絕它們。
MP4結構上毫無關係。MP4 是一棵 box 樹,大小是大端序 32 位元,magic 在位移 4;WebM 是 EBML,每樣東西都是變動長度,magic 在位移 0。混淆完全發生在副檔名層級,因為兩邊都裝得下 AV1 和 Opus、也都能在現代瀏覽器裡播,所以檔案就被人在兩者之間亂改名,然後打不開。
MKA所謂 .mka 就是一個只有音軌的 Matroska 檔案,.mks 則是只有字幕的。兩者都沒有任何能分辨的標頭位元組 — DocType 讀起來仍然是 'matroska' — 所以唯一的辦法是走進 Tracks 元素、讀每條軌的類型。純音訊的 WebM 也一樣,而那正是瀏覽器從麥克風錄音時產出的東西。
Ogg同時代另一個免權利金容器,位元組層級毫無關係:Ogg 檔案位移 0 就是大寫 O 開頭的頁面標記 4F 67 67 53。Ogg 用一套為串流設計的 page 與 granule 結構裝 Vorbis、Opus 和 Theora,WebM 則繼承了 Matroska 的 cluster 與 cue。

常見的壞法

  • 沒有長度的即時錄影。瀏覽器透過 MediaRecorder 錄音錄影時,不可能事先知道 Segment 會有多長,所以它寫的是未知大小形式 — 大小整數的每一個值位元都設成 1,在 EBML 正是為此允許的八位元組編碼裡就是 01 FF FF FF FF FF FF FF。這個檔案完全合法,也完全不能 seek:播放器顯示不出長度,進度條在重新封裝之前拉不動。
  • 沒有 Cues。這個 seek 索引是選用元素,而串流寫入端根本沒有機會把它附加上去,所以從即時來源擷取的 WebM 從頭播得動、卻跳不了。這裡沒有任何東西壞掉;只要複製串流、順便寫出一個 Cues 元素的重新封裝,就能修好,而且不必動到任何一格壓縮後的畫面。
  • 截斷。因為每個元素都宣告自己的長度,讀取端會很順地走到最後一個完整的 cluster,然後碰到一個承諾了不存在的位元組的大小。多數播放器把解得出來的部分放完就停;有些則把整個檔案報成損壞 — 所以同一個被截斷的檔案,在兩個工具裡的行為才會不一樣。
  • 容器看起來對,裡面的編碼卻不對。DocType 說自己是 webm、軌裡裝的卻是 H.264 的檔案,在任何有意義的角度上都不是 WebM。它剖析得動、hex dump 看起來也乾淨,而每個瀏覽器都拒絕它 — 對不上的地方在 Tracks 元素裡的 CodecID 字串,不在標頭的任何位置。
  • 前面被塞了垃圾。一頁被存成 .webm 名字的 HTML 錯誤訊息,會讓本該是 1A 45 DF A3 的地方變成看得懂的文字。跟 MP4 不同的是,WebM 裡面沒有記錄任何絕對的檔案位移可以被弄壞,所以只要把開頭那幾個位元組刪掉,檔案通常就是完整的。

這個格式現在還在用嗎

WebM 存在的理由是 H.264 要收授權費,而它在「給開放網路一個不必付錢的影片格式」這件具體任務上成功了。每個瀏覽器都播得動它,而網頁在錄螢幕、相機或麥克風時,瀏覽器產出的也是它。它完勝的場合是開放網路上的 VP9 與 AV1 交付,以及用 Opus 的音訊 — Opus 在低位元率下贏 AAC 贏得夠多,對語音來說有實質差別。它輸的則是所有牽涉到硬體和 Apple 的地方:Safari 的支援來得晚、而且一直只有一半,手機用矽晶片解 H.264、VP9 有時才有,而沒有任何電視、相機或剪輯軟體把 WebM 當一等公民。實務上網站兩種都送 — 要 WebM 的瀏覽器給 WebM,其他一律 MP4 — 而如果只能留一種,留下的還是 MP4。

在這個站上打開 WebM 檔

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

相關格式

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

格式開頭位元組副檔名
Matroska1A 45 DF A3.mkv
MP466 74 79 70.mp4
Ogg4F 67 67 53.ogg

常見問題

檔案的 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 仍然可能夾帶惡意內容。辨識真實類型是有用的第一道檢查,尤其在副檔名和位元組不一致的時候,但它不是惡意軟體掃描。

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