- Expanded useVideoDurations to detect both form-sourced segments AND
editable-slot video fields inside content scenes
- Wired videoDurations into ProductionForm (getTemplateDuration,
compileExpressToTimeline, LivePreviewCanvas, ExportModal)
- LivePreviewCanvas now accepts videoDurations prop
- Simplified getTemplateDuration/compiler: any scene with a known
video duration uses it, regardless of segmentSource type
- A 33s uploaded video now creates a 33s timeline, not 5s
1. Audio/Video sync: During playback, let the browser handle media naturally
and only force-seek when drift > 250ms. Prevents audio glitching caused
by setting currentTime 30x/sec. When paused/scrubbing, sync precisely.
2. Blob URLs → Server uploads: All media uploads (BrandTabMedia, SceneFieldEditor,
TemplateFieldInput) now POST to /api/upload and use persistent server URLs
instead of blob: URLs that vanish on refresh.
3. Dynamic duration: Added useVideoDurations hook that probes actual video
durations from uploaded form videos. getTemplateDuration and
compileExpressToTimeline now accept videoDurations to override static
durationSeconds for form-sourced scenes.
Bug 1: RENDERS_DIR mismatch (root cause)
- server.ts had hardcoded renders dir, now reads BRADLY_RENDERS_DIR env
- renderQueue.ts saves to ~/Library/.../Bradly/renders/
- server.ts now serves from the same directory
Bug 2: Upload origin pointing to wrong port
- uploadBlobContent.ts used window.location.origin (Vite 5173)
- Remotion bundler needs Express origin (3000) to access media
- Added getExpressOrigin() helper that detects Electron
Bug 3: Batch ZIP export using file-saver (doesn't work in Electron)
- Added saveBlobFile IPC method (preload + main)
- batchExporter.ts now uses native save dialog in Electron
- Web mode falls back to file-saver