JS:加载时同时播放多个音频源
JS: play multiple audio sources simultaneously when loaded
我有一个包含三个音频源的 Web 项目(仅限香草 HTML/CSS/JS)。想法是让所有三个同时播放,但我注意到在移动设备上文件播放不同步(即一个源开始,然后几毫秒后第二个开始,然后是第三个)。我相信它们正在播放是因为单个文件在加载后立即播放,所以我想请求一旦所有文件都加载完毕,同时对所有三个文件调用 play() 方法,
使用 vanilla JS 实现此目的的最佳方法是什么?
示例:https://jacksorjacksor.xyz/soundblocks/
回购:https://github.com/jacksorjacksor/jacksorjacksor/tree/master/soundblocks
TIA!
富有
MediaElements 用于媒体的正常播放,并没有优化到足以获得低延迟。最好是使用 Web Audio API, and AudioBuffers.
您将首先在内存中获取文件数据,然后从中解码音频数据,一旦所有音频数据都已解码,您就可以安排在同一精确时刻播放所有内容:
(async() => {
const urls = [ "layer1_big.mp3", "layer2_big.mp3", "layer3_big.mp3" ]
.map( (url) => "https://cdn.jsdelivr.net/gh/jacksorjacksor/jacksorjacksor/soundblocks/audio/" + url );
// first, fetch the files's data
const data_buffers = await Promise.all(
urls.map( (url) => fetch( url ).then( (res) => res.arrayBuffer() ) )
);
// get our AudioContext
const context = new (window.AudioContext || window.webkitAduioContext)();
// decode the data
const audio_buffers = await Promise.all(
data_buffers.map( (buf) => context.decodeAudioData( buf ) )
);
// to enable the AudioContext we need to handle an user-gesture
const btn = document.querySelector( "button" );
btn.onclick = (evt) => {
const current_time = context.currentTime;
audio_buffers.forEach( (buf) => {
// a buffer source is a really small object
// don't be afraid of creating and throwing it
const source = context.createBufferSource();
// we only connect the decoded data, it's not copied
source.buffer = buf;
// in order to make some noise
source.connect( context.destination );
// make it loop?
//source.loop = true;
// start them all 0.5s after we began, so we're sure they're in sync
source.start( current_time + 0.5 );
} );
};
btn.disabled = false;
})();
<button disabled>play</button>
我有一个包含三个音频源的 Web 项目(仅限香草 HTML/CSS/JS)。想法是让所有三个同时播放,但我注意到在移动设备上文件播放不同步(即一个源开始,然后几毫秒后第二个开始,然后是第三个)。我相信它们正在播放是因为单个文件在加载后立即播放,所以我想请求一旦所有文件都加载完毕,同时对所有三个文件调用 play() 方法,
使用 vanilla JS 实现此目的的最佳方法是什么?
示例:https://jacksorjacksor.xyz/soundblocks/
回购:https://github.com/jacksorjacksor/jacksorjacksor/tree/master/soundblocks
TIA!
富有
MediaElements 用于媒体的正常播放,并没有优化到足以获得低延迟。最好是使用 Web Audio API, and AudioBuffers.
您将首先在内存中获取文件数据,然后从中解码音频数据,一旦所有音频数据都已解码,您就可以安排在同一精确时刻播放所有内容:
(async() => {
const urls = [ "layer1_big.mp3", "layer2_big.mp3", "layer3_big.mp3" ]
.map( (url) => "https://cdn.jsdelivr.net/gh/jacksorjacksor/jacksorjacksor/soundblocks/audio/" + url );
// first, fetch the files's data
const data_buffers = await Promise.all(
urls.map( (url) => fetch( url ).then( (res) => res.arrayBuffer() ) )
);
// get our AudioContext
const context = new (window.AudioContext || window.webkitAduioContext)();
// decode the data
const audio_buffers = await Promise.all(
data_buffers.map( (buf) => context.decodeAudioData( buf ) )
);
// to enable the AudioContext we need to handle an user-gesture
const btn = document.querySelector( "button" );
btn.onclick = (evt) => {
const current_time = context.currentTime;
audio_buffers.forEach( (buf) => {
// a buffer source is a really small object
// don't be afraid of creating and throwing it
const source = context.createBufferSource();
// we only connect the decoded data, it's not copied
source.buffer = buf;
// in order to make some noise
source.connect( context.destination );
// make it loop?
//source.loop = true;
// start them all 0.5s after we began, so we're sure they're in sync
source.start( current_time + 0.5 );
} );
};
btn.disabled = false;
})();
<button disabled>play</button>