更新日期 2008-06-08 20:41
新消息
伺服器選擇
雜談
如何架設網站
超頻+省電
Prime95 地獄特訓
AV 心得篇
影音編輯
場景順序
DVD 字幕
歷史
2005-01-20 影音處理談「解決 A/V 不同步」

歷經了幾十分鐘、甚至幾個小時不間斷的連續錄影後,終於將影像錄影完畢,接下來最想看的就是:錄製的結果如何?嗯‧‧‧一開始聲音與影像完全符合,達到同步,可是當影像時間慢慢的增加後,嘿嘿嘿‧‧‧竟然發生不對嘴的現象,這‧‧‧太殺風景了啦!

刪除影像重新錄?恐怕沒有那個美國時間了,或是要等到下一次電視重播‧‧‧種種煩死人的事在腦海中湧了出來;究竟為什麼一開始影音同步,越到播放到後面就越來越荒腔走板呢?以下是幾個原因:

  • 錄製時 CPU 使用率達到 100%,造成錄影程式沒有將影像與聲音滑順的結合在一起
  • 聲音取樣參數設定錯誤。國外不少討論區都有人提到 Creative SoundBlaster Live! 在 44100Hz 表現不如 48000Hz 穩定;有幾塊如果錄製特定取樣頻率的聲音時,會容易發生不同步的現象,所以要更換取樣參數
  • 影像壓縮器忙不過來,造成 Drop Frame (有時候不會被錄影程式偵測到),這其實可能又有幾種可能:
    • 錄製時使用一些會影響運作的東西,像是聽 MP3、看影片、存取 USB 界面裝置、上網路、傳檔或跑 P2P‧‧‧等等,一般而言錄製時枯燥乏味,但為了減少將來的後悔,減少後製作的難度,還是安分守己的睡覺吧。
    • 影像壓縮器不適合進行 Real Time Capture,誰呢?Xvid、DivX、WMV‧‧‧等等,這類壓縮器適合後製作時,細細品味影像內容後再來壓縮 (也就是 2-pass);所以請改用如 Huffyuv (這是 loseless 非失真壓縮法!)或是 PICVideo (飛馬牌) Motion JPEG Codec、亦或是 Morgan Motion JPEG Codec、當然還有其他不錯的「低壓縮率、低失真率」的 M-Jpeg Codec,都很適合錄影時「輕微的」壓縮一下,以保持畫質供後製作使用。
  • 「起始性誤差」:一開始就發生不同步了 (這是最常見、也最容易解決的)
  • 「累積性誤差」:隨著錄影時間的增加,不斷累積微小不同步秒差 (都是千分之幾秒)。因為錄影時間長,這些誤差累積的結果,造成了巨大的誤差 (幾秒!)

每個人對於影音同步的敏感性不同,以筆者的自己的經驗,超過 200ms 的誤差很容易被發現。可是每一次錄影時,影音不同步又是難免的,這實在很傷腦筋。於是有幾種解決方案:

  • 「分段同步法」:土法煉鋼的手工調整法,藉由調整 VirtualDub.Interleaving.Delay audio track by XXXX ms 來解決,進行分段同步。只要某一區段的影音是同步的 (頭尾很可能誤差超過 100ms,但有些場景不容易發現,矇混過去),立刻輸出這一區段,然後以此類推將影片全部「分段同步」完。(當然得準備足夠的空間才行)
  • 使用 Adobe Audition (舊版是 CoolEdit),將影像時間長度除聲音時間長度,得到 tempo 值,使用 Time/Pitch.Stretch 功能,將整個聲音重新處理 (這個 Uncompress WAV 是個體積很肥的怪物),在硬碟一陣哀號聲後,製造出另一個差不多肥的新怪物,然後重新 Dub 進影像中,是看看「有否同步?」
  • 使用 VirtualDubMod + AviSynth 聯手出擊!超硬派的影音同步法!以下是詳解→
VirtualDub + AVISynth 2.5 手動影音同步法

解決「起始性誤差」的方法→多錄幾個長時間的檔 (強烈建議錄電視新聞台,也請別刪除掉,等一下還有用處),將開始就不同步的時間用紙記錄起來 (這些秒差值完全憑您自己感覺,您認為同步就是同步了,所以要錄電視新聞,容易看出主播的唇型與放出來的聲音是否同步),僅可能找出平均值,設定 DelayAudio(XXXX)。

利用 VirtualDub.Interleaving.Delay audio track by XXXX ms 將方才抓出的「起始性誤差」參數填入,然後接下來要處理的是「累積性誤差」,這是最令人頭痛的問題,但有幾個方法可以抓參數:

  1. 將播放時間移至最後面一個容易看出說話者唇型的片段,逐步調整 VirtualDub.Interleaving.Delay audio track by XXXX ms 的時間,直到完全對嘴為止,假設為 YYYY ms。記錄下這個 YYYY-XXXX 的值,並且記錄下影片放映的時間點,如 59min24sec 時用參數 700ms 對嘴成功,起始誤差值為 100ms,則累積誤差是 600ms。這時候用 600ms/59min 得到 10ms/min 的平均累積誤差值。
  2. 重複將所有影片的最後一部份對嘴成功。
  3. 檢視每一個影片的平均累積誤差值是否十分接近,如果是→恭喜您!累積性誤差值已經找出來了。
  4. 假設就是 10ms/min 這個值,則聲音播放速率要調快 100 + (10ms / 1000) = 100.0010這個比率,設定 TimeStretch(tempo= 100.0010) 即可得到整個影片完全同步的效果。如果您得到的結果是 -10ms/min 代表聲音快過於影像,則設定值是 100 - (10ms / 1000) = 99.990。

如果這個方法可行,每一次只要自行計算出 tempo 值,將它改寫在載入的 script 內即可;只不過這個方法仍然不夠「懶」,參考下方這個「更加硬派」的超懶辦法作法→不經手的自動影音同步法。

VirtualDubMod + AVISynth 2.5 超硬派自動影音同步法

首先要解決「起始性誤差」,同上面所述,設定 DelayAudio(XXXX) 參數。這部份已經是常數了,所以不用再修改了。

「累積性誤差」往往可由 VirtualDub.File.File Information 的 Video stream length 時間部份參數與 Audio stream length 時間部份參數看出端倪。如果這兩個參數的秒差不少,那影片快結束時應該有很明顯的不同步。使用這個方法的前提是,「累積性誤差」必須為常數,也就是一個平均值,每台電腦搭配的捕捉卡與捕捉程式,都會有不同的常數 (當然也會有不同的起始性誤差值);如果「累積性誤差」值飄忽不定,甚至伴隨著 Drop Frame,那請用「分段同步法」。

藉由計算影像部分時間與聲音部分時間的差距值,換算出對應的 tempo 參數,這個方法上面已經說過了,原理也大致說明了,只是上面的方法必須自行取得時間值,再自行計算出對應的 tempo,再自行修改 script,有點給他麻煩,所以現在要大量運用 AviSynth 的 script 語言,做出一個自動會抓參數的 script,自動算出 tempo 並且載入不同的影像檔。

首先,請注意題目是「VirtualDubMod」而非「VirtualDub」。這兩者的差異在 mod 版是修改原始版本的程式碼,加上很多強力的新功能,如 mod 版允許直接修改並載入 AviSynth script 的 template(模板)、mod 版還允許聲音串流加入 AC3, MP3(CBR,VBR),OGG, DTS, SRT 等等多種主流的格式,mod 版的影音輸出格式還支援很熱門的新興影音容器→Matroska (MKV) 與 OGG Media (OGM),這些都是 mod 版本強力的地方。只要是原始版本 (v1.5.10) 有的能力,一樣也沒縮水,再外加很多強力且實用的功能,所以筆者已經不知道多久沒用 VirtualDub 這個原始版本了。(目前 VirtualDub 已經出至 v1.6.3, 不過原作者不斷的提醒說那是「實驗版」,不要用來真的輸出成品,優點是 64-bit 原生版本也已經出現了,看來不久之後等原始版本成熟後,K8 64-bit 狂壓檔案的時代也來臨了)

首先 AviSynth 內部定義了一些參數,筆者將幾個重要的列出來,她們是:

  • FrameCount (影像格數目)
  • FrameRate (影像播放速率)
  • AudioLength (聲音取樣長度)
  • AudioRate (聲音取樣速率)

有了這四個參數,就能變出一些花樣了→

  • 影像播放時間 = FrameCount 除 FrameRate
  • 聲音播放時間 = AudioLength 除 AudioRate

這樣就輕鬆的取得了影音兩者的關係,然後將他轉為 tempo 值輸出給 TimeStretch 函數即可。但是筆者發現了一個有趣的現象,就是這個自動計算的 tempo 值,必須加上一些「經驗常數」 ,也就是說當 tempo 值被轉換出來以後,「大體上來說」已經是「自動對嘴了」,但仍覺得聲音有一點延遲或提前,必須要自行試驗幾段不同長度的影像後,找出符合所有不同影像的共用「經驗常數」,然後就可以得到完美的「自動影音同步 Script」了!經歷過一點時間的調較以後的 AviSynth [Auto-AV-Sync] Script,保證讓每一次錄影後的結果,都是自動影音同步的狀態。

說了這麼多,看倌們趕緊自行製造您專屬的 script 吧。