Establish a peer-to-peer connection and manage data channels for audio transmission.
by fippo
HTML
<video id="remoteVideo" autoplay muted></video>
<div id="log"></div>
JavaScript
function log(text) {
document.getElementById('log').innerText += text + '\n';
}
const pc1 = new RTCPeerConnection({alwaysNegotiateDataChannels: true});
const pc2 = new RTCPeerConnection();
pc1.onicecandidate = (e) => pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = (e) => pc1.addIceCandidate(e.candidate);
pc2.ontrack = e => remoteVideo.srcObject = e.streams[0];
pc1.addEventListener('connectionstatechange', () => log(pc1.connectionState));
async function run() {
const stream = await navigator.mediaDevices.getUserMedia({video: true});
pc1.createDataChannel('...');
pc1.addTransceiver('audio');
pc1.addTrack(stream.getTracks()[0], stream);
await pc1.setLocalDescription();
await pc2.setRemoteDescription(pc1.localDescription);
await pc2.setLocalDescription();
await pc1.setRemoteDescription(pc2.localDescription);
await new Promise(r => {
if (pc1.connectionState === 'connected') return r();
pc1.addEventListener('connectionstatechange', () => {
if (pc1.connectionState === 'connected') return r();
});
});
log('connected');
await new Promise(r => setTimeout(r, 1000)); // wait 1 seconds.
pc1.getTransceivers()[0].stop(); // stops the audio transceiver.
log('stopped transceiver, video will freeze');
await pc1.setLocalDescription();
await pc2.setRemoteDescription(pc1.localDescription);
await new Promise(r => setTimeout(r, 4000)); // wait 4 seconds.
log('renegotiated');
await pc2.setLocalDescription();
await pc1.setRemoteDescription(pc2.localDescription);
await new Promise(r => setTimeout(r, 1000)); // wait 1 seconds.
const stats = await pc2.getStats();
const freezes = [...stats.values()].filter(s => s.type === 'inbound-rtp' && s.kind === 'video').map(s => s.totalFreezesDuration);
log('FREEZE ' + JSON.stringify(freezes) + ' seconds');
}
run();