HyperFrames Audio
混音是一組關係,而非處理器的堆疊。兩條各自聽起來很好的音軌放在一起可能變得無法忍受,而解決方法幾乎從來不是「調低其中一條」——而是找出它們在爭奪什麼,並把那個東西交給需要它的那一條。這裡的每個工具都是為了表達其中一種關係而存在。
效果存在於元素上的 data-fx-chain,而預覽與渲染執行的是同一個 Web Audio 圖形——在即時環境中是工作室,在它已驅動的瀏覽器內部以離線方式執行。每個效果只有一種實作,因此你在拖曳時聽到的,就是最終將會寫入的內容。你無需調整兩次。
片段時間軸仍屬於 /hyperframes-core:音訊/視訊修剪與來源範圍使用 data-start、data-duration 與 data-media-start,而交叉淡接則將不同音軌上的片段重疊。此技能負責已放置音軌的淡入/淡出、交叉淡接包絡、音軌增益/音軌音量、音量與效果自動化、閃避/語音旁白雕刻,以及效果鏈。/media-use 則負責來源處理、生成與前處理。
常數 data-playback-rate(0.1..5)對於畫面與保留音高的聲音來說是渲染安全的,前提是匹配的音訊/視訊元素使用相同的時間軸、來源偏移與速率。不支援來源速度漸變,因為沒有速率包絡;請預先處理一個衍生出的同步資產。HyperFrames 不提供自動波形同步或漂移校正。
如需可複製的剪輯/交叉淡接/重設時間配方,請使用 /hyperframes-core → references/creator-editing-recipes.md。
三個屬性承載了一切,全部位於音訊/視訊元素本身:
| 屬性 | 承載內容 |
|---|---|
data-fx-chain | 效果,按訊號順序排列 |
data-automation | 此音軌音量或其效果參數的包絡 |
data-fx-carve | 雕刻本身的設定,以便可以重新推導 |
出廠的效果系列包括:增益、等化器(高通、低通、峰值、擱架)、壓縮器、限制器、噪音閘、飽和、延遲、殘響、合唱、移相器與位元破碎。
每個效果的確切 JSON,以及音軌必須滿足的規則:references/attributes.md。
每個效果及其參數、範圍與單位:references/fx-registry.md。
如何解決你聽不到聲音的檔案問題:references/diagnosis.md。
預設集、命名工作與單旋鈕設定檔,以及症狀對應修復表:references/presets.md — 在親手建立效果鏈之前請先閱讀此文件,因為通常其中一個預設集或命名工作已經指出了問題所在。
各部分的運作方式
兩個編輯表面寫入這些屬性;兩個執行時期透過相同的建構器讀取它們。這個共享的中間層正是預覽能預測渲染結果的原因。
flowchart TB
voice["語音音軌<br/>媒體檔案"]
bed["音樂背景<br/>媒體檔案"]
subgraph AUTHOR["編輯階段 — 唯一會寫入屬性的部分"]
panel["Studio<br/>語音旁白雕刻控制"]
script["scripts/carve.mjs<br/>偵測配對,預設為動態"]
analysis["core/audioCarve.ts<br/>carveProfile · analyseCarveBands<br/>analyseCarveDuck · analyseCarveDynamics"]
panel --> analysis
script --> analysis
end
voice --> analysis
bed --> analysis
subgraph ATTRS["寫入背景元素的屬性"]
carveAttr["data-fx-carve<br/>source · strength · dynamic"]
chainAttr["data-fx-chain<br/>peaking xN + gain,標記為 fromCarve"]
autoAttr["data-automation<br/>每個雕刻參數一條音軌"]
end
analysis --> carveAttr
analysis --> chainAttr
analysis --> autoAttr
subgraph SHARED["單一實作,由兩者讀取"]
build["audioFxGraph.ts · buildFxChain"]
sched["audioFxAutomation.ts · scheduleChainAutomation"]
end
chainAttr --> build
autoAttr --> sched
build --> preview["預覽<br/>即時 AudioContext<br/>attachElementFxChain"]
sched --> preview
build --> render["渲染<br/>在無頭瀏覽器中以 OfflineAudioContext<br/>applyAudioFxChain"]
sched --> render
preview --> heard["你在拖曳時聽到的內容"]
render --> wav["處理後的 WAV<br/>+ chainTailSeconds 讓混音能容納尾音"]
wav --> mix["引擎 · audioMixer<br/>音量軌道在此處嵌入 PCM,而非在圖形中"]
mix --> out["最終的混音輸出"]
edit["在播放中編輯屬性"] -.->|MutationObserver| preview
雕刻本身的設定在播放時永遠不會被讀取——播放的是它所產生的效果鏈與音軌。data-fx-carve 的存在是為了讓強度可以在現有的雕刻上被改變,而不是從濾波器中反向推測出來。
在經過雕刻的背景內部,訊號會先通過衰減區,然後是電平匹配,最後才是你自己建立的效果——這也就是為什麼你添加的限制器仍然能作為最終的上限:
flowchart LR
src["解碼後的背景"] --> p1["peaking<br/>400 Hz"]
p1 --> p2["peaking<br/>1 kHz"]
p2 --> p3["peaking<br/>1.6 kHz"]
p3 --> g["gain<br/>電平匹配"]
g --> hand["你自己的效果<br/>例如限制器"]
hand --> dest["音軌增益,然後輸出"]
l1["音軌 fx.n1.gain"] -.->|"語音在該頻段的<br/>電平包絡" p1
l4["音軌 fx.n4.gain"] -.->|"背景整體<br/>閃避的程度" g
靜態雕刻就是相同的圖形,但使用固定值且完全沒有任何音軌。
首先,找出問題所在
下表從「聽起來很轟」開始——這假設已經有人聽過並這樣說。如果你拿到一個檔案並被告知「修好它」,你沒有這樣的描述,也無法聆聽,所以你必須進行測量。有一條規則主導這一切:
無法診斷單一未知語音的絕對頻譜。 共振峰是 ±10 dB,基頻範圍為 85–255 Hz,句子在結尾時會衰減 5–6 dB。 這些單獨來看都會被認為是缺陷,但它們每一個都是說話者本身的特性。
因此,請進行比較,並且與同一個檔案內部的東西進行比較:如果存在,就是乾淨的原始檔案;否則就是停頓處——在間隙中能聽到的任何東西都是疊加進去的,而間隙的頻譜就是該聲道而非語音本身的頻譜。與公佈的平均頻譜或合成的對照語音進行比較是行不通的:兩個不同的說話者之間的差異比大多數的缺陷還要大,而在本指南背後的評估中,兩個錯誤的答案正是來自這種比較。
當沒有原始檔案也沒有可用的靜音時,靜態的音調缺陷實際上是一個欠定的問題。請說明這一點並提供符合情況的讀數,而不是選擇一個並根據它來建立效果鏈。
命令、陷阱與實作配方:references/diagnosis.md。在診斷一個沒有人描述過的檔案之前,請先閱讀它。
從症狀開始
一旦你知道了頻段和類型,就找出音訊的問題所在。大多數糟糕的音訊屬於以下一兩種類型,而每一種都有出廠的解決方案:
| 聽起來像是 | 使用這個 |
|---|---|
| 低頻嗡鳴或低沈的撞擊聲 | rumble-cut,或是在 80 Hz 使用 highpass |
| 渾厚、胸腔共鳴感過重 | Tame Boominess 工作(200 Hz) |
| 模糊、像隔著紙板 | Reduce Mud 工作(250 Hz) |
| 難以辨識字詞 | Add Clarity 工作(3 kHz),或雕刻背景 |
| 刺耳且令人疲勞 | Soften Harshness 工作(3.2 kHz) |
| 某些字詞比其他字詞大聲很多 | 在壓縮器上使用 Evenness,或是 Even Out Levels |
| 句子之間的空間感(房間殘響) | room-gate |
| 語音與音樂互相干擾 | Voiceover carve — 不是對任何一個使用 EQ |
| 乾澀、不像在空間中錄製 | room-tight 或 room-natural |
| 就是「業餘水準」 | voice-clean,它是上述四個的組合,按順序使用 |
完整目錄、每個預設集的內容、頻段詞彙,以及刻意不涵蓋的項目(例如去噝聲、降噪、音色匹配):references/presets.md。
根據問題選擇效果家族,而非名稱
濾波器(highpass、lowpass、peaking、lowshelf、highshelf)決定一條音軌被允許佔據哪些頻率。這是解決兩個來源衝突的首要工具,因為衝突發生在頻段中:背景音樂和語音都想要 1–3 kHz,而從背景音樂中拿走這個頻段,對背景音樂的影響遠小於將整個音量調低對混音的影響。對語音使用高通濾波器是解決低頻嗡鳴的標準方法;低通濾波器則故意讓聲音變暗或模糊。
動態處理(gain、compressor、limiter、gate)決定一條音軌的音量隨時間變化的行為。壓縮縮小了大聲與小聲之間的距離,讓小聲的部分可以被提升。限制器是一個上限——它不會塑造任何東西,它只是保證沒有東西能超過它。噪音閘會移除低於閾值的內容,這就是你如何讓句子之間的空間噪音消失的方法。gain 是一個單純的電平級,當一條音軌必須讓路時,自動化音軌就會作用於它。
非線性處理(saturate、bitcrush)會改變波形的形狀,從而增加原本不存在的諧波。當一條音軌需要個性或質感而不是修正時,可以使用它——但要記住它是有生成性的:它會讓一個單薄的來源變得更密實,而不是更乾淨。
時間效果(delay、reverb、chorus、phaser)將一條音軌置於一個空間中或賦予它寬度。這些是最容易破壞混音的效果,因為一個尾音或一個失諧的複製品會佔據語音需要的相同空間。把它們用在應該位於其他東西後方的事物上,並保持濕聲量低於在單獨聆聽時聽起來正確的程度。
效果鏈是串聯的:每個效果處理前一個效果產生的結果。因此,校正性的濾波器應放在前面,特性效果在中間,而限制器放在最後,這樣它才能真正起到上限的作用。
語音旁白雕刻
它解決的問題。 音樂背景在語音下方會讓語音難以聽清。直覺的反應是讓整個背景閃避,這雖然有效,但代價是讓背景失去了所有存在感——音樂在整個語音旁白期間都變得軟弱無力。但語音並不需要整個頻譜。它只需要它實際上佔據的那幾個頻段。雕刻只拿走這些頻段,而背景則保留其低頻與高頻,因此當語音仍然清晰可辨時,背景聽起來仍是音樂。
它是一種關係,而非一個效果。 設定存在於背景上——即被處理的音軌——並且它們指定了要聆聽的語音,就像側鏈壓縮器一樣:你選擇會變安靜的音軌,並指定是什麼讓它變安靜。永遠不要將雕刻放在語音音軌上。 語音對自己進行雕刻是一個錯誤,而不是一個微妙的混音選擇。
每一個語音,而非其中一個。 sources 是一個列表,因為一條背景通常會貫穿整個序列——一個旁白、一個採訪回答、第二位主持人。它們在背景自己的時鐘上被加總(mixCarveSources),然後再進行測量,因此一次分析涵蓋了所有語音:頻段來自所有存在的語音,而包絡在語音發生的任何地方都會上升。永遠不會在背景播放時出現的語音則被排除在外;它們無法遮蔽背景。
一個旋鈕。 strength 是 0..1 的數值,並推導出一切:要削減多深、使用多少個頻段、頻寬多寬、在清晰度與原始語音能量之間偏向多少、電平可以下降多少、目標要比語音低多少。這六個參數在任何真實混音中都是一起變化的——溫和的雕刻是在少數頻段進行淺層削減並伴隨少量的閃避;強烈的雕刻則是在更多頻段進行更深層的削減並伴隨更多的閃避——因此它們是一個關係,只需在 carveProfile 中寫一次。預設值為 0.25——在三個頻段中進行 6 dB 的衰減,並保留 6 dB 的電平空間,可聽到但不會感覺像個窟窿。在 0.5 時,衰減達到 10 dB,此時雕刻開始被聽到是一種效果,而不是為語音騰出空間;高於此值則屬於故意為之的領域,適用於大聲的背景伴隨著小聲的語音。0 則僅進行頻譜處理——只使用一個頻段,完全不進行電平匹配。
預設使用雕刻。 在旁白下方播放的背景需要雕刻;這不是一個有空才做的打磨步驟。放置兩條音軌,執行下面的命令,然後聆聽。只有在沒有旁白需要音樂作為襯底時才跳過它——例如音樂影片、標題卡、配合音樂剪輯的蒙太奇。
它總是跟隨語音。 沒有靜態模式:固定的深度會在每個停頓處削弱背景,而且一旦你聽過兩者,就沒有理由想要靜態模式。每個值都會變成語音自身電平的包絡——寂靜時背景不受影響,大聲的段落則將雕刻推到最大深度——這些被寫成普通的自動化音軌,這就是為什麼這些音軌會出現在時間軸上並且可以在之後被編輯。
電平匹配是其中的一部分。 頻譜雕刻無法解決一個只是比語音更大聲的背景。因此,雕刻也會測量背景相對於語音高了多少,並寫入一個 gain 級:對於靜態雕刻,它保持在一個固定值;對於動態雕刻,則由一個包絡驅動。這個包絡會被刻意緩慢地釋放——在一個詞結束的瞬間就立即彈回最大音量的音樂,聽起來像機器在操作。
執行它。 在 Studio 中,雕刻是音軌效果器架頂部的一個模組——語音、強度、動態,以及它產生的分析結果,都在一個卡片內。每當另一條音軌可能是語音時,它就會出現;而一條背景如果上方剛好有一個候選者,則會預設以動態方式、以預設強度進行雕刻:這就是旁白下方的背景所需要的,而這個模組就是你用來更改或關閉它的地方。如果有多個候選者,則選擇器會等待,而不是猜測。無頭模式—— 這是當你在編輯一個組合而非單一曲目時的路徑:
node <SKILL_DIR>/scripts/carve.mjs --comp index.html
這就是完整的命令。它會找出
...
[為翻譯而截斷]