从 <audio> 标签中擦除音频时如何听到声音播放?
How can I hear sound playing while scrubbing the audio from an <audio> tag?
在我的示例中,我有一个用户上传到网页的 mp3。我在页面上创建了一个可视波形,并对所有默认控件进行了编码和工作(播放、暂停、停止、擦洗等...)
我想要实现的是您在 After Effects 或 Animate 中听到的擦洗效果。当我擦洗音频时,我想在擦洗器所在的确切位置听到音频的音调。
我什至不知道从哪里开始?我查看了 AudioContext
,我想我的答案就在那里,但我不确定。我想过有一个 "shadow audio tag" 我设置了相同的 src 然后调用 play()
并在不久之后暂停它但这看起来像一团糟;特别是使用强力洗涤器。任何方向将不胜感激!
我认为您的方向是正确的。您的洗涤器 UI 可以与未附加到 DOM/page 的 Audio
元素交互,并可以直接设置 audio.currentTime
,播放几毫秒,然后停止。您可以利用 setTimeout()
队列的取消来创建简短的清理播放,然后在清理停止时继续播放。我假设这一切都取决于正在下载的完整文件以避免清理期间的网络延迟。
是的,您的答案在 AudioContext API 中(所有异步和慢速 MediaElements 都不是为此而制作的)。具体来说,你要的是AudioBufferSourceNode接口,可以即时播放音频。
您需要做的就是将您的音频文件作为 ArrayBuffer 获取,从该缓冲区请求 AudioContext decode the audio PCM data 并从中创建一个 AudioBuffer。
这是最重的部分,但只完成了一次。
然后你只需要为每个 "scrub" 事件创建一个非常轻的 AudioBufferSourceNode。
为此,您可以使用其 start(when, offset, duration)
方法的三个参数版本。
const slider = document.getElementById('slider');
const ctx = new AudioContext();
fetch("https://upload.wikimedia.org/wikipedia/en/d/dc/Strawberry_Fields_Forever_(Beatles_song_-_sample).ogg")
.then( resp => resp.arrayBuffer() )
.then( buf => ctx.decodeAudioData(buf) )
.then( prepareUI )
.catch( console.error );
function prepareUI( audioBuf ) {
let source;
slider.oninput = e => {
if( source ) { source.stop(0); }
source = ctx.createBufferSource();
source.buffer = audioBuf;
source.connect(ctx.destination);
const offset = slider.value * audioBuf.duration;
const duration = 0.1;
source.start(0, offset, duration);
};
slider.disabled = false;
}
input { width: 350px }
<input type="range" id="slider" min="0" max="1" step="0.005" disabled>
当然,您也可以为整个播放器重复使用此 AudioBuffer。
在我的示例中,我有一个用户上传到网页的 mp3。我在页面上创建了一个可视波形,并对所有默认控件进行了编码和工作(播放、暂停、停止、擦洗等...)
我想要实现的是您在 After Effects 或 Animate 中听到的擦洗效果。当我擦洗音频时,我想在擦洗器所在的确切位置听到音频的音调。
我什至不知道从哪里开始?我查看了 AudioContext
,我想我的答案就在那里,但我不确定。我想过有一个 "shadow audio tag" 我设置了相同的 src 然后调用 play()
并在不久之后暂停它但这看起来像一团糟;特别是使用强力洗涤器。任何方向将不胜感激!
我认为您的方向是正确的。您的洗涤器 UI 可以与未附加到 DOM/page 的 Audio
元素交互,并可以直接设置 audio.currentTime
,播放几毫秒,然后停止。您可以利用 setTimeout()
队列的取消来创建简短的清理播放,然后在清理停止时继续播放。我假设这一切都取决于正在下载的完整文件以避免清理期间的网络延迟。
是的,您的答案在 AudioContext API 中(所有异步和慢速 MediaElements 都不是为此而制作的)。具体来说,你要的是AudioBufferSourceNode接口,可以即时播放音频。
您需要做的就是将您的音频文件作为 ArrayBuffer 获取,从该缓冲区请求 AudioContext decode the audio PCM data 并从中创建一个 AudioBuffer。
这是最重的部分,但只完成了一次。
然后你只需要为每个 "scrub" 事件创建一个非常轻的 AudioBufferSourceNode。
为此,您可以使用其 start(when, offset, duration)
方法的三个参数版本。
const slider = document.getElementById('slider');
const ctx = new AudioContext();
fetch("https://upload.wikimedia.org/wikipedia/en/d/dc/Strawberry_Fields_Forever_(Beatles_song_-_sample).ogg")
.then( resp => resp.arrayBuffer() )
.then( buf => ctx.decodeAudioData(buf) )
.then( prepareUI )
.catch( console.error );
function prepareUI( audioBuf ) {
let source;
slider.oninput = e => {
if( source ) { source.stop(0); }
source = ctx.createBufferSource();
source.buffer = audioBuf;
source.connect(ctx.destination);
const offset = slider.value * audioBuf.duration;
const duration = 0.1;
source.start(0, offset, duration);
};
slider.disabled = false;
}
input { width: 350px }
<input type="range" id="slider" min="0" max="1" step="0.005" disabled>
当然,您也可以为整个播放器重复使用此 AudioBuffer。