Skip to content

Instantly share code, notes, and snippets.

@greggman
Created February 4, 2026 02:58
Show Gist options
  • Select an option

  • Save greggman/3ce54ed24d11573c3e63ee5220a64fd2 to your computer and use it in GitHub Desktop.

Select an option

Save greggman/3ce54ed24d11573c3e63ee5220a64fd2 to your computer and use it in GitHub Desktop.
Make a video using canvas 2d
:root {
color-scheme: dark;
}
html, body {
height: 100%;
}
video {
max-width: 100%;
display: block;
}
/*bug-in-github-api-content-can-not-be-empty*/
const src = await generateVideo(2580, 1280);
const video = document.createElement('video');
document.body.append(video);
video.muted = true;
video.loop = true;
video.src = src;
video.play();
function generateVideo(width, height) {
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
const stream = canvas.captureStream(25);
const recordedChunks = [];
const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/mp4' });
mediaRecorder.ondataavailable = (e) => {
if (e.data.size > 0) {
recordedChunks.push(e.data);
}
};
mediaRecorder.onstop = () => {
const blob = new Blob(recordedChunks, { type: 'video/mp4' });
const url = URL.createObjectURL(blob);
const downloadLink = document.createElement('a');
downloadLink.href = url;
downloadLink.download = 'canvas-animation.mp4';
downloadLink.textContent = 'Download Video';
document.body.appendChild(downloadLink);
resolve(url);
};
mediaRecorder.start();
let requestId;
let frameCount = 0;
function drawFrame() {
ctx.fillStyle = '#333';
ctx.fillRect(0, 0, width, height);
ctx.beginPath();
ctx.lineWidth = 50;
ctx.strokeStyle = 'yellow';
for (let x = 0; x < width * 2; x += 100) {
ctx.save();
ctx.translate(-frameCount, 0)
ctx.moveTo(x, 0);
ctx.lineTo(x - height, height);
ctx.restore();
}
ctx.stroke();
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, width, 20);
ctx.fillRect(0, 0, 20, height);
ctx.fillRect(0, height - 20, width, 20);
ctx.fillRect(width - 20, 0, 20, height);
ctx.fillStyle = 'black';
ctx.font = '380px sans-serif';
ctx.fillText(`Frame ${frameCount}`, 10, 500);
frameCount++;
requestId = requestAnimationFrame(drawFrame);
}
requestId = requestAnimationFrame(drawFrame);
setTimeout(() => {
cancelAnimationFrame(requestId);
mediaRecorder.stop();
}, 4000);
});
}
{"name":"Make a video using canvas 2d","settings":{},"filenames":["index.html","index.css","index.js"]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment