Article remote control track
by jib1
HTML
<table><tr valign="top"><td><fieldset id="buttons">
<legend>Remote control:</legend>
<button onclick='transceiver = pc1.addTransceiver(trackA, {streams})'>transceiver = pc.addTransceiver(trackA, {streams})</button><br>
<button onclick='transceiver.direction = "recvonly"'>tranceiver.direction = "recvonly"</button><br>
<button onclick='transceiver.direction = "sendrecv"'>tranceiver.direction = "sendrecv"</button><br>
<button onclick='transceiver.sender.track.enabled = false'>transceiver.sender.track.enabled = false</button><br>
<button onclick='transceiver.sender.track.enabled = true'>transceiver.sender.track.enabled = true</button><br>
<button onclick='transceiver.sender.replaceTrack(trackB)'>transceiver.sender.replaceTrack(trackB)</button><br>
<button onclick='transceiver.sender.replaceTrack(trackA)'>transceiver.sender.replaceTrack(trackA)</button><br>
<button onclick='transceiver.sender.replaceTrack(null)'>transceiver.sender.replaceTrack(null)</button><br>
<button onclick='transceiver.stop()'>transceiver.stop()</button><br>
</fieldset>
You can repeat the above sequence<br>
<button onclick='trackA.stop();trackB.stop();buttons.disabled = true'>Stop Example</button><br>
</td>
<td>
<div id="div"></div>
</td>
<td>
<video id="video" width="320" height="240" autoplay></video><br>
</td>
</tr></table>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
JavaScript
let [pc1, pc2] = localPeerConnectionLoop(), transceiver, streams, trackA, trackB;
pc2.ontrack = ({transceiver, streams: [stream]}) => {
log("pc.ontrack with transceiver and streams");
stream.onaddtrack = () => log("stream.onaddtrack");
stream.onremovetrack = () => log("stream.onremovetrack");
transceiver.receiver.track.onmute = () => log("transceiver.receiver.track.onmute");
transceiver.receiver.track.onended = () => log("transceiver.receiver.track.onended");
transceiver.receiver.track.onunmute = () => {
log("transceiver.receiver.track.onunmute");
video.srcObject = stream;
};
};
(async () => {
try {
pc1.createDataChannel("dummy");
await new Promise(r => pc1.onsignalingstatechange = () => pc1.signalingState == "stable" && r());
streams = [await navigator.mediaDevices.getUserMedia({video: true})];
trackA = streams[0].getTracks()[0];
trackB = whiteNoise();
} catch (e) {
log(e);
}
})();
function localPeerConnectionLoop(cfg = {sdpSemantics: 'unified-plan'}) {
const setD = (d, a, b) => Promise.all([a.setLocalDescription(d), b.setRemoteDescription(d)]);
return [0, 1].map(() => new RTCPeerConnection(cfg)).map((pc, i, pcs) => Object.assign(pc, {
onicecandidate: e => pcs[i ^ 1].addIceCandidate(e.candidate),
onnegotiationneeded: async e => {
try {
await setD(await pc.createOffer(), pc, pcs[i ^ 1]);
await setD(await pcs[i ^ 1].createAnswer(), pcs[i ^ 1], pc);
} catch (e) {
log(e);
}
}
}));
}
function whiteNoise() {
let canvas = Object.assign(document.createElement("canvas"), {width: 320, height: 240});
let ctx = canvas.getContext('2d');
ctx.fillRect(0, 0, canvas.width, canvas.height);
let p = ctx.getImageData(0, 0, canvas.width, canvas.height);
requestAnimationFrame(function draw(){
for (var i = 0; i < p.data.length; i++) {
p.data[i++] = p.data[i++] = p.data[i++] = Math.random() * 255;
}
ctx.putImageData(p, 0, 0);
...