如何使用 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。您可能想检查一下。
当使用<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。您可能想检查一下。