是否可以同时在两个音频输出设备上播放相同的音频
Is it possible to play the same audio on two audio output devices simultaneously
我正在尝试制作一个脚本,从音频元素获取音频并同时在耳机和笔记本电脑扬声器上播放。
这可能吗?
这是我目前写的代码:
const outputs = (await navigator.mediaDevices.enumerateDevices()).filter(({ kind, deviceId }) => kind === 'audiooutput' && deviceId !== 'default' && deviceId !== 'communications' );
var players = [];
document.querySelectorAll('audio').forEach((y)=>{
players.push([]); let l = players.length-1;
outputs.forEach((x)=>{
if(players[l].length===0) players[l].push(y);
else {
let p = y.cloneNode();
p.srcObject = players[l][0].srcObject.clone();
players[l].push(p);
}
});
})
players.forEach((a)=>{
a.forEach((o, i)=>{
o.setSinkId(outputs[i].deviceId);
o.play();
})
})
此代码的问题是它使音频只在另一个扬声器上播放,而不是在两个扬声器上播放。
请注意,window 可以访问麦克风,因此我可以看到来自 navigator.mediaDevices.enumerateDevices()
的所有设备。
该脚本主要用于 Edge 和 Chrome.
我找到了解决办法!
由于我无法在同一个 window 中同时在多个设备上播放声音,因此我设法通过创建包含音频元素的 iframe 来完成此操作。
然后我将所有这些音频元素设置为相同的源,并将它们设置为输出特定设备的音频,然后将 play/stop 与事件侦听器同步。
之所以有效,是因为 iframe 由主 window 分隔。实际上我认为他们有自己的进程(在 chromium 浏览器上)。
我的代码如下所示:(注意我没有使用静态源,而是 srcObjects)
navigator.mediaDevices.getUserMedia({audio: true}).then(s=>{
s.getTracks().forEach(x=>x.stop()); //stop mic use because we need only outputs
navigator.mediaDevices.enumerateDevices().then(o=>{
const outputs = o.filter(({ kind, deviceId }) => kind === 'audiooutput' && deviceId !== 'default' && deviceId !== 'communications');
let audioSrc = getAudioSrc(), players = [];
audioSrc.src.pause(); // Pause source to start audio in sync ?
audioSrc.src.addEventListener("pause", () => players.forEach(x=>x.pause()));
audioSrc.src.addEventListener("play", () => players.forEach(x=>x.play()));
outputs.forEach((x)=>{
let ifrm = makeIFrame(), audioEl = makeAudio(ifrm.document, audioSrc.s, x.deviceId);
players.push(audioEl);
});
});
}).catch(e=>console.log(e));
我正在尝试制作一个脚本,从音频元素获取音频并同时在耳机和笔记本电脑扬声器上播放。 这可能吗?
这是我目前写的代码:
const outputs = (await navigator.mediaDevices.enumerateDevices()).filter(({ kind, deviceId }) => kind === 'audiooutput' && deviceId !== 'default' && deviceId !== 'communications' );
var players = [];
document.querySelectorAll('audio').forEach((y)=>{
players.push([]); let l = players.length-1;
outputs.forEach((x)=>{
if(players[l].length===0) players[l].push(y);
else {
let p = y.cloneNode();
p.srcObject = players[l][0].srcObject.clone();
players[l].push(p);
}
});
})
players.forEach((a)=>{
a.forEach((o, i)=>{
o.setSinkId(outputs[i].deviceId);
o.play();
})
})
此代码的问题是它使音频只在另一个扬声器上播放,而不是在两个扬声器上播放。
请注意,window 可以访问麦克风,因此我可以看到来自 navigator.mediaDevices.enumerateDevices()
的所有设备。
该脚本主要用于 Edge 和 Chrome.
我找到了解决办法!
由于我无法在同一个 window 中同时在多个设备上播放声音,因此我设法通过创建包含音频元素的 iframe 来完成此操作。
然后我将所有这些音频元素设置为相同的源,并将它们设置为输出特定设备的音频,然后将 play/stop 与事件侦听器同步。
之所以有效,是因为 iframe 由主 window 分隔。实际上我认为他们有自己的进程(在 chromium 浏览器上)。
我的代码如下所示:(注意我没有使用静态源,而是 srcObjects)
navigator.mediaDevices.getUserMedia({audio: true}).then(s=>{
s.getTracks().forEach(x=>x.stop()); //stop mic use because we need only outputs
navigator.mediaDevices.enumerateDevices().then(o=>{
const outputs = o.filter(({ kind, deviceId }) => kind === 'audiooutput' && deviceId !== 'default' && deviceId !== 'communications');
let audioSrc = getAudioSrc(), players = [];
audioSrc.src.pause(); // Pause source to start audio in sync ?
audioSrc.src.addEventListener("pause", () => players.forEach(x=>x.pause()));
audioSrc.src.addEventListener("play", () => players.forEach(x=>x.play()));
outputs.forEach((x)=>{
let ifrm = makeIFrame(), audioEl = makeAudio(ifrm.document, audioSrc.s, x.deviceId);
players.push(audioEl);
});
});
}).catch(e=>console.log(e));