summaryrefslogtreecommitdiff
path: root/apps/web/src/services/renderer/nodes/video-node.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/services/renderer/nodes/video-node.ts')
-rw-r--r--apps/web/src/services/renderer/nodes/video-node.ts84
1 files changed, 84 insertions, 0 deletions
diff --git a/apps/web/src/services/renderer/nodes/video-node.ts b/apps/web/src/services/renderer/nodes/video-node.ts
new file mode 100644
index 00000000..01394b3d
--- /dev/null
+++ b/apps/web/src/services/renderer/nodes/video-node.ts
@@ -0,0 +1,84 @@
+import type { CanvasRenderer } from "../canvas-renderer";
+import { BaseNode } from "./base-node";
+import { videoCache } from "@/services/media/video-cache";
+
+const VIDEO_EPSILON = 1 / 1000;
+
+export interface BaseMediaNodeParams {
+ file: File;
+ duration: number;
+ timeOffset: number;
+ trimStart: number;
+ trimEnd: number;
+ x?: number;
+ y?: number;
+ width?: number;
+ height?: number;
+ opacity?: number;
+}
+
+export interface VideoNodeParams extends BaseMediaNodeParams {
+ mediaId: string;
+}
+
+export class VideoNode extends BaseNode<VideoNodeParams> {
+ private getVideoTime(time: number) {
+ return time - this.params.timeOffset + this.params.trimStart;
+ }
+
+ private isInRange(time: number) {
+ const videoTime = this.getVideoTime(time);
+ return (
+ videoTime >= this.params.trimStart - VIDEO_EPSILON &&
+ videoTime < this.params.trimStart + this.params.duration
+ );
+ }
+
+ async render({ renderer, time }: { renderer: CanvasRenderer; time: number }) {
+ await super.render({ renderer, time });
+
+ if (!this.isInRange(time)) {
+ return;
+ }
+
+ const videoTime = this.getVideoTime(time);
+ const frame = await videoCache.getFrameAt({
+ mediaId: this.params.mediaId,
+ file: this.params.file,
+ time: videoTime,
+ });
+
+ if (frame) {
+ renderer.context.save();
+
+ if (this.params.opacity !== undefined) {
+ renderer.context.globalAlpha = this.params.opacity;
+ }
+
+ if (
+ this.params.x !== undefined &&
+ this.params.y !== undefined &&
+ this.params.width !== undefined &&
+ this.params.height !== undefined
+ ) {
+ renderer.context.drawImage(
+ frame.canvas,
+ this.params.x,
+ this.params.y,
+ this.params.width,
+ this.params.height,
+ );
+ } else {
+ renderer.context.drawImage(
+ frame.canvas,
+ 0,
+ 0,
+ renderer.width,
+ renderer.height,
+ );
+ }
+
+ renderer.context.restore();
+ }
+ }
+}