如何使用 javascript 动态加快音频播放中的单词间隙?

How to dynamically speed up word gaps in audio playback with javascript?

当使用<audio>标签在网页上播放音频文件时,有没有办法在音频中出现单词间隙或暂停时动态加快播放速度,然后恢复到 1x(正常) 速度?

改编the linked question中的示例:

<!DOCTYPE html>
<head>
    <meta charset='utf-8'>
    <title>Henry Louis Gates</title>

<body>
    <p><audio crossorigin='anonymous' id='audio' controls src='https://upload.wikimedia.org/wikipedia/commons/0/08/Split_infinitive.ogg' style='width: 100%'></audio>
    <p><label><input id='chk-skip' type='checkbox' checked> Skip silence</label>
    <p>Loudness: <meter id='meter' style='width: 15em;'></meter> <span id='label-loud' style="display: inline-block; width: 20em; text-align: right;">−∞ dB FS</span>
    <p>Speed: <span id='label-fast'>1×</span>

    <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', function () {
            const audio = document.getElementById('audio');
            // 2048 sample buffer, 1 channel in, 1 channel out
            const meter = document.getElementById('meter');
            const labelFast = document.getElementById('label-fast');
            const labelLoud = document.getElementById('label-loud');
            const chkSkip = document.getElementById('chk-skip');

            const handler = function () {
                // we only need to do this once
                this.removeEventListener('play', handler);

                const ctx = new AudioContext();
                const processor = ctx.createScriptProcessor(2048, 1, 1);

                processor.onaudioprocess = function (evt) {
                    const input = evt.inputBuffer.getChannelData(0);

                    const rms = Math.sqrt(
                        input.map(val => val * val).reduce((a, b) => a + b, 0)
                        / input.length
                    );

                    if (chkSkip.checked) {
                        if (rms < 0.006) {
                            audio.playbackRate = 4;
                        } else if (rms >= 0.004) {
                            audio.playbackRate = 1;
                        }
                    }

                    function formatDecibel(val) {
                        val = 10 * Math.log(val) / Math.log(10);
                        if (val === -Infinity)
                            return '−∞';
                        if (val < 0)
                            return '−' + (-val).toFixed(1)
                    }

                    
                    meter.value = rms;
                    labelLoud.textContent = `${formatDecibel(rms)}\xa0dB FS (LPCM RMS ${rms.toFixed(5)})`;
                    labelFast.textContent = `${audio.playbackRate}×`;
                };

                const source = ctx.createMediaElementSource(audio);
                source.connect(ctx.destination);
                source.connect(processor);
                processor.connect(ctx.destination);
            }
            
            audio.addEventListener('play', handler, false);
        }, false);
    </script>

缺点:这似乎只能在基于 Blink 和 WebKit 的浏览器中顺利运行(同源策略偶尔会干扰)。 Firefox 播放音频并检测到静音正常,但播放速度设置似乎没有效果。寻找到无声段的末尾可能效果更好。

此外,为了简单起见,我在这里使用了已弃用的 API;实现像静音检测器这样的过滤器的首选方法是使用 a Worker thread。您可能想检查一下。