Skip to content

Instantly share code, notes, and snippets.

@aztack
Created November 18, 2022 06:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aztack/b7ba85347a82562d0c04d221754f5c12 to your computer and use it in GitHub Desktop.
Save aztack/b7ba85347a82562d0c04d221754f5c12 to your computer and use it in GitHub Desktop.
recordCanvasStream
**
* Record canvas stream into a webm file
* @param canvas HTMLCanvasElement
* @param options {duration: number, fps: number}
* @returns Promise<Blob> | ((discard:boolean) => Promise<Blob|null>)
* @example
* // Stop after 5 seconds
* const blob = await recordCanvasStream(canvas, { duration: 5, fps: 30 });
* downloadBlob(blob, 'recording.webm');
*
* // Stop manually
* const stop = recordCanvasStream(canvas);
* saveButton.onclick = () => {
* const blob = await stop();
* downloadBlob(blob, 'recording.webm');
* };
* discardButton.onclick = () => {
* stop(true);
* };
*
*/
export function recordCanvasStream(canvas: HTMLCanvasElement, options?: {duration: number, fps: number})
: Promise<Blob>
| ((discard: boolean) => Promise<Blob | null>)
{
if (!canvas) {
throw new Error('Canvas is required');
}
if (!canvas.captureStream) {
throw new Error('Canvas.captureStream is not supported');
}
const { duration, fps = 30 } = options ?? {};
const canvasStream = canvas.captureStream(fps);
const chunks: Blob[] = [];
const mediaRecorder = new MediaRecorder(canvasStream, { mimeType: 'video/webm' });
const record = () => {
mediaRecorder.start();
mediaRecorder.ondataavailable = e => {
if (e.data.size) {
chunks.push(e.data);
}
};
};
if (duration) {
return new Promise<Blob>(resolve => {
record();
mediaRecorder.onstop = () => {
resolve(new Blob(chunks, { type: 'video/webm' }));
};
setTimeout(() => {
mediaRecorder.stop();
}, duration);
});
} else {
record();
return (discard: boolean = false) => {
return new Promise(resolve => {
try {
mediaRecorder.stop();
mediaRecorder.onstop = () => {
if (discard) {
chunks.length = 0;
resolve(null);
} else {
resolve(new Blob(chunks, { type: 'video/webm' }));
}
};
} catch (e) {
resolve(null);
}
});
};
}
}
function downloadBlob(blob: Blob, fileName: string) {
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = fileName;
a.click();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment