hexa-viewer-communicator
Version:
A simple API for <hexa-viewer>
114 lines (103 loc) • 3.6 kB
text/typescript
export class ImageToVideo {
private cStream: MediaStream;
private recorder: MediaRecorder;
private chunks: Array<Blob>;
private wrap: HTMLDivElement;
private canvas: HTMLCanvasElement;
private ctx: CanvasRenderingContext2D;
private images: Array<string>;
private frame: number;
private resolve: Function;
private FPS: number;
private _codecs: string;
constructor(images: Array<string>) {
this._codecs = 'h264';
this.images = images;
this.chunks = [];
this.FPS = this.images.length / 15;
this.wrap = document.createElement("div");
this.wrap.style.cssText = `
position: absolute;
top: 0;
left: 0;
overflow: hidden;
opacity: 0.01;
z-index: -9999999;
max-width: 100%;
`;
this.canvas = document.createElement("canvas");
this.wrap.appendChild(this.canvas);
}
get codecs() {
return this._codecs;
}
set codecs(value: string) {
this._codecs = value;
}
getVideo() {
return new Promise((resolve: any, reject: any) => {
this.resolve = resolve;
document.body.appendChild(this.wrap);
this.frame = 0;
this.ctx = this.canvas.getContext("2d", { alpha: true });
const img = new Image();
img.onload = () => {
this.canvas.width = img.naturalWidth;
this.canvas.height = img.naturalHeight;
this.start();
this.anim();
};
img.src = this.images[0];
});
}
setTimeout(ms: number) {
return new Promise((resolve: any, reject: any) => {
setTimeout(() => {
resolve();
}, ms);
});
}
anim() {
const img = new Image();
img.onload = async () => {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.drawImage(img, 0, 0);
if (++this.frame < this.images.length) {
await this.setTimeout(1000 / this.FPS);
requestAnimationFrame(this.anim.bind(this));
} else this.stopRecording();
};
img.src = this.images[this.frame];
}
start() {
// set the framerate to 30FPS
this.cStream = this.canvas.captureStream(30);
// this.cStream = this.canvas.captureStream(this.images.length / 30);
// create a recorder fed with our canvas' stream
const options = {
// mimeType: 'video/webm',
// mimeType: "video/webm;codecs=h264",
mimeType: `video/webm;codecs=${this.codecs}`,
// mimeType: 'video/webm;codecs="vp9, av1"',
} as MediaRecorderOptions;
this.recorder = new MediaRecorder(this.cStream, options);
// start it
this.recorder.start();
// save the chunks
this.recorder.ondataavailable = this.saveChunks.bind(this);
this.recorder.onstop = this.exportStream.bind(this);
}
saveChunks(e: BlobEvent) {
this.chunks.push(e.data);
}
stopRecording() {
this.recorder.stop();
}
exportStream(e: Event) {
// combine all our chunks in one blob
// var blob = new Blob(this.chunks, { type: this.recorder.mimeType });
var blob = new Blob(this.chunks, { type: 'video/webm' });
this.resolve(blob);
this.wrap.remove();
}
}