【问题标题】:Is it possible to play the same audio on two audio output devices simultaneously是否可以同时在两个音频输出设备上播放相同的音频
【发布时间】:2021-11-14 10:00:53
【问题描述】:

我正在尝试制作一个脚本,该脚本从音频元素获取音频并同时在耳机和笔记本电脑扬声器上播放。 这可能吗?

这是我目前写的代码:

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

此代码的问题在于它使音频仅在另一个扬声器上播放,而不是在两个扬声器上播放。

请注意,该窗口可以访问麦克风,因此我可以看到来自navigator.mediaDevices.enumerateDevices() 的所有设备。 该脚本主要用于 Edge 和 Chrome。

【问题讨论】:

  • 虽然这可能是不可能的,但即使是这样我也不会这样做。您无法控制用户选择的音频输出,您也不应该控制。
  • 这样做的目的是在不失真的情况下增加音频响度。我只使用耳机进行测试。现实世界的场景是使用笔记本电脑扬声器和外部 USB 扬声器。
  • 不,你不能,用户在控制之中。
  • @Grumpy 你说的用户是什么意思?如果用户是我,我可以这样做吗?或者你的意思是js不能,只有用户可以手动(可能通过虚拟音频线)
  • 用户在控制中,用户选择输出,因为它应该是。

标签: javascript html5-audio web-audio-api


【解决方案1】:

我找到了解决办法!
由于我无法在同一个窗口中同时在多个设备上播放声音,因此我设法通过创建包含音频元素的 iframe 来完成此操作。 然后我将所有这些音频元素设置为相同的源,并将它们设置为在特定设备上输出音频,并将播放/停止与事件侦听器同步。

这是可行的,因为 iframe 由主窗口分隔。实际上我认为他们有自己的流程(在铬浏览器上)。

我的代码如下所示:(注意我使用的不是静态源,而是 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));

【讨论】:

    猜你喜欢
    • 2014-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多