From 65bc21f1538e29606d826ad58df9e58b0d1199a0 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Fri, 28 Nov 2025 17:41:30 -0700 Subject: [PATCH] fix the bug i just introduced lol --- src/lib/exporter/frameRenderer.ts | 77 ++++++++++++++++--------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/src/lib/exporter/frameRenderer.ts b/src/lib/exporter/frameRenderer.ts index ffe1f84..f5d2000 100644 --- a/src/lib/exporter/frameRenderer.ts +++ b/src/lib/exporter/frameRenderer.ts @@ -3,9 +3,8 @@ import type { ZoomRegion, CropRegion } from '@/components/video-editor/types'; import { ZOOM_DEPTH_SCALES } from '@/components/video-editor/types'; import { findDominantRegion } from '@/components/video-editor/videoPlayback/zoomRegionUtils'; import { applyZoomTransform } from '@/components/video-editor/videoPlayback/zoomTransform'; -import { DEFAULT_FOCUS, SMOOTHING_FACTOR, MIN_DELTA } from '@/components/video-editor/videoPlayback/constants'; +import { DEFAULT_FOCUS, SMOOTHING_FACTOR, MIN_DELTA, VIEWPORT_SCALE } from '@/components/video-editor/videoPlayback/constants'; import { clampFocusToStage as clampFocusToStageUtil } from '@/components/video-editor/videoPlayback/focusUtils'; -import { layoutVideoContent as layoutVideoContentUtil } from '@/components/video-editor/videoPlayback/layoutUtils'; interface FrameRenderConfig { width: number; @@ -299,53 +298,57 @@ export class FrameRenderer { } private updateLayout(): void { - if (!this.app || !this.videoSprite || !this.maskGraphics || !this.videoContainer || !this.cameraContainer) return; + if (!this.app || !this.videoSprite || !this.maskGraphics || !this.videoContainer) return; const { width, height } = this.config; + const { cropRegion } = this.config; const videoWidth = this.config.videoWidth; const videoHeight = this.config.videoHeight; - // Create a mock container element for layoutVideoContentUtil - const mockContainer = { - clientWidth: width, - clientHeight: height, - } as HTMLDivElement; + // Calculate cropped video dimensions + const cropStartX = cropRegion.x; + const cropStartY = cropRegion.y; + const cropEndX = cropRegion.x + cropRegion.width; + const cropEndY = cropRegion.y + cropRegion.height; - // Create a mock video element with the actual dimensions - const mockVideoElement = { - videoWidth, - videoHeight, - } as HTMLVideoElement; + const croppedVideoWidth = videoWidth * (cropEndX - cropStartX); + const croppedVideoHeight = videoHeight * (cropEndY - cropStartY); + + // Calculate scale to fit in viewport (using VIEWPORT_SCALE from constants) + const viewportWidth = width * 0.8; // VIEWPORT_SCALE = 0.8 + const viewportHeight = height * 0.8; + const scale = Math.min(viewportWidth / croppedVideoWidth, viewportHeight / croppedVideoHeight); - // Use the same layout logic as preview - const layoutResult = layoutVideoContentUtil({ - container: mockContainer, - app: this.app, - videoSprite: this.videoSprite, - maskGraphics: this.maskGraphics, - videoElement: mockVideoElement, - cropRegion: this.config.cropRegion, - lockedVideoDimensions: { width: videoWidth, height: videoHeight }, - }); + // Position video sprite + this.videoSprite.width = videoWidth * scale; + this.videoSprite.height = videoHeight * scale; - if (!layoutResult) { - console.warn('[FrameRenderer] layoutVideoContentUtil returned null'); - return; - } + const cropPixelX = cropStartX * videoWidth * scale; + const cropPixelY = cropStartY * videoHeight * scale; + this.videoSprite.x = -cropPixelX; + this.videoSprite.y = -cropPixelY; - // Position the videoContainer (which contains the sprite and mask) - // Note: layoutVideoContentUtil positions the sprite within the container at (0,0) - // but in export we need to position the container itself - this.videoContainer.x = 0; - this.videoContainer.y = 0; + // Position video container + const croppedDisplayWidth = croppedVideoWidth * scale; + const croppedDisplayHeight = croppedVideoHeight * scale; + const centerOffsetX = (width - croppedDisplayWidth) / 2; + const centerOffsetY = (height - croppedDisplayHeight) / 2; + this.videoContainer.x = centerOffsetX; + this.videoContainer.y = centerOffsetY; + + // Update mask + const radius = Math.min(croppedDisplayWidth, croppedDisplayHeight) * 0.02; + this.maskGraphics.clear(); + this.maskGraphics.roundRect(0, 0, croppedDisplayWidth, croppedDisplayHeight, radius); + this.maskGraphics.fill({ color: 0xffffff }); // Cache layout info this.layoutCache = { - stageSize: layoutResult.stageSize, - videoSize: layoutResult.videoSize, - baseScale: layoutResult.baseScale, - baseOffset: layoutResult.baseOffset, - maskRect: layoutResult.maskRect, + stageSize: { width, height }, + videoSize: { width: croppedVideoWidth, height: croppedVideoHeight }, + baseScale: scale, + baseOffset: { x: centerOffsetX, y: centerOffsetY }, + maskRect: { x: 0, y: 0, width: croppedDisplayWidth, height: croppedDisplayHeight }, }; }