0

I'm stuck with a problem in which whenever I pass the stream from createMediaStreamDestination to an audio element srcObject, no audio is being played. My implementation is based off of the response posted here Combine setSinkId with stereoPanner?

Initially, I have an audio element in which I isolate the sound so that it would only play from the left speaker

    const audio = document.createElement('audio');
    audio.src = audioUrl;

    let audioContext = new AudioContext();
    let source = audioContext.createMediaElementSource(audio);
    let panner = audioContext.createStereoPanner();
    let destination = audioContext.destination;

    panner.pan.value = -1;

    source.connect(panner).connect(destination);

The above plays sound fine when I add audio.play() but I want to be able to set specifically the speakers that the audio would play out of while keeping the panner changes. Since audioContext doesn't contain any possibility of setting the sinkId yet, I created a new audio element and mediastreamdestination and passed the mediaStream into the source object

    const audio = document.createElement('audio');

    audio.src = audioUrl;

    let audioContext = new AudioContext();
    let source = audioContext.createMediaElementSource(audio);
    let panner = audioContext.createStereoPanner();
    let destination = audioContext.createMediaStreamDestination();

    panner.pan.value = -1;

    source.connect(panner).connect(destination);

    const outputAudio = new Audio();
    outputAudio.srcObject = destination.stream;
    outputAudio.setSinkId(audioSpeakerId);
    outputAudio.play();

With the new code, however, when I start up my application, the outputAudio doesn't play any sound at all. Is there anything wrong with my code that is causing the outputAudio element not to play sound? I'm fairly new to web audio api and I tried implementing the code from the mentioned stackoverflow thread but it doesn't seem to be working for me. Any help would be appreciated!

vwg
  • 1
  • 1

1 Answers1

0

In the description of your first code block you mention that you additionally also call audio.play() to start the audio. That's also necessary for the second code block to work. You need to start both audio elements.

Generally calling play() on an audio element and creating a new AudioContext should ideally happen in response to a user action to make sure the browser's autoplay policy doesn't block the audio.

If all goes well the state of your AudioContext should be "running".

chrisguttandin
  • 7,025
  • 15
  • 21
  • Hey Chris, thanks for the response! Would it be possible to only allow the outputAudio element with the setSinkId to play? In my case I don't want the first audio element to play as that would play sound from both my system speaker and my set speaker. I only want sound to be produced from the audio element with a sinkId set. Would simply muting the first audio element work? – vwg Aug 30 '22 at 19:30
  • It should do that automatically. You should only hear the last audio element. Here is the relevant part from the spec: "As a consequence of calling this method, audio playback from the HTMLMediaElement will be re-routed into the processing graph of the AudioContext." – chrisguttandin Sep 03 '22 at 10:24