PeerConnection 2 gUMs
by Andreas Pehrson
HTML
<button onclick="start()">Start</button>
<button onclick="swap()">Change Audio track</button>
<br>
<video id="remote" style="width:120px;height:80px;"></video>
<div id="div"></div>
JavaScript
var log = msg => div.innerHTML += msg + "<br>";
let stream, pc1, pc2, videoTrack, audioTrack;
async function sendTracks() {
// Start the 1st gUM
stream = await navigator.mediaDevices.getUserMedia({audio: true, video: true});
videoTrack = stream.getVideoTracks()[0];
audioTrack = stream.getAudioTracks()[0];
// Set up the PCs
pc1 = new RTCPeerConnection();
pc2 = new RTCPeerConnection();
pc1.addEventListener('icecandidate', async e => await pc2.addIceCandidate(e.candidate));
pc1.addTrack(videoTrack, stream);
pc1.addTrack(audioTrack, stream);
const offer = await pc1.createOffer({
offerToReceiveAudio: 1
});
await pc1.setLocalDescription(offer);
pc2.addEventListener('icecandidate', async e => await pc1.addIceCandidate(e.candidate));
pc2.addEventListener('track', e => {
remote.srcObject = e.streams[0];
remote.play();
});
await pc2.setRemoteDescription(offer);
const answer = await pc2.createAnswer();
await pc2.setLocalDescription(answer);
await pc1.setRemoteDescription(answer);
}
async function start() {
try {
await sendTracks();
} catch(e) {
console.log(e);
log(e);
}
};
async function swap() {
try {
const devices = await navigator.mediaDevices.enumerateDevices();
let newId = "";
for (const device of devices) {
if (device.kind == "audioinput" && device.label != audioTrack.label) {
// First *other* microphone
newId = device.deviceId;
break;
}
}
// First stop the existing audio track
audioTrack.stop();
// 2nd gUM
const newStream = await navigator.mediaDevices.getUserMedia({
audio: {
deviceId: {
exact: newId,
},
},
});
// Replace track in PC
await pc1.getSenders()
.filter(s => s.track == audioTrack)[0]
.replaceTrack(newStream.getAudioTracks()[0]);
audioTrack = newStream.getAudioTracks()[0];
} catch(e) {
console.log(e);
log(e);
}
}