我有一首歌曲的几首曲目,我想一起播放,并且能够将一些曲目静音并播放其他曲目。所以我需要能够同时启动它们。现在,它们都开始有点不同步:
// Start playing
for ( i = 0; i < 5; i++ ) {
tracks[i].audio.play();
}
即使这显然还不足以同时启动它们。
javascript中有什么方法可以保证HTML5音频标签将同时开始播放吗?
我有一首歌曲的几首曲目,我想一起播放,并且能够将一些曲目静音并播放其他曲目。所以我需要能够同时启动它们。现在,它们都开始有点不同步:
// Start playing
for ( i = 0; i < 5; i++ ) {
tracks[i].audio.play();
}
即使这显然还不足以同时启动它们。
javascript中有什么方法可以保证HTML5音频标签将同时开始播放吗?
不确定您是否已经这样做了,但这里有一些用于预加载音频的示例代码。
var audios = [];
var loading = 0;
AddNote("2C");
AddNote("2E");
AddNote("2G");
AddNote("3C");
function AddNote(name) {
loading++;
var audio = document.createElement("audio");
audio.loop = true;
audio.addEventListener("canplaythrough", function () {
loading--;
if (loading == 0) // All files are preloaded
StartPlayingAll();
}, false);
audio.src = "piano/" + name + ".mp3";
audios.push(audio);
}
function StartPlayingAll() {
for (var i = 0; i < audios.length; i++)
audios[i].play();
}
}
您可以尝试的另一件事是audio.currentTime
在每个轨道上设置手动同步音频。
您可以在开始的短暂延迟后使用 setTimeout 同步它们(尽管您可能希望等待所有音频对象加载)。
JSFiddle:http: //jsfiddle.net/bmAYb/35/
var au1 = document.getElementById('au1');
var au2 = document.getElementById('au2');
au1.volume = 1;
au2.volume = 0; //mute
au1.play();
au2.play();
var notfirstRun = false;
//sync for the first time
setTimeout(function() {
au2.currentTime = au1.currentTime;
au2.volume = 1;
}, 250);
我最初的想法是使用 setInterval 每 x 毫秒同步一次,但是当你这样做时,如果volume
设置为1
(可听),音频就会弹出。
我的小提琴并不完全同步,但非常接近。您可以使其 100% 同步,但您需要将其他轨道上的音频静音或处理爆音。
代码(和小提琴中的音乐)来自Hungry Media。
我遇到了同样的问题,并找到了使用Audio API的解决方案。
问题是音频输出有几毫秒的延迟,所以不可能同时启动多个音频。但是,您可以通过使用ChannelMergerNode将音频源合并为一个来解决此问题。通过将GainNode放在两者之间,您可以分别控制每个音频源的音量。
我为此编写了一个简单的 javascript 类。这是您可以使用它的方式:
var audioMerger = new AudioMerger(["file1.ogg", "file2.mp3", "file3.mp3",
"file4.ogg", "file5.mp3"]);
audioMerger.onBuffered(() => audioMerger.play());
// Make sure it's always in sync (delay should be less than 50 ms)
setInterval(() => {
if (audioMerger.getDelay() >= 0.05) {
audioMerger.setTime(audioMerger.getTime());
}
}, 200);
// Set volume of 3rd audio to 50%
audioMerger.setVolume(0.5, 2);
// When you want to turn it off:
audioMerger.pause();
此代码在我的 PC 上的 Firefox 中将音频之间的延迟减少到不到 10 毫秒。这种延迟是如此之小,你不会注意到它。不幸的是,它不适用于 Internet Explorer 等较旧的浏览器。
这是该课程的代码:
class AudioMerger {
constructor(files) {
this.files = files;
this.audios = files.map(file => new Audio(file));
var AudioContext = window.AudioContext || window.webkitAudioContext;
var ctx = new AudioContext();
this.merger = ctx.createChannelMerger(this.audios.length);
this.merger.connect(ctx.destination);
this.gains = this.audios.map(audio => {
var gain = ctx.createGain();
var source = ctx.createMediaElementSource(audio);
source.connect(gain);
gain.connect(this.merger);
return gain;
});
this.buffered = false;
var load = files.length;
this.audios.forEach(audio => {
audio.addEventListener("canplaythrough", () => {
load--;
if (load === 0) {
this.buffered = true;
if (this.bufferCallback != null) this.bufferCallback();
}
});
});
}
onBuffered(callback) {
if (this.buffered) callback();
else this.bufferCallback = callback;
}
play() {
this.audios.forEach(audio => audio.play());
}
pause() {
this.audios.forEach(audio => audio.pause());
}
getTime() {
return this.audios[0].currentTime;
}
setTime(time) {
this.audios.forEach(audio => audio.currentTime = time);
}
getDelay() {
var times = [];
for (var i = 0; i < this.audios.length; i++) {
times.push(this.audios[i].currentTime);
}
var minTime = Math.min.apply(Math, times);
var maxTime = Math.max.apply(Math, times);
return maxTime - minTime;
}
setVolume(volume, audioID) {
this.gains[audioID].gain.value = volume;
}
}