p5.record.js
Version:
p5.js addon providing functions to record HTML canvas based sketches
105 lines (87 loc) • 2.61 kB
text/typescript
import { SequenceRecorder, imageTypesMap } from "./SequenceRecorder";
interface RecorderOptions {
frameRate: "manual" | number,
source: HTMLCanvasElement | {
canvas: HTMLCanvasElement
},
mimeType?: string,
stopCallback?: (blob: Blob) => void
}
export class Recorder {
#stream: MediaStream;
#recorder: MediaRecorder | SequenceRecorder;
constructor(options: RecorderOptions) {
const frameRate = options.frameRate === "manual" ? 0 : options.frameRate;
const chunks = [];
const canvas = (
options.source instanceof HTMLCanvasElement ?
options.source :
options.source.canvas
);
const stream = canvas.captureStream(frameRate);
let recorder: MediaRecorder | SequenceRecorder;
if(Object.keys(imageTypesMap).includes(options.mimeType)){
recorder = new SequenceRecorder(canvas, options.mimeType, frameRate);
}else{
recorder = new MediaRecorder(stream, {
mimeType: options.mimeType ?? "video/webm;codecs=vp8"
});
}
recorder.addEventListener("start", () => {
console.log("recording started");
});
recorder.addEventListener("stop", (e: Event) => {
let blob: Blob, filename: string;
if(this.#recorder instanceof SequenceRecorder){
blob = (e as CustomEvent).detail.blob;
filename = "recording.zip";
}else{
blob = new Blob(chunks);
filename = "recording.webm";
}
const executeDefault = typeof options?.stopCallback === "function" ?
options?.stopCallback(blob) :
true;
if(executeDefault){
const blobUrl = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = blobUrl;
link.download = filename;
link.click();
}
});
(recorder as MediaRecorder).addEventListener("dataavailable", (e: BlobEvent) => {
chunks.push(e.data);
});
recorder.addEventListener("pause", () => {
console.log("recording paused");
});
recorder.addEventListener("resume", () => {
console.log("recording resumed");
});
this.#recorder = recorder;
this.#stream = stream;
}
get state() {
return this.#recorder.state;
}
start() {
this.#recorder.start();
}
stop() {
this.#recorder.stop();
}
pause() {
this.#recorder.pause();
}
resume() {
this.#recorder.resume();
}
frame() {
if(this.#recorder instanceof SequenceRecorder){
this.#recorder.frame();
}else{
(this.#stream.getVideoTracks()[0] as CanvasCaptureMediaStreamTrack).requestFrame();
}
}
}