Feroz Siddiqui
Feroz Siddiqui

Reputation: 4096

Chrome Extension: Record Microphone and Speaker in Background JS

As per latest updates what is proper way to capture microphone and speaker audio for real time audio processing in background js. I am stuck at this I have tried all media recorder api,record js api and chrome desktop capture but all of them are returning microphone audio. None of them will be able to capture the speaker audio. Please suggest a way to implement this scenario

below is sample code which capture microphone but not speakers:

var audioChunks;
startRecord.onclick = e => {
  startRecord.disabled = true;
  stopRecord.disabled=false;
  // This will prompt for permission if not allowed earlier
  navigator.mediaDevices.getUserMedia({audio:true})
    .then(stream => {
      audioChunks = []; 
      rec = new MediaRecorder(stream);
      rec.ondataavailable = e => {
        audioChunks.push(e.data);
        if (rec.state == "inactive"){
          let blob = new Blob(audioChunks,{type:'audio/x-mpeg-3'});
          recordedAudio.src = URL.createObjectURL(blob);
          recordedAudio.controls=true;
          recordedAudio.autoplay=true;
          audioDownload.href = recordedAudio.src;
          audioDownload.download = 'mp3';
          audioDownload.innerHTML = 'download';
       }
      }
    rec.start();  
    })
    .catch(e=>console.log(e));
}
stopRecord.onclick = e => {
  startRecord.disabled = false;
  stopRecord.disabled=true;
  rec.stop();
}

Upvotes: 4

Views: 2581

Answers (2)

Vasanth Gopal
Vasanth Gopal

Reputation: 1285

Here is a sample code which lists all available devices.

navigator.mediaDevices.enumerateDevices()
.then((devicesInfo)) => {
// Expect devices of kind `audioinput`, `audiooutput`, `videoinput` and other media cards available.
// Internal default speakers would fall under `audiooutput` and internal default microphone would fall under `audioinput`.
const select = document.createElement('select');
devicesInfo.forEach((device, index) => {
    const option = document.createElement('option');
    option.value = deviceInfo.deviceId;

    if(deviceInfo.kind === 'audioinput')
      option.text = deviceInfo.label;

    select.appendChild(option);
})
document.body.appendChild(select);

...
// Let user make the selection of device. Once selected, start the recording.
...

// select.value has the selected deviceId. Use `onChange` event of select to capture the value.
const constraints = {
    audio: {deviceId: select.value ? {exact: select.value} : undefined}
  };
  
  var audioChunks = [];
  navigator.mediaDevices.getUserMedia(constraints)
  .then((stream) => {
      window.stream = stream; // make stream available to console
  
      var rec = new MediaRecorder(stream);
      rec.ondataavailable = (e) => {
          audioChunks.push(e.data);
          if (rec.state == "inactive"){
              let blob = new Blob(audioChunks,{type:'audio/x-mpeg-3'});
              const recording = document.createElement('audio');
              recording.id = "recording";
              recording.src = URL.createObjectURL(blob);
              recording.controls=true;
              recording.autoplay=true;
              document.body.removeChild(document.getElementById('recording'));
              document.body.appendChild(downloadLink);

              const downloadLink = document.createElement('a');
              downloadLink.id = "downloadLink";
              downloadLink.href = recordedAudio.src;
              downloadLink.download = 'mp3';
              downloadLink.innerHTML = 'download';
              document.body.removeChild(document.getElementById('downloadLink'));
              document.body.appendChild(downloadLink);
    };

    // Start recording whenever user prefers to start.
    rec.start();

    ...
    ...


    // Stop recording whenever user prefers to stop.
    rec.stop();
  }
  })

}

Let know if this is what you are looking for.

Upvotes: -2

James Tomasino
James Tomasino

Reputation: 3581

When you first initiate a call to getUserMedia your available devices will only be audio (meaning microphone) and camera (default webcam). However, if you call enumerateDevices you will get back a list of all available audio devices. You can then specify the specific id of your audio card like so:

navigator.mediaDevices.getUserMedia({audio:{deviceId:{exact: deviceId}}})

This takes two calls to getUserMedia with an await in there to get working properly. Also, I should note that the devicechange event doesn't fire in Chromium browsers for mediaDevices. That will make it harder to detect configuration changes.

For a background extension I think you'll have to play around a bit to get this working right. You could present the list of devices to the user and let them choose, but that will take some messaging to your front-end script and back again, complicating your setup.

Upvotes: 6

Related Questions