'How do you combine many audio tracks into one for mediaRecorder API?

I want to make a recording where, I get multiple audio tracks from different mediaStream objects (some of them, remote). Use the getAudioTracks () method and add them to a mediaStream object using addTrack (). At the moment of passing this last object as a parameter for mediaRecorder I realize that it only records the audio track located in position [0]. That gives me to understand that mediaRecorder is capable of recording a track by type, is there any way to join these tracks into one to record them correctly using mediaRecorder? I would be grateful for any page that explains this if possible and if it exists



Solution 1:[1]

I was battling with this for a while and took me ages to realise that the MediaStream only ever recorded the first track I added. My solution was to get the Web Audio API involved. This example uses two UserMedia (e.g. a mic & Stereo Mix) and merges them. The UserMedia are identified by their deviceId as shown when you use await navigator.mediaDevices.enumerateDevices().

In summary:

  • Create an AudioContext()
  • Get your media using navigator.mediaDevices.getUserMedia()
  • Add these as a stream source to the AudioContext
  • Create an AudioContext stream destination object
  • Connect your sources to this single destination
  • And your new MediaRecorder() takes this destination as its MediaStream

Now you can record yourself singing along to your favourite song as it streams ;)

const audioContext = new AudioContext();
audioParams_01 = {
    deviceId: "default",
}
audioParams_02 = {
    deviceId: "7079081697e1bb3596fad96a1410ef3de71d8ccffa419f4a5f75534c73dd16b5",
}

mediaStream_01 = await navigator.mediaDevices.getUserMedia({ audio: audioParams_01 });
mediaStream_02 = await navigator.mediaDevices.getUserMedia({ audio: audioParams_02 });

audioIn_01 = audioContext.createMediaStreamSource(mediaStream_01);
audioIn_02 = audioContext.createMediaStreamSource(mediaStream_02);

dest = audioContext.createMediaStreamDestination();

audioIn_01.connect(dest);
audioIn_02.connect(dest);

const recorder = new MediaRecorder(dest.stream);

chunks = [];

recorder.onstart = async (event) => {
    // your code here
}

recorder.ondataavailable = (event) => {       
    chunks.push(event.data); 
}

recorder.onstop = async (event) => {
    // your code here
}

Solution 2:[2]

Finish using a library built by muazKhan, which allows you to merge the streams and return them in one!

It's incredibly easy!

https://github.com/muaz-khan/MultiStreamsMixer

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Adam Marsh
Solution 2 lucas emanuel himelfarb