瞭解視訊軌道的元件
此示例將探討如何檢視視訊軌道的佈局以及如何在其中提取單個圖片。
這裡使用的樣品內容是 Blender Foundation 的 Tears of Steel 。具體來說,我們將使用名為“HD 720p(~365MB,mov,2.0)”的下載。這是一個以副檔名 mov
結尾的單個檔案,幾乎可以播放任何現代媒體播放器。
我們將使用 Bento4 套件中的 mp4info 和 mp4dump 工具進行軌道佈局和結構分析,使用 FFmpeg來提取構成視訊軌道的單個圖片。
樣本電影使用 QuickTime
(MOV)打包格式,該格式基於 ISO 基礎媒體檔案格式 - 這是 MP4 檔案格式系列中所有打包格式的基礎的國際標準。這使其與大多數可用工具高度相容,並且易於分析。
我們首先檢查檔案的整體結構。基於 ISO 基礎媒體檔案格式的所有媒體檔案都被構造為一個盒子層次結構 - 一個微型檔案系統。使用 mp4dump 實用程式通過執行以下命令來提取框結構:
mp4dump tears_of_steel_720p.mov
輸出將類似於以下內容:
[ftyp] size=8+12
major_brand = qt
minor_version = 200
compatible_brand = qt
[wide] size=8+0
[mdat] size=8+371579623
[moov] size=8+598972
[mvhd] size=12+96
timescale = 1000
duration = 734167
duration(ms) = 734167
[trak] size=8+244250
[tkhd] size=12+80, flags=f
enabled = 1
id = 1
duration = 734167
width = 1280.000000
height = 534.000000
...
這表示檔案的內部結構。例如,你在這裡看到一個 moov 框,它有一個 8 位元組的標題和 598972 位元組的內容。此框是用於描述檔案內容的各種後設資料框的容器。有關各種盒子及其屬性含義的更多資訊,請參閱 ISO / IEC 14496-12 。
實際的媒體樣本本身 - 壓縮的圖片和音訊波形 - 儲存在 mdat 框中,其內容對 mp4dump 實用程式是不透明的。
要排除不相關的資料並簡化分析工作流程 - 此示例主要關注視訊軌道 - 我們現在從示例影片中刪除音軌。執行以下命令:
ffmpeg -i tears_of_steel_720p.mov -an -vcodec copy video_track.mov
請注意,上述步驟還將從輸入視訊中刪除各種自定義擴充套件元素,將可視內容的本質打包到新的容器檔案中並丟棄其他任何內容。如果你在生產場景中執行此操作,請確保你真正可以放棄輸入檔案中的所有其他元素!
編碼視訊軌道是一系列圖片。使用此處使用的 H.264 編解碼器 - 以及所有其他常用的現代編解碼器 - 圖片可以是各種不同的型別:
- I 影象 - 這些是獨立影象,僅使用影象中包含的資料可解碼。
- P 影象 - 這些影象將另一張圖片作為基線並對該影象應用變換(例如“將這些特定畫素向右移動 5 個畫素”)。
- B 影象 - 類似於 P 幀,但是是雙向的 - 它們還可以參考未來的影象並定義變換,例如“這些在 5 幀中完全可見的特定畫素現在是 10%可見”。
圖片型別的精確組合可以由編碼工作流程自由選擇,產生許多優化機會,儘管某些用例可能通過例如要求 I 幀以恰好 2 秒的間隔存在來約束可用的靈活性。
執行以下命令檢視視訊軌道的圖片結構:
mp4info --show-layout video_track.mov
除了呈現整個檔案後設資料的人類可讀形式之外,你還將看到視訊軌道圖片佈局的詳細列印輸出。
...
00000959 [V] (1) size= 7615, offset=15483377, dts=491008 (39958 ms)
00000960 [V] (1)* size=104133, offset=15490992, dts=491520 (40000 ms)
00000961 [V] (1) size= 16168, offset=15595125, dts=492032 (40042 ms)
00000962 [V] (1) size= 4029, offset=15611293, dts=492544 (40083 ms)
00000963 [V] (1) size= 24615, offset=15615322, dts=493056 (40125 ms)
00000964 [V] (1) size= 4674, offset=15639937, dts=493568 (40167 ms)
00000965 [V] (1) size= 18451, offset=15644611, dts=494080 (40208 ms)
00000966 [V] (1) size= 95800, offset=15663062, dts=494592 (40250 ms)
00000967 [V] (1) size= 30271, offset=15758862, dts=495104 (40292 ms)
00000968 [V] (1) size= 10997, offset=15789133, dts=495616 (40333 ms)
00000969 [V] (1) size= 28458, offset=15800130, dts=496128 (40375 ms)
00000970 [V] (1) size= 9593, offset=15828588, dts=496640 (40417 ms)
00000971 [V] (1) size= 24548, offset=15838181, dts=497152 (40458 ms)
00000972 [V] (1) size= 6853, offset=15862729, dts=497664 (40500 ms)
00000973 [V] (1) size= 27698, offset=15869582, dts=498176 (40542 ms)
00000974 [V] (1) size= 7565, offset=15897280, dts=498688 (40583 ms)
00000975 [V] (1) size= 24682, offset=15904845, dts=499200 (40625 ms)
00000976 [V] (1) size= 5535, offset=15929527, dts=499712 (40667 ms)
00000977 [V] (1) size= 38360, offset=15935062, dts=500224 (40708 ms)
00000978 [V] (1)* size= 82466, offset=15973422, dts=500736 (40750 ms)
00000979 [V] (1) size= 13388, offset=16055888, dts=501248 (40792 ms)
00000980 [V] (1) size= 2315, offset=16069276, dts=501760 (40833 ms)
00000981 [V] (1) size= 21983, offset=16071591, dts=502272 (40875 ms)
00000982 [V] (1) size= 3384, offset=16093574, dts=502784 (40917 ms)
00000983 [V] (1) size= 22225, offset=16096958, dts=503296 (40958 ms)
...
此列印輸出中的每一行都是視訊軌道中包含的圖片。那些用星號標記為 (1)*
的是 I-pictures。你可以看到它們的大小最大,其他的通過引用現有圖片來實現更大的壓縮,並且僅描述差異。
該列表還包含視訊檔案中影象資料的偏移和影象的解碼時間戳,從而實現進一步的相關和分析。注意,圖片的解碼順序/定時不一定與呈現順序/定時相同! 如果視訊中存在 B 影象,它們只能在它們引用的任何影象之後進行解碼,即使它們出現在參考影象之前 !
在深入瞭解視訊軌道的結構後,執行以下命令將從 40 秒標記開始的 30 張圖片解壓縮為 PNG 檔案:
ffmpeg -i video_track.mov -ss 00:00:40 -vframes 30 picture%04d.png
提取的影象將被完全解碼,因為它們將出現在視訊播放器中 - 不可能(沒有極其專業的工具)在 P 幀或 B 幀中獲得原始資料的直觀表示。
觀察視訊中第 7 個生成的圖片是如何完整的場景變化。你可以輕鬆地將其與上面的 mp4info 輸出相關聯 - 從 40 秒標記(編號 00000966)開始的第 7 張圖片的尺寸遠大於靠近它的圖片。場景更改很難編碼,因為它們會重新整理整個影象幷包含大量新資料。如果編碼器沒有給予足夠的寬容來優化場景變化(即不允許生成大圖片),則視覺輸出將是低質量或塊狀直到下一個 I 影象。通過檢查各種圖片的頻寬(位元組)分配,你可以深入瞭解可能突然出現在視訊中的視覺偽像。