summaryrefslogtreecommitdiff
path: root/apps/web/src/core
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-07-28 19:41:14 +0200
committercashmere <cashmere@autistici.org>2026-07-28 19:41:14 +0200
commite837e7504379e100ff3b56282577ec67bb88bec9 (patch)
treeeec7e6f964725a783a9e907e931862591bb46b55 /apps/web/src/core
parentda99dec8a2de1f3849aebbf5695c1e812b2dbdf9 (diff)
downloadopencut-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.ts3
-rw-r--r--apps/web/src/core/managers/renderer-manager.ts11
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,