插件安装: 在 setup 或 freshness 命令之前,如果此技能位于 HyperFrames 插件中,请遵循插件执行规则。独立安装请保留下面的更新说明。
HyperFrames 音频
混音是一组关系,而不是处理器堆栈。单独听起来正确的两条轨道放在一起可能无法入耳,解决方式几乎从来不是“调低一个”——而是要找出它们争夺什么,然后把那个频率给更需要它的轨道。这里的每个工具都是为了表达这些关系之一。
效果位于元素上的 data-fx-chain 中,预览和渲染运行相同的 Web Audio 图——在实时上下文中是演播室,在离线上下文中是引擎,都在它已经驱动的浏览器内部。每个效果只有一种实现,所以你擦洗时听到的就是最终写入的。你永远不会调两次。
剪辑时序仍由 /hyperframes-core 负责:音频/视频修剪和源范围使用 data-start、data-duration 和 data-media-start,交叉淡化则通过不同轨道上的重叠剪辑实现。本技能拥有已放置轨道的淡入/淡出、交叉淡化包络、轨道增益/音量、音量和效果自动化、闪避/画外音雕刻以及效果链。/media-use 负责音频源获取、生成和预处理。
常量 data-playback-rate(0.1..10)对于画面和保持音调的音频是渲染安全的,前提是匹配的音频/视频元素使用相同的时序、源偏移和速率。速度斜坡是 data-automation 中的 rate 通道(见 docs/reference/speed-ramps);它优先于常量,并在预览和渲染中保持音调。HyperFrames 不提供自动波形同步或漂移校正。
对于可复制的剪切/交叉淡化/重定时配方,请使用 /hyperframes-core → references/creator-editing-recipes.md。
三个属性承载所有内容,位于音频/视频元素本身——或者,对于前两个,位于 <hf-audio-group> 总线上(见“一条总线用于多条轨道”):
| 属性 | 作用 |
|---|---|
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["工作室<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/>峰值 xN + 增益,标记 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["峰值<br/>400 Hz"]
p1 --> p2["峰值<br/>1 kHz"]
p2 --> p3["峰值<br/>1.6 kHz"]
p3 --> g["增益<br/>电平匹配"]
g --> hand["你自己的效果<br/>例如限幅器"]
hand --> dest["轨道增益,然后输出"]
l1["通道 fx.n1.gain"] -.->|"该频段语音电平的包络"| p1
l4["通道 fx.n4.gain"] -.->|"背景音乐整体闪避的程度"| g
静态雕刻是相同但具有固定值且没有通道的图。
首先,找出问题所在
下表从“听起来有低频共振”开始——这假设已经有人听过并指出了这一点。如果拿到一个文件并要求“修复它”,而你没有这样的描述且无法试听,那么你必须进行测量。一条规则支配所有情况:
一个未知语音的绝对频谱无法诊断。 共振峰在 ±10 dB,基频范围为 85–255 Hz,句子结束时会下降 5–6 dB。 这些单独看来都像是缺陷,但实际上都是说话者的特征。
所以,进行比较,并且与同一文件内部的某个参考进行比较:如果存在干净的原始音频则用它,否则使用静音间隙——间隙中可听到的内容是附加的,间隙的频谱是信道而非语音。与已发布的平均频谱或合成的对照语音进行比较是无效的:两个说话者的差异大于大多数缺陷,而在本指南背后的评估中,两个错误答案都恰恰源于此。
当没有原始音频也没有可用的静音时,静态音调缺陷确实是不确定的。请说明这一点并提供符合条件的读数,而不是选择一个并基于它构建效果链。
命令、陷阱和经过验证的配方:references/diagnosis.md。在诊断未被任何人描述过的文件之前请先阅读它。
从症状入手
一旦你知道了频段和类型,就指出音频的问题所在。大多数劣质音频属于以下一两种类型,每种都有现成的解决方案:
| 听起来像 | 使用 |
|---|---|
| 嗡嗡声或低音闷响 | rumble-cut,或 80 Hz 的高通滤波器 |
| 沉闷、胸腔共鸣 | Tame Boominess 任务(200 Hz) |
| 模糊、像隔着纸板 | Reduce Mud 任务(250 Hz) |
| 说话听不清 | Add Clarity 任务(3 kHz),或雕刻背景音乐 |
| 刺耳、令人疲劳 | Soften Harshness 任务(3.2 kHz) |
| 有些单词比其他单词响得多 | 压缩器上的 Evenness,或 Even Out Levels |
| 句子之间有房间混响 | room-gate |
| 语音和音乐互相干扰 | 画外音雕刻——不是对任一轨道使用均衡器 |
| 干涩、像没有空间感 | 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),因此一次分析涵盖所有语音:频段来自所有存在的语音,包络线在任何语音出现的地方上升。从未与背景音乐同时播放的语音则被排除在外;它们不会遮蔽它。
针对多个剪辑 ID 的雕刻是错误的。将剪辑分组,然后对组进行雕刻。 这是一个不变规则,而非建议。逐一命名剪辑必须是彻底正确的,并且只有在下次编辑之前才保持正确——稍后添加的第四个旁白剪辑将超出雕刻的感知范围,背景音乐将无法在其下方静默闪避。改为命名组可以在分析时解析成员关系,因此稍后添加到组的剪辑无需更改 sources 即可被覆盖:
<!-- 将旁白分组,然后针对该组雕刻背景音乐 -->
<audio id="vo-intro" data-audio-group="voiceover" …></audio>
<audio id="vo-middle" data-audio-group="voiceover" …></audio>
<audio id="vo-outro" data-audio-group="voiceover" …></audio>
<audio id="music" data-fx-carve='{"enabled":true,"sources":["voiceover"],"strength":0.8}' …></audio>
一个命名了两个或更多普通剪辑 ID 而非组的 sources 列表会被 audio_carve_ungrouped_sources lint 规则捕获——它仍然可以工作,但它是那种在添加剪辑时会静默失效的版本。
保持雕刻组为语音组:不含背景音乐、音响效果或音乐。 sources 中的组 ID 在_每一次_分析时都会解析为_当前_的所有成员,因此你命名的组就是你之后得到的组——而不是当初写入时测量的轨道。两种可能出问题的情况:
- 背景音乐位于自身源组中。 它被当作语音对待,并针对自身内容进行雕刻——这就是“切勿对自身进行雕刻”的规则在重新分析后出现的情况。
- 音响效果或音乐剪辑位于语音组中。 它在下一次分析时进入侧链,背景音乐开始针对“嗖”声进行闪避,即使当初写入属性的那次运行从未测量过它。
这两种情况在雕刻写入时都是不可见的:分析将检测到的语音求和,并且不会通过组解析进行循环验证,因此第一次通过是真正正确的,只有下一次才是错误的。因此,为每个角色分配单独的组——music 用于背景音乐,voiceover 用于旁白,sfx 用于效果音——并保持 sources 命名的组中只包含语音。
carve.mjs 在发现这两种情况时拒绝写入组形式,改为记录剪辑 ID,并显示
…
[内容已截断以进行翻译]