停顿不是听出来的,是算出来的

给口播录音做后期,第一刀永远是切掉废话和停顿。播客去口误、会议录音提效、课程音频压时长,本质都是同一个动作:把「没在说话」的部分找出来剪掉,让三分钟的干货不再被五分钟的呼吸和嗯啊拖成八分钟。人听一段录音,哪里是停顿似乎「一听便知」,但那是语义和语感在帮忙——耳朵加上大脑,连说话人吸了一半的气都能被脑补成「即将开口」。浏览器里没有任何器官,只有一串数字,所以「哪段是停顿」必须变成一个可以被计算的问题:把每个时刻的响度算出来,再定义一个规则判定「多安静、多长才算停顿」。这一整套账本的度量衡,叫 dBFS。

从 PCM 到 dBFS

浏览器解码完一段音频,拿到的是 AudioBuffer:里面是 [-1, 1] 范围的浮点采样,1.0 就是满幅,定义为 0dBFS(dB Full Scale)——数字音频的刻度以「满幅为零、往下为负」计,越小越安静。

一段窗口内的响度不看峰值,看均方根(RMS):

1
2
3
rms = sqrt(sum(x[i] * x[i]) / N)   // 一窗内采样的均方根
db  = 20 * log10(rms)              // 换算 dBFS,满幅 1.0 → 0
if (rms <= 0) db = -120            // 纯静音:log 无定义,钉到地板

几个锚点帮人建立直觉:幅度 0.5 约等于 -6dB,0.05 约等于 -26dB。而纯静音的 RMS 是 0,对数对 0 没有定义,工程上把它钉到 -120dB 当作地板值——否则公式直接算出负无穷,后面的门限比较没法做。对数刻度的意义和所有 dB 一样:把乘法关系变成加减法,人耳对响度的感知本身也是对数的,两边刚好对上。

为什么用 RMS 而不用峰值?峰值只看最高的一个采样,一句话里的一个爆破音就能把峰值顶上去;RMS 是整窗能量的平均,更贴近人耳感知到的「持续响度」。语音天然忽大忽小,峰值响但音节之间的过渡可能很低,用 RMS 才能把「这一窗整体上有多响」量得稳定。

窗与跳步

RMS 要在一个窗口里算,窗口多长是个权衡:窗太长,停顿的边界被糊掉,切口位置含糊;窗太短,逐窗数值抖动,一闪而过的齿音就能把判定带偏。50ms 是个恰好落在中间的值——低于一个音节的典型时长,任何真正的发音都不会被漏掉,又足够长到能压住瞬时毛刺。判定就以 50ms 一窗、逐窗滑动的方式进行。

门限与「最短时长」

有了逐窗响度,规则就一句话:连续低于阈值、且足够长的区段才判静音。阈值默认 -40dBFS(安静环境的口播录音),嘈杂环境——风扇、空调、街头——建议提到 -30dBFS,录音棚级安静可以用 -50dBFS 更保守地只切纯停顿。

真正容易忽略的是第二条:最短静音时长,默认 0.3s。低于阈值的区段必须连续够 0.3 秒才算静音,短于此的保留原样。没有这条,字与字之间几十毫秒的自然间隙也会被判成「停顿」切掉,成品听起来像结巴——自然呼吸和断句是语速舒适感的来源,不是废料。想让节奏更紧凑,可以把最短静音时长降到 0.1 到 0.2 秒,但低于音节时长的设定就该慎用了。

最后切减时,每段静音的两侧还要向内收一点 padding(默认 50ms,可在 0 到 0.2 秒之间调),让切口落在停顿中间而不是音节尾巴上,防止把尾音削掉。padding 偏小切得干净但可能伤到尾音,偏大更保险但切得少。另一个实用提醒来自反向场景:如果整段录音电平偏低——峰值只有 -26dBFS 左右——按 -40 的阈值一测可能全篇都像「说话」,这时该把阈值调到 -50 附近再检测,或者先用增益工具把电平提上来,避免整段被误判。

导出链:44 字节的 WAV 头

判定完成后,保留段的 Float32Array 直接首尾拼接,交给一个自写的 WAV 编码器。WAV 的文件头只有 44 字节:RIFF、WAVE、fmt 、data 四个块标识按小端写入,fmt 块里声明 PCM 格式、声道数与采样率,data 块里就是采样本体——每个采样先 clamp 到满幅,再映射成 16 位整数(PCM16)写进小端字节流:

1
2
3
RIFF  <size>  WAVE
fmt   16      PCM / 声道数 / 采样率 / 对齐
data  <size>  PCM16 小端采样

为什么导 WAV 不导 MP3?MP3 是感知压缩编码,要引入一整套编码器库,还会带来有损压缩的代次损失;而 WAV 的头 44 字节手写就够了,数据段是 PCM 原样直写——无损、够快,任何后期软件都能直接读。对于「切静音」这种不该动采样本身的操作,无损是底线:切之前采样是什么,切之后还是什么,变的只有首尾位置。

实现与配套

🔧 口播静音切除 的检测、拼接、编码全部写成纯函数,node 里就能单测,浏览器只负责读文件和画波形——波形预览里那片红色区段,就是算法判定结果的可视化,阈值、最短静音时长和 padding 都可调,切前切后可对比试听,最后无损导出 WAV。

同一本 dB 账本还支撑着另外两件工具:🔧 音量增益 先测峰值、RMS 与响度估算再给建议增益,放大后经限幅器压住峰值防爆音;🔧 音频拼接 把多段录音本地解码、按序合并、自动重采样后导出 WAV。要注意的是,这些工具里的 dB 都是数字满幅口径(dBFS),与 🔧 噪音分贝检测 的**声压级(SPL)**不是一回事:后者从麦克风信号按 dBFS 加 94dB 的经验换算估算物理世界的环境声压,未经计量校准,只做环境吵不吵的参考。一个量的是文件内部的电平,一个量的是空气里的声压,刻度起点完全不同。

这些工具连同混音、BPM 检测等一整套音频处理,都收在音频创作工具箱专题里,一页排开,全部本地计算,录音不出浏览器。