diff options
| author | Maze <167211895+mazeincoding@users.noreply.github.com> | 2026-01-31 00:20:04 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-31 00:20:04 +0100 |
| commit | 7bf0984698e43b9aa2dd879f65951318ed410390 (patch) | |
| tree | ccf2cd590a47d550152afc07129cb55c71a9ec35 /apps/web/src/services/renderer/nodes/video-node.ts | |
| parent | 0173db99448d1c4c6415dcf15272e17551b48b04 (diff) | |
| download | opencut-7bf0984698e43b9aa2dd879f65951318ed410390.tar.gz | |
codebase overhaul (#697)
Diffstat (limited to 'apps/web/src/services/renderer/nodes/video-node.ts')
| -rw-r--r-- | apps/web/src/services/renderer/nodes/video-node.ts | 84 |
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(); + } + } +} |
