是否可以同时在两个音频输出设备上播放相同的音频

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));