Last active
December 16, 2020 23:40
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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