如何快速替換錄影檔案中的聲音

4月 26, 2017
我是預設的預覽圖,不使用可以整段刪除

Hi 大家好,我是Denny,今天來跟大家分享一下我處理現場錄音錄影的後期流程。

試著想像一個情況:
樂團演出的時候有現場的錄影,也有現場PA台的錄音,在演出後要如何快速簡單地把二者合併,讓現場PA台的錄音可以"高品質"融入錄影的環境音,並且放到網路上跟其他人分享呢?



當我一開始面對這個課題的時候,曾經想過幾個可能的解決方式,例如:


A. 使用影片編輯軟體(例如Final Cut Pro或Premiere),把現場錄音的音軌疊進去錄影的音軌內。
這個作法是早期在GuitarBox in Starbucks使用過的作法,但應用在La Cozzi樂團的現場錄影會面臨幾個無法克服的缺點,像是:

  1. 影片編輯軟體的混音功能有限,對於大家在混音和後期會使用的plug-in的支援也不盡然全面,會造成聲音處理綁手綁腳的問題,特別是對聲音標準要求比較高的時候。
  2. 無法避免最後在匯出的時候因為原始編碼和目標編碼轉換造成的畫質損失,更重要的是這需要超級無敵大量的運算時間才能做到,儘管事實上影像根本沒有動過。

基於以上理由,加上我的電腦其實也舊了,就完全不想使用這個方式處理,因為我的電腦可能要算很久很久才能算完。

於是就有了下一個想法:

B. 使用支援影像輸入的混音工作站(DAW),像是Cakewalk Sonar或是Presonus Studio One,來實現高品質的聲音處理,然後再將合併後的音軌連同影像輸出。

但這個作法也很快被我排除,因為我手邊可以使用的Sonar和Studio One的影像匯入功能都不好用,加上無法避免最後需要花費大量時間運算輸出,所以就繼續想下一個解法。

C. 把錄影的聲音用影片編輯軟體輸出,匯入DAW,連同現場錄音一起處理以後再匯出成新的聲音,然後再匯回影片編輯軟體匯出。

這個作法聽起來很龐大但好像比較可行?其實也沒有,因為要如何在影片編輯軟體中選擇"一模一樣"的時間軸長度匯出成跟原始檔一模一樣的影片片段,本身就是一個挑戰,而且仍然無法避免萬一輸出和輸入編碼不一致的時候需要的大量運算時間。

綜合以上ABC方案的限制和缺點,截至目前為止,對我來說,符合我需求的處理流程(workflow)必須符合以下幾點:

  1. 可以使用常見或順手的DAW和plug-in單純處理聲音,而不用管原始影像(因為我的目的是聲音,其實不想動影像)。
  2. 可以避開影像重新編碼所需要的大量運算。
  3. 不改變原始影片檔案的時間軸和分段點。這點在團隊運作時特別重要,特別是聲音和剪接同時進行的時候。我相信負責剪接的人不會想要看到後期處理後的影片檔案跟從錄影機取出來的原始檔時間軸對不起來,這絕對是災難。

以上說了這麼多都還沒有切入重點,主要是想讓大家對接下來要分享的流程有更明確的概念,因為需要清楚知道每個步驟在克服的問題,才能讓這套流程可以活用。

好,所以接下來我會說明我的處理方式。

整套流程大約分成幾個部分:

  1. 把聲音從影片原始檔中取出,並轉換成DAW可以讀的格式,例如wav檔。
  2. 在DAW中把影片原始檔的聲音和PA台的錄音對齊和處理,然後匯出跟"原始檔聲音長度相同"的聲音檔案。
  3. 用處理過後的聲音軌道取代原始檔中的聲音軌道。

在這整套流程中,總共需要二樣工具:

  1. 免費的跨平台影音編碼工具 - ffmpeg
  2. 你所慣用的混音工作站和plug-in,如果只是想要合併的話也可以考慮用免費的AudacityStudio One Prime
我是在Windows 10下作業,但macOS和Linux也都有在ffmpeg支援的範圍內,同時也都有各自可以運作的DAW,這點大家使用自己慣用的工具即可,平台不是重點。


首先是如何"把影片中的原始檔取出"

這一個步驟全部使用ffmpeg完成。
將下載下來的ffmpeg執行檔跟影片檔案放在同一個資料夾內。

然後使用鍵盤上的Win + R,叫出執行,命令填入cmd,按下Enter,叫出提示命令字元模式。


接下來使用提示命令字元模式,把工作目錄切換到ffmpeg所在的目錄,目錄可以透過"單點"資料夾上方的名稱得到,例如我的就是"E:\LaCozzi working\20160115\mts" (注意下面第二張圖反藍的部分)。



接下來切回提示命令字元模式的視窗,輸入以下命令
cd /d 資料夾位置
以我的資料夾為例,就會是
cd /d E:\LaCozzi working\20160115\mts

然後按下Enter,這時候工作目錄就會切換過去了,可以看到命令列的開頭已經變成該資料夾的路徑。

這時可以輸入dir,並且按下Enter取得檔案列表,看看ffmpeg和影片檔是不是都有正確讀到,如果沒有看到檔案,有很大的可能就是路徑錯了,請再檢查一次。



接下來,使用以下命令,讓ffmpeg把影片檔中聲音軌道匯出
ffmpeg -i 影片檔名(含副檔名) -acodec copy 聲音檔名.ac3
以我的例子來看,匯出第一個檔案00020.mts的命令就會是
ffmpeg -i 00020.mts -acodec copy 00020.ac3
聲音檔名不用和影片檔名完全一樣,但我習慣用相同的命名方便管理。

按下Enter以後就ffmpeg就會開始執行,同時在影片同一目錄下產生以ac3為副檔名的聲音抽取檔。


接下來我們需要把ac3格式的聲音檔轉換成大多數DAW可以讀的wav檔,一樣使用ffmpeg的命令。
ffmpeg -i ac3檔名 wav檔名

以我的例子來說,第一個檔案的命令就是
ffmpeg -i 00020.ac3 00020.wav

接下來就會在目錄下看到一個相同檔名的wav檔產生。


好,到這裡為止已經太複雜了。

以上這段教學主要是要說明使用ffmpeg處理的原理,所以接下來我會提供一段批次命令來自動執行上面提過的步驟,完全略過自己打開提示命令字元模式和輸入指令這二道複雜又容易錯的手續,讓這套工作流程也可以由不熟悉命令列操作的朋友使用。

如果你不在Windows下作業,而使用macOS或Linux的話,請參考ffmpeg documentation查詢如何在這二個系統下調用ffmpeg,很抱歉我無法幫忙寫批次命令。

為了讓批次命令順利執行,原始檔資料夾需要依照底下或類似的方式安排,後面會說明如何改變編排方式。

mts: 放置原始的影片檔案
new_mts: 合併聲音後的影片檔案會放在這裡(後面會提)
wavs: 放處理過後的聲音檔案,依照原使影片檔名命名

ffmpeg則放在根目錄下,像以下這樣的安排。請忽略Studio One,那是我用來處理聲音的專案資料夾,與這個階段的ffmpeg處理無關。

接下來,請把以下的批次命令複製貼上到任何一個文字編輯器中,推薦使用Notepad++,然後存成一個bat檔案放在與ffmpeg同一個目錄下,我的例子是new.bat。
REM extract audio from mts files
for %%a in ("mts\*.mts") do ffmpeg -i "%%a" -acodec copy "%%~na.ac3"
pause
REM convert ac3 to wav
for %%a in ("*.ac3") do ffmpeg -i "%%a" "%%~na.wav"
pause
REM combine new wav with mts without offset (for the first file)
for %%a in ("mts\*.mts") do ffmpeg -i "mts\%%~na.mts" -i "wavs\%%~na.wav" -map 0:0 -map 1:0 -c:v copy -c:a ac3 -b:a 256k "new_mts\%%~na.mts"
pause
REM combine new wav with mts with offset 0.5
for %%a in ("mts\*.mts") do ffmpeg -i "mts\%%~na.mts" -itsoffset -0.5 -i "wavs\%%~na.wav" -map 0:0 -map 1:0 -c:v copy -c:a ac3 -b:a 256k "new_mts\%%~na.mts"
pause


請不要擔心那些批次命令很醜,因為根本不需要改任何東西就可以跑了。

批次命令共分成四段,分別對應整個處理流程中的三個環節。

第一段:REM extract audio from mts files

(REM是Windows批次命令的註解符號,只要由REM開頭的代碼就不會被執行,我們後面會用這個來控制執行的區段)
這一段代碼負責把聲音從放在mts資料夾裡面的影片原始檔"依序"取出,存成ac3檔案放在根目錄。

第二段:REM convert ac3 to wav

這段代碼負責把前一段取出的ac3檔案"依序"轉換為wav檔,一樣放在根目錄。

第三、四段:REM combine new wav with mts without offset

這二段代碼幾乎相同,是把放在wavs資料夾裡面的處理過後的聲音檔案"依序"轉換成ac3和取代原始影片檔案裡面的聲音,最後存在new_mts裡面。二段代碼的差別只有第四段加入讓聲音提前0.5秒的offset,後面會提適用情況。

回到我們目前需要使用ffmpeg處理的作業:從原始檔裡面取出聲音,然後轉換成wav檔。


對應的正式批次命令的第一段和第二段,我們需要依序執行這二段。
將除了第一段以外的代碼通通加上REM開頭,讓它們變成註解,如此便不會被執行。如果你使用Notepad++的話,可以圈選代碼行後,使用Ctrl + Q來切換註解會比較快,不用一行一行自己打。僅保留第一段取出聲音的代碼應該會長得像下面這樣:

這時候準備工作就完成了,確定有存檔,然後左鍵二下執行這個批次檔,這時提示命令字元會自動被叫出來,並在根目錄下產生ac3檔,得到像是下面這樣的結果:


看到Press any key to continue...的時候,就按任意鍵繼續吧!按任意鍵後視窗就會關掉。


接著如法炮製第二段代碼:把第一段代碼加上REM變成註解,然後刪掉第二段代碼的REM變成可執行,像下面這樣:


如此剛才取出的ac3檔案,就會被轉換成wav檔,一樣放在根目錄。


請把wav檔匯入你要使用的DAW內,然後ac3檔就可以刪掉了。

到此為止,我們已經從影片原始檔中取出需要的聲音片段,接下來就是在DAW中進行需要的編輯。

聲音的處理每個人喜好和取向都不同,底下簡單提供我自己的流程。

  1. 對齊現場錄影和PA錄音的時間軸。
    通常PA台錄音是連續不間斷的,所以就以這段錄音當成參考點,把從現場錄影擷取出來的聲音跟PA台錄音對齊。不管PA台錄音是多軌(stem)、立體聲(stereo)、假立體聲(fake stereo)、或甚至是單聲道(mono)。
    如果錄影機的聲音模式被設定在5.1等非stereo的模式,這一步就會出問題,需要先將多軌道的聲音mixdown到stereo,否則相位會出問題,細節和解決方式請參考另篇文章
  2. 我通常會先聽一下各軌道看有沒有需要修飾的頻率,如果有的話就會用EQ修掉。
    例如婚宴的現場錄音常常在100-300Hz之間會有過多的共振,可能低頻也有點過多,我就會直接用low cut filter去掉。
    我在處理修飾現場錄音類型的case的時候幾乎都是以EQ和Dynamic EQ為主,其他類別的效果器幾乎不會使用,確保處理後的聲音跟原本的差距不會太大或聽起來加太多料,畢竟是修飾和掩蓋缺點的目的。但這些都取決於手邊的素材,沒有一定的標準,請大家自行判斷。
  3. 下一步則是判斷不同錄音來源的聲音軌道有沒有存在相容性的問題,例如頻率打架,和非常重要一定要確認的相位(phase)是不是一致。
    頻率打架沒處理掉就只是難聽點而已,但相位沒弄好,聲音聽起來會很怪。這通常又跟攝影機相對於舞台擺放的位置,和PA台混音的panning和空間系效果器的使用有關,很難直接說出怎麼處理比較好,所以請注意phase meter的讀數,看看不同來源間是不是存在相位抵銷的問題。
    如果相位有問題,或者是聲音擺位(panning)有不一致的時候(例如攝影機放在側邊但現場PA把聲音都pan在中間),那二者錄到的聲音放在一起就很可能聽起來就會很怪,例如鼓明明就在左邊但聲音卻從中間出來。其中一種解決方式是直接把所有的錄音輸出都改成mono,讓大家的聲音通通擠回中間,再視情況用reverb重做空間,但這沒有鐵則,請大家依照實際的情況判斷處理。
  4. 決定不同軌道的相對音量。
    這點一樣沒有標準答案,有時候也是看伙伴對於現場音呈現的需求。在有多軌的情況下我通常都會先把fader拉到最底然後慢慢拉回來,在遠低於0dB的情況下調整不同來源的相對音量,有需要的話最後會再使用limiter把整體音量拉上去,但"盡可能避免改變動態範圍"。
    這個步驟在PA台錄音有錄好或是有取得分軌檔案的情況下彈性就比較大,但如果有其中一邊的錄音狀況不佳,決定相對音量就會稍微微妙(tricky)一點。
  5. 到這裡差不多完成,我會視情況在master out加上EQ修飾混在一起發現的問題,和掛上limiter避免有任何片段超出0dB造成破音。
聲音軌道對齊後的狀況,上方DV軌道為現場錄音,下方2017..晚宴錄音軌道為PA台錄音。


完成上述處理以後,就可以把聲音匯出。需要注意的是,為了配合批次命令的作業,請將檔案命名維持與原始檔檔名一致,然後放在wavs資料夾內。

每段匯出的長度必須與原始長度一致,下一步的合併才會正常。
在Studio One內可以透過開啟Loop Follows Selection的方式,自動在時間軸上標記每段影片錄音的起使和結束時間點。


再透過匯出時選擇Between Loop,得到與影片錄音長度一模一樣的新聲音檔案。

匯出這一步通常會會等很久,但就慢慢等。最後得到放在wavs資料夾內的新的錄音檔案們(這是範例,檔名不一致請忽略)。

接下來是最後一步,把處理好的聲音和原本的錄影檔案合併,並產生新的錄影檔案。

如果資料夾和檔案擺放的位置、命名,通通都有依照批次命令中的路徑處理,那麼最後這一步就很快,只要讓批次命令自動去抓這些檔案起來合併就好了。

跟之前執行部分的批次命令一樣,只留下這次需要的第三段指令即可,剩下的全部都用註解標記起來不執行。

這裡可能會岔出另外一個情況,不知道大家是不是記得我曾經說過第三段和第四段代碼的差別在哪?


第四段代碼加入了-itsoffset -0.5這個參數,目的在於把聲音提前0.5秒。會加上這組代碼的原因在於,某些攝影機在自動分段檔案的時候,聲音和影像的斷點並"沒有在同一個frame上"。

以La Cozzi錄影的機器為例,在連續錄影的情況下,第一段錄影的開頭是影音資料同時貼齊時間軸開頭,但在第一段錄影結尾時,影像資料有持續直到時間軸結束,但聲音資料並沒有!最後會有0.5秒的空白。而相同的情況延伸到第二段錄影的開頭:聲音資料貼齊時間軸0點,但影像則從0.5秒開始。請注意這不是影音不同步的情況,而是影音資料斷點不一致。

影音資料斷點不一致示意圖
從示意圖可以看到,從第一段檔案結尾開始,每一段結尾跟下一段檔案的開頭都有0.5秒的重疊。也就是說,如果把二段檔案接在一起播放,在斷點的地方會多出0.5秒,也就是那個畫面會黑一下下或聲音頓一下下的時間點。實際上必須把前後二段檔案重疊0.5秒,才會還原錄影當時的時間軸。

我不確定這是大多數錄影機處理分段的慣例,或者是只有少數型號有這個現象。所以如果你手邊的檔案在使用第三段批次命令處理過後,發生影音不同步的問題,很有可能是遇到了這個情況,或其他類似的情況,取決於當時錄影的錄影機如何處理斷點。

以我的下方範例來說,同一次的連續錄影總共被攝影機分成5個檔案,分別是00082-00086.mts。

對照上方資料斷點不一致示意圖,就可以知道只有第一段檔案(00082)不需要另外加入offset的參數讓聲音提前,剩下的四段檔案(00083-00086)都需要讓聲音提前0.5秒,合併後的聲音時間軸才會跟原始檔一樣影音同步。

所以在我的處理流程中,我會把00082.mts留在資料夾中,單獨使用第三段批次命令,讓合併新的聲音檔案和影片原始檔時不套用offset。

處理完以後才把剩下的四個檔案放回來,同時把第一段檔案移走,再使用第四段批次命令,在合併的同時讓聲音提前0.5秒維持影音同步。

2018/01/28補充更新:

部分錄影機會在影片檔案的metadata內寫入聲音軌道相對影像軌道的時間延遲值(delay_relative_to_video),這個值可以作為放回聲音的時候的offset參考。

這個延遲值的欄位不是標準metadata規範下的欄位,使用ffmpeg和ffprobe都不會讀到這個欄位,目前已知可以讀到的工具是mediainfo,以下以這個工具示範。

下載安裝mediainfo以後啟動主要的介面如下圖


左上角File下面的第一個圖示可以載入單一影片檔,第二個圖示可以載入整個資料夾的影片檔,在這個例子裡面我選擇載入整個資料夾的影片。

按下ok以後就會載入該資料夾內的所有影片檔,可能需要一陣子。

載入完成以後可以從最上方的列表選擇要讀取metadata的影片檔,例如00015.MTS


目前畫面中只顯示了一部份的資料,需要切換到其他顯示選項才會顯示更細的資訊。按一下左上角的View,選擇Tree, HTML或Text顯示所有的metadata,在這個例子裡面我選擇Tree。


delay relative to video這個欄位在Audio結構下,往下拉到Audio,找到Delay relative to video欄位,這裡顯示的時間值就是聲音相對於影像的起使點,例如這個例子顯示的-67ms表示聲音比影像早67ms。


上面的-67ms來自一段連續錄影的第一個檔案,這個延遲值在第二個檔案以後就會大幅增加,例如在第二個檔案中記錄到的延遲值是-572ms。


這個值可以作為放回聲音的offset參考,用來增加影音同步的精確度。需要注意的是ffmpeg使用的時間單位是second,需要把欄位內的值除以1000才是ffmpeg使用的值,例如-572ms變成-0.572。

最後在new_mts資料夾內就會看到所有的影片檔案,但其中的聲音軌道已經使用另外處理過的聲音取代了。


以上就是我的處理流程,希望對需要處理現場錄影聲音的朋友會有幫助,如果有問題也請在下方留言,祝福大家處理聲音愉快!

7 則留言:

  1. 好驚人又細緻的流程,感謝分享!!

    回覆刪除
    回覆
    1. 不用客氣!希望可以幫助到也遇到相同問題的朋友!

      刪除
  2. 用 avidemux 軟體 來替換錄影檔案中的聲音會不會比較方便 ?

    回覆刪除
    回覆
    1. Hi Bean,
      謝謝提供關鍵字,剛剛看了一下,應該也是一個可行的作法,可以在GUI下取出和放回聲音軌道。但我還沒有用avidemux實作,不知道面對聲音和影像斷點不一致會不會發生不同步的問題,底下是找到的說明,感謝!
      https://www.avidemux.org/admWiki/doku.php?id=tutorial:save_only_audio
      http://pcsplace.com/software/avidemux-add-audio-to-video/#sthash.sDFuIrQl.dpbs

      刪除
    2. Hi Bean,
      最近因為工作上開發新的程式剛好有接觸到avidemux,有再稍微研究了一下,簡單說明一下avidemux和使用ffmpeg處理替換聲音軌道的狀況。我使用的avidemux版本是2.7。

      取出聲音的部分avidemux可以和ffmpeg做到相同的事情:批次取出影片檔案裡面的聲音軌道,然後轉換成DAW可以讀的wav檔。

      放回聲音的部分我發現了幾個avidemux操作上的限制。在ffmpeg上的做法是在不變更影片容器(container)和編碼的情況下把處理完的wav檔轉換並放回容器中,如此影片的檔案格式、編碼、總長度和時間軸都不會改變,方便不同部門間的協同作業。

      然而在avidemux下的匯出"沒有"copy容器的選項,如果原始影片使用的容器是mp4或mkv等常見的選項,在avidemux下可以透過選擇相同容器的方式達到不改變編碼和容器把聲音放回,但如果原始影片的容器不在avidemux的匯出容器清單內,例如我幫拉扣子處理的影片使用mts,那麼影片容器就會在放回聲音以後改變。這不必然是個問題,但是個ffmpeg和avidemux的差異。

      另外一個在我目前處理流程中影響比較大的問題是關於調整聲音時間軸的問題,就像我文內所說:在某些檔案內,聲音軌道的起使時間跟影片是分開的,在放回聲音軌道的時候需要指定offset時間讓放回的聲音維持和影像的同步,這點在avidemux裡面無法批次處理(或最少我沒有找到,如果有誤歡迎指正)。這個狀況在ffmpeg下是使用 -itsoffset 相對影像的時間 參數校正以後放回。

      以上是二個我發現avidemux和ffmpeg在配合現場錄影混音流程上的差異,給你參考。

      另外我後來也有發現到一些錄影機會在聲音軌道下寫入一個非標準的metadata欄位"delay relative to video",這個欄位記錄了該聲音軌道相對於影像軌道的時間值,在ffmpeg下面我會參考這個欄位的時間值把聲音放回,目前看起來同步的效果非常好。通常連續錄影的第一段大約是-67ms左右,第二段以後約略是-560-580ms不等,放回後的誤差通常在10ms內。但由於這個欄位不是標準的metadata,ffmpeg和ffprobe都讀不到,我只有在mediainfo看到過,這點稍晚會在原文內加註說明,會比原本用-0.5之類的猜測值還要精確。

      刪除
  3. 拜託,哪有這麼麻煩,幾個動作就可以解決的東西

    回覆刪除
    回覆
    1. 您好,謝謝您的回覆。可以請您多提供一些訊息嗎?讓大家都有機會可以學習到更簡便的處理方式,多謝!

      刪除

技術提供:Blogger.