article setCodecPreferences negotiationneeded
My starting point.
by jib1
HTML
<button id="button">Start!</button>
pc1 codec: <select id="pc1Codec">
<option value="">Default</option>
<option value="video/VP8">VP8</option>
<option value="video/VP9">VP9</option>
<option value="video/H264">H264</option>
</select>
<br><br>
<video id="video1" width="160" height="120" autoplay muted></video>
<video id="video2" width="160" height="120" autoplay></video><br>
<div id="div" style="white-space: pre;"></div>
<div id="div1" style="white-space: pre;"></div>
<div id="div2" style="white-space: pre;"></div>
JavaScript
const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
pc1Codec.onchange = async () => {
try {
console.log(`Switching codec to ${pc1Codec.value}`);
const [transceiver] = pc1.getTransceivers();
const codecs = RTCRtpReceiver.getCapabilities("video").codecs;
sortByMimeTypes(codecs, [pc1Codec.value]);
transceiver.setCodecPreferences(codecs);
pc1.onnegotiationneeded(); // <--- hack
} catch (e) {
console.log(e);
}
};
button.onclick = async () => {
const stream = await navigator.mediaDevices.getUserMedia({video: true});
const [track] = stream.getVideoTracks();
pc1.addTrack(track, stream); // send camera track from pc1 → pc2
pc2.addTrack(track, stream); // send camera track from pc2 → pc1
video2.srcObject = (await new Promise(r => pc2.ontrack = r)).streams[0];
const unmuted2 = new Promise(r => video2.srcObject.getVideoTracks()[0].onunmute = r);
const [transceiver2] = pc2.getTransceivers();
video1.srcObject = (await new Promise(r => pc1.ontrack = r)).streams[0];
const unmuted1 = new Promise(r => video1.srcObject.getVideoTracks()[0].onunmute = r);
await Promise.all([unmuted1, unmuted2]); // wait on unmute for stats
while (true) {
update1(`pc1 is sending ${(await getOutboundCodecStat(pc1)).mimeType}`);
update2(`pc2 is sending ${(await getOutboundCodecStat(pc2)).mimeType}`);
await wait(500);
}
};
function sortByMimeTypes(codecs, preferredOrder) {
codecs.sort((a, b) => {
const indexA = preferredOrder.indexOf(a.mimeType);
const indexB = preferredOrder.indexOf(b.mimeType);
const orderA = indexA >= 0 ? indexA : Number.MAX_VALUE;
const orderB = indexB >= 0 ? indexB : Number.MAX_VALUE;
return orderA - orderB;
});
}
pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);
pc1.oniceconnectionstatechange = () => console.log(pc1.iceConnectionState);
pc1.onnegotiationneeded = async () => {
await...