8

I'm trying to get the output of the speaker and then do what ever I want with this stream .

I tried to use this to get the speaker's stream:

var mySpeakerStream = new MediaStream();
navigator.mediaDevices.getUserMedia({audio: {deviceId : {exact: mySpeakerId} } }).then(s => {        
        myStream.addTrack(s.getAudioTracks()[0]);
}).catch( console.log('failed') );

I expected to get the speaker but I did not , then I realised that the getUserMedia method returns a MediaStream of an input device only. Is there any way to get a stream of the speaker's output?

2 Answers2

6

JavaScript media devices behave exactly in the same way as the system audio devices. If you are able to record the device in something like Audacity (or any sound recorder), you will be able to record the device in JavaScript using a media device.

However, getting access to the speaker's output requires set up on the operating system of the computer - probably for security, amongst other reasons.

This can be done by creating an audio loopback device on the operating system, but creating the loopback can't be done purely via client-side JavaScript, as of October 2019.

Greg
  • 21,235
  • 17
  • 84
  • 107
4

after more thinking about the issue I found that: I can use getDisplyMedia method but it doesn't support audio only requests, so I tried to get the stream of both audio and video then I get the audio tracks out of it just like this:

var speaker = new MediaStream;
if (navigator.getDisplayMedia) {
    navigator.getDisplayMedia({
        video: true ,
        audio: true
    }).then(stream => {
        speaker.addTrack(stream.getAudioTracks()[0].clone());
        // stopping and removing the video track to enhance the performance
        stream.getVideoTracks()[0].stop();
        stream.removeTrack(stream.getVideoTracks()[0]);
    }).catch(() => {
        console.error('failed')
    });
} else if (navigator.mediaDevices.getDisplayMedia) {
    navigator.mediaDevices.getDisplayMedia({
        video: true ,
        audio: true
    }).then(stream => {
        speaker.addTrack(stream.getAudioTracks()[0].clone());
        // stopping and removing the video track to enhance the performance
        stream.getVideoTracks()[0].stop();
        stream.removeTrack(stream.getVideoTracks()[0]);
    }).catch(() => {
        console.error('failed')
    });
}

I know that does not solve the issue perfectly but I think it's useful .

'still working and waiting for more solutions'

  • I've come to this same conclusion so far. Have you since been able to to take this any further - capturing audio WITHOUT the DisplayMedia workaround? – calipoop Sep 02 '20 at 20:17
  • No actually, I used this answer back then and I didn't work on media streaming since then. – Albaraa Alshahhoud Jun 12 '22 at 15:45