Version 3.6.0

Recorder, Captions Architecture & Take Health

A platform release with a redesigned recorder shell, consolidated captions architecture, take health checks, transcript editing, and a v2 storage layout.

A platform release. Two large engineering pushes — a ground-up redesign of the recorder shell and a five-phase consolidation of the captions architecture — landed alongside a new take-health system, a redesigned transcript editor, and a v2 storage layout.

Recorder

  • RecorderShell redesign — single phase-aware shell replaces the legacy workspace. Static recording surface, unified top bar across idle/recording/review/player phases, horizontal filmstrip of scenes and takes, contextual scene insertion via flanking ”+” buttons, and a global TakesDrawer toggled by e.
  • SceneTile + TakeThumbCard — compact text-focused scene navigation, inline active-state controls, webcam PiP on take thumbnails, aspect-preserving formats with automatic migration of legacy square thumbnails.
  • DeviceStrip + DevicePicker — hot-plug auto-detection via Swift AVCaptureDevice observers and Tauri events. Empty-array canonical state replaces the per-source enabled flag. Device watchdog auto-stops a recording when hardware disconnects.
  • Long-lived SCStream architecture — ScreenSession FFI keeps the screen-capture pipeline warm across takes. Priming window persists to maintain the XPC connection; forced re-prime on every take fixes the black-screen regression.
  • Broken-take detection — new Rust probe_take_health Tauri command (split across five submodules) uses the bundled ffmpeg sidecar to validate each take’s required streams. Broken takes render with a red ring + disabled star; selectTake refuses them; “Send to …” is gated when any scene has no usable take; the silence-bridge re-probes at handoff and surfaces BundleHasUnhealthyTakesError with a toast.
  • Audio feedback — procedural cues at 432 Hz for countdown, recording state changes, and transitions.
  • Recording project list — status, progress, size, and rename. Project lineage tracking persists recording → silence and silence → captions handoffs.
  • Per-scene export — export model emits per-scene folders, persists export directories for quick access, includes timestamps in folder names, opens in Finder with stale-path recovery, and surfaces a rich success summary.
  • Post-ready error recovery — non-terminal stream failures after recording-ready no longer discard the recording.

Captions Architecture Consolidation (Phases 0–5)

A targeted refactor that took the captions feature from 11 stores to 6, removed two parallel rendering paths, and replaced reactive playhead subscriptions with a single RAF-driven loop.

  • Phase 0 — Zod schemas as the source of truth for captions types, a fixture library with round-trip tests, and a /dev/gallery page for fixture-based visual review.
  • Phase 1 — Single render path. Removed the shadow renderer; all visible captions/overlay output now flows through <MainComposition> driven by Remotion’s <Player> (live editor) or render worker (export). <CaptionsPlayerOverlay> survives as a transparent interaction layer that ghost-renders content for correct drag/resize/rotate handle dimensions.
  • Phase 2 — Store consolidation. Merged style-store, export-store, timeline-display-store, and preview-guide-store into existing stores; split segments-store/index.ts (645 → 44 LoC) and overlays-store.ts (565 → 54 LoC) into focused slices. Extracted a shared buildSegmentEntityMap helper.
  • Phase 3 — Imperative playhead. New PlayheadStore + PlayheadProvider + useFrameValue<T>(selector) hook backed by a single shared RAF loop. Components now only re-render when the selected value actually changes, not on every clock tick. Migrated CropMode, CaptionsPlayerOverlay, TimeDisplay, CutButton, and useOverlayActions off useTimelineStore((s) => s.currentTime).
  • Phase 4a — Retired MediaPool from the captions feature.
  • Phase 5 — Docs. CLAUDE.md §6 (shadow renderer) and §9 (store map) rewritten; new performance rule 18 in docs/perf/REACT_PERF_RULES.md for useFrameValue.
  • Segments as source of truth — per-phrase data migrated from overlays into caption segments; translation feature removed; new transcript editor components replace the old transcription panel.

Transcript Editor

  • Transcript drawer — side-panel editor with toolbar, search/find-and-replace, filter chips, persistent review cursor (R / Shift+R / Cmd+Enter), atomic per-segment review marking, phrase grouping, confidence heatmap with smooth auto-mark fade, and phrase-level context menus.
  • Centralized shortcut catalog at src/features/captions/shortcuts.ts; project- wide migration to the isEditableTarget guard.
  • Search-and-replace — whole-word toggle fixes a data-loss bug; navigation + replace UI with batch select-all.
  • Phrase inspector — per-phrase rotation and maxFontSize overrides, individual segment editing, select-all phrases for batch editing.
  • Heatmap canonical for the reviewed signal, JSON preview tab, deduped download UI; orphan-aware cursor advance.

Editor & Inspector

  • Tabbed cockpit (Content / Style / Transform / Animation) with selection-summary header and bulk Tighten/Delete/Clear actions. “Mixed” indicators across all multi-edit fields. Cockpit thumbnail anchor in the inspector header.
  • Crop overhaul — improved aspect-ratio presets, keyboard shortcuts, crop inspector section, transcript controls relocated to a new drawer toolbar.
  • Animation presets system — UI controls with detection logic; collapsible AnimationPicker panels replaced with persistent PhaseCard components.
  • Whisper engine presets with advanced settings + customization tracking.
  • Multi-selection — Shift+click range, Cmd+click toggle, Cmd+A select all; multi-overlay transcription cockpit; primary anchoring on shift+click.
  • Per-phrase rotation in editor and renderer; capitalize support in text formatting; broader sidebar resize range.
  • Drag-and-drop video import to the Captions dashboard via a pre-filled CaptionsCreationDialog.
  • Crop and text styling — shadow and stroke separated into independent rendering layers (font-relative em fractions for cross-platform consistency); padding and background sizing unified onto em-fractions of font height.
  • FCP-style filmstrip thumbnails on timeline video clips.
  • Bridge templates (Minimal + Screen Studio) for send-to-captions.

Silence Remover

  • Dual-sidebar layout with specialized clips and settings panels. Drag-to-reorder clips, batch deletion, custom shortcuts, segment navigation, adjustable waveform.
  • Per-clip overrides + denoise modes; manual-edit ledger survives slider/preset changes.
  • Orientation-aware player canvas; auto-rewind on playback completion.
  • Atomic multi-file project creation; live import + denoise progress; cancellation.

Storage & Persistence

  • v2 layout — internal state in app_data_root; Exports/ split into {Recordings,SilenceRemoval,Captions}/ subfolders; all three stages auto-save with reveal-in-Finder toast. Centralized naming utilities at crate::storage::naming; paths via crate::storage::paths. Project-type isolation; simplified path resolution.
  • Captions persistence actor with a generation-counter invariant — wired into the save/load lifecycle; prevents reset-time data corruption; surfaces load errors in the warm-up overlay with retry.
  • Project-level legacy fields removed (duration, width, height); dynamic clip-based calculation. Incremental project-metadata backfill for previewVideoPath and missing counts.
  • Debounced auto-save with flush on window close.

Theme

  • Theme provider with curated OKLCH presets, runtime swap via CSS custom props, 220 ms cross-fade, zero-flash boot.
  • Project-wide migration to shadcn theme tokens — replaced raw Tailwind colour scales (bg-zinc-950, text-white/85, border-white/10, …) with theme tokens (bg-background, text-foreground, border-border, …). CLAUDE.md §4c documents the mapping.

Performance

  • Proxy encoder low-latency — -g 6 -keyint_min 6 -tune zerolatency (keyframe every 0.2 s); TARGET_PREMOUNT_S 1.5 → 0.5 — minimizes clip-boundary lag and audio-context strain.
  • Captions overlay audio via pooled <Audio> tags with numberOfSharedAudioTags={6} — fixes the clip-3 audio death caused by WebKit’s per-element user-activation model.
  • MediaPool optimizations — park-once logic for inactive slots; preserve src on recycle so same-clip handoffs stay warm.
  • TranscriptionPanel re-renders eliminated via useFrameValue migration.
  • Increased video playhead drift tolerance to prevent decoder freezing.

Bug Fixes

  • Compositional duration off-by-one fixed alongside the always-visible PhraseLengthInlineSlider.
  • Manual text overlays no longer auto-assign to caption-bearing tracks.
  • Filmstrip layout shift during scene transitions scoped via animations; take row height pinned.
  • Word-merge synchronization bug — mergeWords now calls syncToOverlay before reGroupSegments to prevent stale per-overlay rawWords from overwriting the primary track. Merge shortcut remapped to mod+shift+m.
  • Caption regeneration wipes all prior text overlays for the source clip (pass-specific cleanup treats undefined as ‘original’).
  • New tracks insert at top of section, not bottom.
  • Race-condition media playback — ensurePaused utility chains pause commands to pending play promises.
  • Multi-import in silence remover — black clip 3 + height fluctuation fixes.
  • Self-healing router for stale lastPage redirects.
  • Bridge FFmpeg failures now surface stderr in silence → captions errors.
  • Infinite reset loop introduced by Phase 2 style merge resolved.

Refactoring

  • SettingsTab.tsx 509 → 309 LoC (main); useFontLoader.ts 434 → 83 LoC (orchestration); TimelineItem.tsx split into focused hooks.
  • Tracks persist as full objects instead of IDs; sacred-track logic replaced with manual naming support.
  • Timeline clip colours migrated from static hex to CSS variables with a legacy migration; removed style-card badges; pruned text-style presets.
  • Caption templates consolidated into a single default layout.
Local Mac workflow

Keep the edit on your Mac.

Choose a license to record, clean, caption, and export without moving private footage into a browser editor.