字體:小 中 大 | |
|
||||||||||||
2008/03/15 12:23:17瀏覽92368|回應15|推薦40 | ||||||||||||
生人迴避!
事情源自兩三年前。有同事到國外參展,在同業攤位當「死敗」偷拍重要情資,自己卻不小心刪除。所幸這人還算精乖,拍了幾張照片後察覺不對,趕緊把記憶卡抽掉,想辦法搶救。結果檔案雖然救了回來,影片內容卻無法播放。不死心抓了幾個影片修復軟體,都豎白旗投降。由於敝人先前有和影音軟體打交道的經驗,這位老兄就把毀損的影片檔拿來,問我有沒有辦法救。 一看之下,原來影片檔的「七寸」被掐碎了。檔案頭尾的重要資訊毀損大半,難怪影片修復軟體都寧願放棄。好在影音資料區還有七八成沒壞,於是寫了兩三支小程式,硬是把堪用的部份還原給他,功德圓滿。可惜公司不做這方面,產品化也有實質困難,只好把過程記下,孤芳自賞一番啦。 (對技術細節無興趣者,可直接跳到末段) 這篇重點是談技術,不是介紹軟體;討論的是方法,而不是產品,目的在解決一個特定問題。 影片檔毀損的原因,包括檔案傳輸複製過程的錯誤疏失,和儲存媒介(如硬碟、光碟、記憶卡)的毀損或錯亂。毀損的位置和範圍通常無可預測,加以資料量龐大,需要以程式檢測修復。 修復各種影片檔的軟體很多,網路上不難找;有些是自由軟體,多數要付點費用。然而無論收費與否,大部份軟體遇上這個問題的反應是一致的,也就是兩手一攤,宣告不治。 什麼問題呢?就是萬一影片檔的檔頭毀損,還能不能救? 這個問題的答案要看影片檔的格式。來自VCD或DVD的MPEG檔案,由於編解碼器(CODEC)及其參數固定或變化有限,問題較小,救回的機率較大。相對而言,屬於container格式的AVI或RM檔案,CODEC資訊放在檔頭,一旦損毀就無法解碼。本篇的重點就放在這兩種格式。
圖一,影片檔的基本結構 上圖只是示意,並不符合實際比例。檔頭部份通常只有幾百上千個byte,相對動輒以MB甚至GB計算的資料區來說,比例小之又小,遭到毀損的風險也低。然而檔頭包含解碼所需的重要資訊,一旦損失,靠盲目猜測救回的機會卻又不高。難怪各種修復軟體寧可放棄。 靠人工有沒有機會呢?答案是有,但仍然需要許多程式幫忙。在討論如何搶救之前,先瞭解有關影片檔結構的基本知識,會比較有幫助。 觀念 AVI和RM是所謂container格式,意思是說,抽象觀念上它們只是一連串記錄(record)的組合,至於如何詮釋記錄,則是播放程式的工作。
圖二,影片檔由連續的記錄組成 每個記錄的開頭,通常至少包括一個表明記錄型態的標籤(Tag),以及記錄的長度(Length)。記錄本身可以是另一個container,包含其他記錄。一如前述,如何詮釋記錄,是播放程式的工作。修復程式的工作,就是將檔案恢復到播放程式能夠判讀的程度。
圖三,單一記錄的結構 為了簡化,這裡只討論AVI和RM格式的基本型,衍生加強的型態暫不考慮。詳細的格式資料請看參考文件,此地也不深入討論。 如圖一所示,基本型包括三大塊記錄,即檔頭、資料和索引。資料區是骨幹,包含若干個影音流(stream),通常會有一個視訊流(video stream)和兩聲道的音訊流(audio stream)。影音流資料量大,一般會切割成小塊以便處理。視訊以畫面為單位,音訊則視CODEC而定。 視訊資料幾乎沒有不壓縮的,絕大多數現代的壓縮法,都採用立體壓縮,亦即前後畫面交互參照,消除相同部份,以求最大程度的壓縮比。這種方法會每隔若干畫面設立一個主畫面。理論上說,當場景變化(scene change),就是設立主畫面的好時機,因為畫面變化大;實際得看CODEC如何施作。這部份屬於視訊壓縮的範疇,在此略過不提。音訊資料壓縮與否都有可能,通常切割成小塊和視訊流交錯排列,為的是避免播放程式讀取大檔案時來回移動浪費時間。 索引存在的目的,是當使用者任意選擇播放點的時候,程式可以迅速移動,找到指定的影音資料位置。如果有主畫面的設置,索引中存放的可能是主畫面的位置;也可能按固定間隔,比方說,一百筆記錄,安排一個索引。理論上說,索引並非不可或缺,然而很多播放程式發現索引不正常就哇哇叫甚至當掉。 播放時重要的是影音必須同步,否則對不上嘴事小,音響效果慢了半拍,味道就差多了。檔頭存放資料區的影音流起點、記錄總數、時間長度、CODEC及其附帶參數等資料。AVI和RM都假設影片是連續資料流,每筆記錄並沒有個別的時間戳,播放的時機和同步,都靠個別記錄和起點的相對距離來決定。當資料區遭受破壞時,這是不容易解決的問題。 破壞的型態和坊間修復程式的作為 索引遭到破壞,是最容易解決的問題,修復程式最擅長的也是這個。只需要讀取檔頭中各資料流的起點,整個檔案掃瞄一遍,索引就可以重建。甚至有些耐操的播放程式,如VLC,根本不加以理會,自行在記憶體中重建。 資料區的破壞,當索引仍然完整的時候,可以利用索引所記錄的位置,試圖評估損害,決定那些區域可以修復,同步的問題也比較容易掌握。如果索引不存在,當資料區被破壞時,重建也沒有意義,唯一的辦法是掃瞄資料區。由於影音流都是連續的,裝載資料的每筆記錄都有特定的標籤,和下一筆記錄的位置。先找尋特定標籤,再根據下一筆記錄的位置察看是否正確,反覆執行可以得到若干資料流片段。只不過影音流破壞的程度不一致,又缺乏索引做參考,同步問題極可能發生,甚至可能很嚴重。有些修復程式會試圖復原找到的第一塊資料流,而將其後全數捨棄,免得結果看起來令人不悅。 檔頭被破壞時,會產生幾個重要問題。首先各資料流的起點和總數會成為一個謎。這時候如果索引保持完好,可以提供參考。但由於檔頭通常很小,破壞則至少以幾個KB為單位,開頭的若干損失在所難免。萬一沒有索引可參考,靠掃瞄資料區也有機會找出答案,不過同步仍然是個問題。比較致命的是CODEC及相關參數,相信這是大多數修復程式束手無策之處。自古至今,CODEC的種類沒有一百也有八十。在沒有任何參考的情況下,可能的排列組合太多,放棄還比較輕鬆一點。 對策 這次工作的重點有二。第一是當檔頭損毀時設法重建,第二是儘可能恢復所有可用的影音資料,換句話說,萬一資料區被斷成好幾截,試圖將之儘量復原。 前面說過,一般修復程式在沒有任何參考的情況下,只好選擇放棄。如果我們有同一來源的其他檔案可參考,比方說出自同一台數位相機或製片軟體,將檔頭拷貝過來,可以解決CODEC參數的問題,至少縮小嘗試的範圍。當然資料流起點長度等資料,需要寫一個程式去掃瞄,這支程式同時分析出可用片段和主畫面的位置等。 萬一沒有可供參考的檔案,得要猜測,我們把視訊和音訊個別處理。利用前一支程式分析出、尚可使用的資料片段,以另一支程式調整各項參數試圖解碼。錯誤的CODEC可以經由這個程序過濾掉。找出正確的CODEC之後,再微調各項參數到輸出正確為止。其實時至今日,CODEC百家爭鳴的時代已經過去,除非檔案來源十分古老,否則應該不需要猜測到十次以上。 倘若運氣好,所有片段都能找出來,並且正確解碼,接下來要處理的,就是同步問題。若太過殘缺,又沒有原始索引供參考,恐怕就只能靠人工。用一支程式把原始檔的影音分離,各片段獨立建檔,再利用製片軟體重新接合,或許是比較可行的方式。當然如果資料大體完整,或同步與否沒那麼重要,那麼直接連綴再重建索引,也就可以了。 單以這次任務來說,由於數位相機還在,CODEC部份用不著猜測,解碼不費吹灰之力。然而資料斷成好幾截,同步就很困難了。好在同事只要得到視訊部份就很高興,音訊直接捨棄。是故文末兩段提到的方法只是構思而未實作,那也是產品化的困難所在。講得明白些,這種成功率沒法兒掛保證的事,充其量只能是「殺必死」;就像你把摔破的NB送到維修站,能活命就偷笑了,缺胳膊斷腿也只能摸摸鼻子認賬。 抱歉沒有附圖。手邊書籍當然有,不過都有著作權,不便翻貼。在Wikipedia也沒看到,而且,最重要的,自己作圖好累。還請看倌多多包涵。 |
||||||||||||
( 知識學習|科學百科 ) |