Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MediaRecorder: Record from Multiple Microphones

I am currently using the MediaRecorder API to record audio inside an application.

Is there a way to record from multiple input devices, say, two microphones?

I can get a list of devices using mediaDevices.enumerateDevices(), as demonstrated here.

Ideally, if possible, I would like to select two or more devices to be recorded.

Is this possible?

like image 846
Enijar Avatar asked Nov 01 '17 16:11

Enijar


2 Answers

The solution to this was to request multiple getUserMedia and mix the streams with AudioContext.

Here's how to do that.

const VIDEO_ID = "video_id";
const MIC_1_ID = "mic_1_id";
const MIC_2_ID = "mic_2_id";

// Request permission
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(() => {
  // Loop over all available video and audio devices (input and output)
  navigator.mediaDevices.enumerateDevices().then((devices) => {
    // Request exact devices
    const requests = [
      navigator.mediaDevices.getUserMedia({
        video: { deviceId: { exact: VIDEO_ID } },
      }),
      navigator.mediaDevices.getUserMedia({
        video: false,
        audio: { deviceId: { exact: MIC_1_ID } },
      }),
      navigator.mediaDevices.getUserMedia({
        video: false,
        audio: { deviceId: { exact: MIC_2_ID } },
      }),
    ];

    // Wait for all device requests to resolve.
    Promise.all(requests).then((streams) => {
      const ctx = new AudioContext();
      const dest = ctx.createMediaStreamDestination();

      // Connect streams to the destination audio stream.
      streams.map((stream) => {
        ctx.createMediaStreamSource(stream).connect(dest);
      });

      const videoTrack = streams[0].getTracks()[0];
      const mixedTracks = dest.stream.getTracks()[0];

      // Combine video and audio tracks into single stream.
      const stream = new MediaStream([videoTrack, mixedTracks]);

      // Start recorder
      const recorder = new MediaRecorder(stream, { mimeType: "video/mp4" });

      // ...
    });
  });
});
like image 107
Enijar Avatar answered Nov 03 '22 01:11

Enijar


this function will merge your tracks into one:

function mix(audioContext, streams) {
  const dest = audioContext.createMediaStreamDestination();
  streams.forEach(stream => {
    const source = audioContext.createMediaStreamSource(stream);
    source.connect(dest);
  });
  return dest.stream.getTracks()[0];
}
like image 43
Gergely Vízvári Avatar answered Nov 02 '22 23:11

Gergely Vízvári