diff options
| author | cashmere <cashmere@autistici.org> | 2026-07-28 19:41:14 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-07-28 19:41:14 +0200 |
| commit | e837e7504379e100ff3b56282577ec67bb88bec9 (patch) | |
| tree | eec7e6f964725a783a9e907e931862591bb46b55 /apps/web/src/core | |
| parent | da99dec8a2de1f3849aebbf5695c1e812b2dbdf9 (diff) | |
| download | opencut-e837e7504379e100ff3b56282577ec67bb88bec9.tar.gz | |
feat: ripple-extend resize, timeline filmstrip, export hardening
Yesterday's verified web session (gates green: 316 tests, tsc, build):
- ripple-extend pushes right-hand chain on static-element resize
- per-position video filmstrip thumbnails with zoom-adaptive density
- fps-aware export bitrate, 2s keyframes, even-dim export canvas
- freeze frame uses fixed 3s duration, prompt removed
Diffstat (limited to 'apps/web/src/core')
| -rw-r--r-- | apps/web/src/core/managers/media-manager.ts | 3 | ||||
| -rw-r--r-- | apps/web/src/core/managers/renderer-manager.ts | 11 |
2 files changed, 10 insertions, 4 deletions
diff --git a/apps/web/src/core/managers/media-manager.ts b/apps/web/src/core/managers/media-manager.ts index 69da6e80..739fd3fa 100644 --- a/apps/web/src/core/managers/media-manager.ts +++ b/apps/web/src/core/managers/media-manager.ts @@ -4,6 +4,7 @@ import type { MediaAsset } from "@/media/types"; import { storageService } from "@/services/storage/service"; import { generateUUID } from "@/utils/id"; import { videoCache } from "@/services/video-cache/service"; +import { thumbnailCache } from "@/services/thumbnail-cache/service"; import { waveformCache } from "@/services/waveform-cache/service"; import { BatchCommand, RemoveMediaAssetCommand } from "@/commands"; @@ -103,6 +104,7 @@ export class MediaManager { } async clearProjectMedia({ projectId }: { projectId: string }): Promise<void> { + thumbnailCache.clearAll(); waveformCache.clearAll(); this.assets.forEach((asset) => { @@ -131,6 +133,7 @@ export class MediaManager { clearAllAssets(): void { videoCache.clearAll(); + thumbnailCache.clearAll(); waveformCache.clearAll(); this.assets.forEach((asset) => { diff --git a/apps/web/src/core/managers/renderer-manager.ts b/apps/web/src/core/managers/renderer-manager.ts index 38d1e57f..d73e3e58 100644 --- a/apps/web/src/core/managers/renderer-manager.ts +++ b/apps/web/src/core/managers/renderer-manager.ts @@ -6,7 +6,6 @@ import { SceneExporter } from "@/services/renderer/scene-exporter"; import { buildScene } from "@/services/renderer/scene-builder"; import { createTimelineAudioBuffer } from "@/media/audio"; import { formatTimecode } from "opencut-wasm"; -import { frameRateToFloat } from "@/fps/utils"; import { downloadBlob } from "@/utils/browser"; type SnapshotResult = @@ -192,6 +191,10 @@ export class RendererManager { const exportFps = fps ?? activeProject.settings.fps; const canvasSize = activeProject.settings.canvasSize; + const exportSize = { + width: 2 * Math.round(canvasSize.width / 2), + height: 2 * Math.round(canvasSize.height / 2), + }; let audioBuffer: AudioBuffer | null = null; if (includeAudio) { @@ -207,13 +210,13 @@ export class RendererManager { tracks, mediaAssets, duration, - canvasSize, + canvasSize: exportSize, background: activeProject.settings.background, }); const exporter = new SceneExporter({ - width: canvasSize.width, - height: canvasSize.height, + width: exportSize.width, + height: exportSize.height, fps: exportFps, format, quality, |
