Skip to content

Instantly share code, notes, and snippets.

@signalwerk
Last active March 31, 2024 16:00
Show Gist options
  • Save signalwerk/81eb1c3b01524d31a6c830fe9f05ff67 to your computer and use it in GitHub Desktop.
Save signalwerk/81eb1c3b01524d31a6c830fe9f05ff67 to your computer and use it in GitHub Desktop.
Record from a canvas element to a webm file
// 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