Last active
March 31, 2024 16:00
-
-
Save signalwerk/81eb1c3b01524d31a6c830fe9f05ff67 to your computer and use it in GitHub Desktop.
Record from a canvas element to a webm file
This file contains 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
// convert .webm to .mp4 and remove audio | |
// ffmpeg -i in.webm -vcodec h264 -an out.mp4 | |
function dateString() { | |
const now = new Date(); | |
return ( | |
now.getUTCFullYear() + | |
"-" + | |
("0" + (now.getUTCMonth() + 1)).slice(-2) + | |
"-" + | |
("0" + now.getUTCDate()).slice(-2) + | |
"--" + | |
("0" + now.getUTCHours()).slice(-2) + | |
"-" + | |
("0" + now.getUTCMinutes()).slice(-2) + | |
"-" + | |
("0" + now.getUTCSeconds()).slice(-2) | |
); | |
} | |
function setupCanvasRecording() { | |
// get the first canvas element to record | |
const canvas = document.querySelector("canvas"); | |
const fps = 25; // frames per second recorded | |
const duration = 10; // in seconds | |
const videoBitsPerSecond = 500; // in Mbps | |
const audioBitsPerSecond = 128; // in Kbps | |
const format = "webm"; | |
const codec = "vp9"; | |
const type = `video/${format}`; | |
const mimeType = `${type};codecs=${codec}`; | |
// recorder options | |
const options = { | |
mimeType, | |
audioBitsPerSecond: audioBitsPerSecond * 1000, | |
videoBitsPerSecond: videoBitsPerSecond * 1000000, | |
}; | |
// download helper | |
const download = (blob) => { | |
const url = window.URL.createObjectURL(blob); | |
const a = document.createElement("a"); | |
a.style.display = "none"; | |
a.href = url; | |
a.download = `recording_${dateString()}_${videoBitsPerSecond}Mbps.${format}`; | |
document.body.appendChild(a); | |
a.click(); | |
setTimeout(function () { | |
document.body.removeChild(a); | |
window.URL.revokeObjectURL(url); | |
}, 300); | |
}; | |
// setup recorder & stream | |
const stream = canvas.captureStream(fps); | |
const recorder = new MediaRecorder(stream, options); | |
let blobs = []; | |
recorder.ondataavailable = (e) => { | |
if (e.data && e.data.size > 0) { | |
console.log(e.data); | |
blobs.push(e.data); | |
} | |
}; | |
recorder.onstop = (e) => { | |
console.log("recording stopped"); | |
download(new Blob(blobs, { type })); | |
blobs = []; | |
}; | |
return recorder; | |
} | |
// Usage | |
const recorder = setupCanvasRecording(); | |
recorder.start(100); // collect im 100ms chunks | |
recorder.stop(); | |
// stop the recording after 10sec | |
// setTimeout(() => { | |
// recorder.stop(); | |
// }, duration * 1000); | |
// // start/stop recording with F1/F2 | |
// window.onkeydown = (evt) => { | |
// switch (evt.key) { | |
// case "F1": | |
// console.log("recording started"); | |
// recorder.start(100); // collect im 100ms chunks | |
// break; | |
// case "F2": | |
// console.log("recording stopped"); | |
// recorder.stop(); | |
// break; | |
// // Fallback to default browser behaviour | |
// default: | |
// return true; | |
// } | |
// }; | |
// save canvas as PNG | |
function downloadPNG() { | |
const canvas = document.querySelector("canvas"); | |
var url = canvas.toDataURL(); | |
// Create a link | |
const a = document.createElement("a"); | |
a.style.display = "none"; | |
a.href = url; | |
a.download = `capture_${dateString()}.png`; | |
document.body.appendChild(a); | |
a.click(); | |
setTimeout(function () { | |
document.body.removeChild(a); | |
window.URL.revokeObjectURL(url); | |
}, 300); | |
} | |
downloadPNG(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment