Skip to content

Instantly share code, notes, and snippets.

@kwindla
Last active December 16, 2020 23:40
Show Gist options
  • Save kwindla/8c392bb52c57ee28ad02962eb4051584 to your computer and use it in GitHub Desktop.
Save kwindla/8c392bb52c57ee28ad02962eb4051584 to your computer and use it in GitHub Desktop.
Use a canvas MediaStream as a custom videoSource with the Daily video calls API
<html>
<head>
<title>custom video source from canvas element</title>
<script src="https://unpkg.com/@daily-co/daily-js"></script>
</head>
<body onload="main()">
<div id="local-controls" style="width: 50%; float: left; visibility: hidden">
<button onclick="switchToCanvas()" />switch to canvas</button>
<button onclick="switchToCamera()" />switch to camera</button>
<hr />
<canvas id="can" width="640" height="320" style="width: 100%"></canvas>
</div>
<div id="videos" style="margin-left: 50%"></div>
<script>
async function main() {
setupCanvas();
const ROOM_URL = YOUR-ROOM-URL;
window.callObject = DailyIframe.createCallObject({
dailyConfig: {
experimentalChromeVideoMuteLightOff: true,
},
});
callObject.on("track-started", displayVideo);
callObject.on("track-stopped", destroyVideo);
await callObject.join({ url: ROOM_URL });
document.getElementById('local-controls').style.visibility = 'visible';
window.cameraDeviceId = (await callObject.getInputDevices()).camera.deviceId;
}
function setupCanvas() {
window.canvas = document.getElementById("can");
window.context = canvas.getContext("2d");
animationFrame(context);
window.canvasStream = canvas.captureStream(20);
window.angle = 0;
}
function animationFrame() {
window.angle += 0.01;
context.save();
context.resetTransform();
context.fillStyle = '#F8C471';
context.fillRect(0, 0, canvas.width, canvas.height);
context.restore();
context.save();
context.transform(1, 0, 0, 1, canvas.width/2, canvas.height/2);
context.rotate(window.angle);
context.transform(1, 0, 0, 1, canvas.width/-2, canvas.height/-2);
context.beginPath();
context.moveTo(canvas.width/2, canvas.height/2);
context.lineTo(canvas.width, canvas.height/2);
context.strokeStyle = '#2C3E50';
context.stroke();
context.restore();
requestAnimationFrame(animationFrame);
}
async function switchToCanvas() {
await callObject.setInputDevicesAsync({
videoSource: canvasStream.getVideoTracks()[0],
});
}
async function switchToCamera() {
await callObject.setInputDevicesAsync({
videoDeviceId: cameraDeviceId,
});
}
function displayVideo(evt) {
console.log(evt);
if (!(evt.track.kind === "video")) {
return;
}
let videosDiv = document.getElementById("videos");
let videoEl = document.createElement("video");
videosDiv.appendChild(videoEl);
videoEl.style.width = "100%";
videoEl.srcObject = new MediaStream([evt.track]);
videoEl.play();
}
function destroyVideo(evt) {
let vids = document.getElementsByTagName("video");
for (let vid of vids) {
if (vid.srcObject.getVideoTracks()[0] === evt.track) {
vid.remove();
}
}
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment