Commit Graph

207 Commits

Author SHA1 Message Date
Brandon Thomas 1f54f4a608 ROADMAP: measured parity scorecard (~62%) and Opus 5.5 hours estimate to parity
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 07:44:09 -04:00
Brandon Thomas 7db132d98c ROADMAP: menu long tail, transcripts, AV1 threading, CLI; 1095 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 00:05:24 -04:00
Brandon Thomas e222d025cf Merge transcripts (M10.5) and clip/project commands (M3.10); clip schema renumbered to v10
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:34:12 -04:00
Brandon Thomas f5ac5989f0 Merge branch 'worktree-agent-a7d751de0d72abab7' into worktree-agent-a6d2cbb6d6b3e5d7a
# Conflicts:
#	crates/edit/src/lib.rs
2026-10-01 23:31:39 -04:00
Brandon Thomas dc6e271442 Merge branch 'main' into worktree-agent-a6d2cbb6d6b3e5d7a
# Conflicts:
#	crates/ui-egui/src/panels/dialogs.rs
2026-10-01 23:31:26 -04:00
Brandon Thomas c3d2f740d0 M3.10: Edit/Clip/File menu commands — labels, Paste/Remove Attributes, subclips, frame holds, time interpolation, audio options, Replace With Clip
Edit: Label ▸ 16 colours + Select Label Group, Paste Attributes… (⌥⌘V, with
Scale Attribute Times), Remove Attributes…, Select All Matching, Remove
Unused, Consolidate Duplicates. File: New ▸ Sequence From Clip, Bin From
Selection (⇧B), Offline File…; Close Project (⇧⌘W, asks to save), Save All.
Clip: Make Subclip… (⌘U, Restrict Trims), Edit Subclip…, Modify ▸ Audio
Channels… (⇧G) / Timecode…, Video Options ▸ Frame Hold Options…, Add Frame
Hold (now splits at the playhead), Insert Frame Hold Segment, Field
Options…, Time Interpolation (Frame Sampling / Frame Blending / Optical
Flow, blending rendered on CPU; optical flow falls back to blending),
Fit to frame / Fill frame; Audio Options ▸ Breakout to Mono, Extract Audio
(WAV next to the project, imported); Replace With Clip ▸ From Source
Monitor / Match Frame / From Bin. Hold Filters: effects animate through a
hold unless set. Menus support nested submenus (egui and native) and follow
Premiere's order. Dialogs in panels::clip_dialogs with automation ids and
ui.set {clipDialog}.

Project schema v9 (no-op migration v8→v9, v8-subclip fixture): clip
time_interpolation / hold_filters / field_options / source_channels,
Interpretation.audio_channels, Subclip.restrict_trims.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:28:37 -04:00
Brandon Thomas fc18a6962e M10.5: Text-based editing / transcripts
- crates/speech (L2): Transcriber trait, FixedTranscriber, Whisper model catalogue (pinned,
  SHA-256 verified) with optional downloader (feature `download`: ureq + rustls + RustCrypto),
  pure-Rust Whisper inference on candle with word timestamps (feature `whisper`), log-mel, VAD
  word tightening, MFCC speaker clustering. Both features off by default and for wasm.
- project: per-media-item transcripts (Project::transcripts); schema v9 with a no-op v8->v9
  migration and a v8 fixture.
- edit::transcript: sequence transcript derived from clip transcripts, search, paragraphs,
  word ranges, pause/filler detection, ripple delete of many ranges, caption layout.
- engine: transcript.* commands (generate, set, delete, inspect, search, select, extract, lift,
  renameSpeaker, removeFillers, removePauses, createCaptions, models, downloadModel);
  Session::transcriber for hosts/tests; features `whisper` / `speech-download` (also on the
  desktop and CLI apps). Without whisper, transcript.generate fails with a clear error.
- ui: Text panel Transcript tab (Transcribe button, speaker paragraphs of clickable words,
  Shift+click selection -> In/Out, extract/lift/remove fillers/create captions, search) with
  text.transcript.* automation ids; headless UI test.
- docs/transcripts.md, crates/speech/README.md, architecture and project-files updates.
  whisper-tiny measures 12.2% WER over 797 words on local samples.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:25:49 -04:00
Brandon Thomas 858403ebf3 M3.9: Sequence and Markers menu long tail
Sequence: Reverse Match Frame (Shift+R), Go to Gap > Next/Previous in
Sequence (Shift+; / Cmd+Shift+;) and in Track, Selection Follows Playhead,
Show Through Edits (bow-tie marks on the timeline, wrench toggle), Join
Through Edits (clip context menu), Make Subsequence (Shift+U), Delete
Tracks... (dialog: all empty tracks or one track per kind).

Markers: Mark Split and Go to Split (Video/Audio In/Out) on the sequence
and the Source monitor; source split points make J/L-cuts on Insert and
Overwrite. Add Range Marker (Ctrl+Shift+M), Add Range Marker to In and Out
(Ctrl+M), Add Chapter Marker..., Clear Markers label, Show All Marker
Colors with a Markers panel colour filter, Ripple Sequence Markers
(insert, paste insert, extract, ripple delete, close gap, ripple trim) and
Copy Paste Includes Sequence Markers.

Edit crate: through-edit detection/join, track and sequence gaps, range
clipping. Shifted punctuation keys (Shift+; arrives as ':') now match
their bindings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:25:38 -04:00
Brandon Thomas 0ebc328fc4 Merge branch 'worktree-agent-aa900e64f5299bf69' 2026-10-01 23:23:59 -04:00
Brandon Thomas 9947fee359 M4.7: View menu and monitor view options: Paused Resolution, 1/16, High Quality Playback, Display Mode (alpha/RGB channels, comparison, multi-camera, source audio waveform, video+waveform split), Magnification with panning, rulers, guides (drag from rulers, lock, clear, Add Guide, templates in preferences), Snap in Program Monitor
MonitorView state is serde and settable with ui.set {program|source}; view.* UI commands with
menu checkmarks; wrench and zoom menus with automation ids; headless kittest tests (view_ui.rs).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:23:27 -04:00
Brandon Thomas 012bcf7aa5 M10.6: Graphics and Titles menu: New Layer (Vertical Text, Rectangle, Ellipse, Polygon, From file), Align to Video Frame / as Group / to Selection, Distribute (centres and gaps), Arrange, Select Next/Previous Graphic and Layer, Reset All Parameters, Reset Duration
Vertical text layout in the text engine (one line per character, columns right to left).
All edits are undoable engine commands; engine tests cover each menu group.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:23:27 -04:00
Brandon Thomas 83357490d4 Merge branch 'worktree-agent-a047c9696e3105eec' 2026-10-01 22:46:23 -04:00
Brandon Thomas 0e35e82e47 M9.7: AV1 tile, frame and post-filter threading
Tiles decode in parallel into private region buffers (Plane / MiInfo with a
frame-coordinate origin) that are merged afterwards; intra block copy frames
keep whole-frame buffers. Post-filter row bands run on a rayon pool (par.rs,
behind the `threads` feature, sequential on wasm32). Frames become jobs that
wait on the reference slots they read and run on frame worker threads, so
independent GOP layers decode concurrently; output stays in order and each
Picture carries the pts of its temporal unit (Decoder::decode_pts, flush,
flush_result). codecs::Av1Decoder passes pts through and drains on flush.

Oracle tests now compare 1 thread, many threads and libdav1d (bit-exact),
with new multi-tile fixtures and an ignored 1080p set. README records fps
before/after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 22:45:40 -04:00
Brandon Thomas 2d5267a7df M12.4: agent-friendly CLI: exec/describe/inspect/import/export, run from stdin with JSON lines and --keep-going, --save/--save-as, --bridge to the live app, exit codes; tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 21:26:44 -04:00
Brandon Thomas bf67521c4d Merge branch 'main' into worktree-agent-a047c9696e3105eec 2026-10-01 20:43:25 -04:00
Brandon Thomas ff07ed1dc8 Merge main into M13 (web app): community links and ArtCraft wordmark
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:54:09 -04:00
Brandon Thomas 3e834442ea ArtCraft brand marks: docs/brand logos with sidecars (ArtCraft trademark, all rights reserved, used with permission), AGENTS.md §1.8 first-party exception, wordmark in the About dialog and on the Home screen; README licence notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:52:40 -04:00
Brandon Thomas 5f613aff25 M13.2: FilmCraft web app (apps/filmcraft-web) with Blob media, OPFS recovery, WebAudio, WebCodecs
- eframe web runner on WebGPU (WebGL2 fallback; GPU compositor on WebGPU, CPU on WebGL2).
- fs: virtual file table of File/Blob handles, 1 MiB chunked async range reads with an
  LRU cache and read-ahead (pending + retry instead of blocking), downloads for written
  files, /opfs/ paths written to OPFS.
- import: File System Access picker / <input type=file>, drag-and-drop anywhere,
  container index prefetch (moov wherever it is), retried imports; project open/save.
- recovery: OPFS auto-save snapshot while dirty, media copies, reopened on next visit.
- audio: AudioWorklet output fed ahead from the UI thread; played-frame audio clock.
- webcodecs: H.264/HEVC/VP9/AV1 MP4/MOV decoded by the browser VideoDecoder via a
  reader opener (fallback to our decoders on any error), probed with isConfigSupported.
- api: window.filmcraft (execute/request/commands/screenshot/importFiles/importUrl/
  openProject/files/readFile/info).
- cargo xtask web [--dev] [--serve PORT] (wasm-bindgen CLI); xtask wasm also checks
  filmcraft-ui-egui and filmcraft-web; layer L6 for the web app.
- Original web icon (favicon.svg) with attribution sidecar; docs/web.md; headless-Chrome
  smoke test (tests/smoke.mjs).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:52:35 -04:00
Brandon Thomas 243e95ab24 M13.1: wasm groundwork: range readers, pending reads, cooperative frames, stepped export
- filmcraft-media: ByteReader/ReaderOpener (open containers without reading the whole
  file) and the pending flag for asynchronous (web Blob) reads.
- filmcraft-codecs: MP4/MOV and Matroska open from a ByteReader; registry of reader
  openers (platform sources first).
- filmcraft-engine: Services::reader / export_in_memory; streamed imports; media pool
  never caches a still-loading file as offline; Session::pump_jobs advances stepped
  exports on hosts without threads.
- filmcraft-export: Exporter (one batch per step, re-renders on pending reads) used by
  export(); OutputSink for in-memory output.
- filmcraft-ui-egui: FrameServer::pump (time-budgeted cooperative frame jobs on wasm,
  retries jobs whose media is loading); screenshots as base64 on wasm; web-time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:50:06 -04:00
Brandon Thomas 31f8b3dadf M9.7: AV1 hot loops: vectorisable MC, CDEF, transforms; faster deblocking and entropy decoding
Bit-exact restructuring of the per-sample spec processes (all oracle and conformance
vectors still match libdav1d):
- Inter prediction: unscaled references use one filter phase per block, so the 8-tap
  filters run tap-outer over whole rows (no per-tap clamps inside the frame, identity
  phases copy, zero-tap rows skipped); scratch buffers are reused, not allocated.
- CDEF: padded 12x12 block with availability; blocks whose taps are all available run
  branch-free in i16 lanes; zero-strength blocks are skipped.
- Inverse transforms: generic over lanes, 4 or 8 rows/columns at a time in 32-bit
  arithmetic (exact up to 10-bit per the spec's intermediate range); all-zero rows skipped;
  only the used dequant area is cleared.
- Deblocking: early exits before strength lookup; per-length sample filters; the wide
  filters as sliding-window sums.
- Symbol decoder: a 64-bit window of inverted bits instead of bit-at-a-time refills.
- Coefficient contexts from a zero-padded level buffer (no bounds checks); mode info
  stored with row fills; reconstruction on row slices.

Single-threaded 1080p (thread CPU): GOP 20.7 -> ~52 fps, high-quality GOP 9.6 -> ~20 fps,
4x2-tile GOP 22 -> ~48 fps, 10-bit GOP 17 -> ~44 fps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:48:22 -04:00
Brandon Thomas 9f687f7b44 Community links: header Discord button, Help menu (Discord, ArtCraft website, FilmCraft app page, GitHub, Report an Issue), Discord in the macOS app menu, About dialog with link buttons (centred, Escape closes), Community row on the Home screen, README links; help.* commands for agents; headless UI test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:25:46 -04:00
Brandon Thomas fef248a527 M9.7: AV1 decode statistics (per-stage busy time) and perf test with stage breakdown
Decoder::stats() reports frames, tiles and the busy time of setup, tile decoding,
deblocking, CDEF, superres, loop restoration and output. The ignored perf test
measures single-threaded throughput with the thread CPU clock (robust to machine
load), prints ms/frame per stage, and the all-cores wall-clock rate next to the
load average. Adds high-quality and 4x2-tile 1080p fixtures. Decoder::with_threads
and flush() are added as the API the threaded decoder will use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:07:55 -04:00
Brandon Thomas 89cfbf24f6 ROADMAP: masks/tracking/presets, multicam, DNxHR, AV1, focus fix, new hero; ~55% parity, 988 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 13:26:40 -04:00
Brandon Thomas dc9c5fd32c Merge branch 'main' into worktree-agent-a98dbfec8c9b949c7 2026-10-01 13:06:51 -04:00
Brandon Thomas 351b3387c9 fmt after merge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 12:51:35 -04:00
Brandon Thomas 645cfd9ad1 Merge branch 'main' into worktree-agent-a98dbfec8c9b949c7 2026-10-01 12:50:04 -04:00
Brandon Thomas 44f93d615c Merge branch 'main' into worktree-agent-ac059806d5abf3b44 2026-10-01 12:46:50 -04:00
Brandon Thomas f0c705493a M9.7: AV1 inter-GOP seek tests in MP4/WebM, decode perf bench, docs and roadmap
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 12:03:34 -04:00
Brandon Thomas a9278c81cc Merge M12 (multicam) into M5.5–7 (masks/presets): schema v7 = masks, v8 = multicam (WIP: CI not yet run)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:55:13 -04:00
Brandon Thomas 7095a986ff fix: control channel never steals keyboard focus — UI requests and screenshots bring the window forward without activating the app (orderFrontRegardless); --control launches without activation; only ui.focus activates
Agents' ui.* requests used ViewportCommand::Focus, so the user's typing in another app landed in FilmCraft as shortcuts (stray Extract, Mark In/Out, markers…). Verified live: the frontmost app stays frontmost through launch, ui.click, ui.key and ui.screenshot, and the requests still take effect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:53:19 -04:00
Brandon Thomas 05e6976854 M9.7: AV1 film grain synthesis; superres and film-grain oracle fixtures
Film grain (7.18.3) on output pictures, bit-exact against libdav1d on the libaom
23-film_grain-50 vectors (8/10-bit) and an SVT film-grain stream; super-resolution now
oracle-tested (SVT superres denominator 12) and bit-exact.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:52:26 -04:00
Brandon Thomas 753b673e6a M9.7: AV1 inter prediction, MV prediction, motion field, intra block copy, scalable output
Inter mode info syntax, spatial/temporal MV candidate stacks, motion field estimation and MV
storage, scaled references, sub-pixel filters, global/local warp, OBMC, wedge/diffwtd/inter-intra
masks, distance weights; intra block copy; one output frame per temporal unit with spatial
layers. Bit-exact against libdav1d on SVT-AV1 GOPs and the libaom size/quantizer/cdfupdate/mv/
mfmv/svc/monochrome/intrabc vectors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:47:36 -04:00
Brandon Thomas d9eaa0fe8f M5.7: effect presets — save (scale / anchor to in / anchor to out / without keyframes), apply (undoable; intrinsics replaced, geometry scaled to the target frame), built-in presets, user library in the data dir, JSON import/export; Presets bin in the Effects panel (drag onto clips), Save Preset dialog
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:44:55 -04:00
Brandon Thomas ad1ea19bde Merge branch 'main' into worktree-agent-a8d392646466fb2c4 2026-10-01 11:36:04 -04:00
Brandon Thomas 1db60f8edc M12.3: Multi-Camera view (angle grid at reduced resolution as one prefetched frame job, click / Ctrl-click to switch, live recording while playing with 1–9, Record toggle 0, Shift+0 view toggle), Create Multi-Camera / Synchronize / Merge Clips dialogs, [MCn] clip labels and angle thumbnails; headless UI tests with snapshots; grid perf test; ROADMAP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:36:00 -04:00
Brandon Thomas 68927178e2 M5.6: adjustment layers — Motion restricts the adjusted region; tests for below-only application, opacity/blend mix, effect and opacity masks (sequence pixels, any output scale) and nesting scope
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:21:02 -04:00
Brandon Thomas 35a2d2a861 M9.7: AV1 import from MP4 (av01/av1C) and Matroska/WebM (V_AV1)
Av1Decoder in filmcraft-codecs: feeds the av1C configuration OBUs before the
first sample (and after every reset), converts pictures to 8/16-bit planar
YUV with the stream's colour description, and reports random-access points
from the first frame header of each temporal unit (shown key frame) so GOP
seeking ignores bogus container sync flags. Matroska V_AV1 tracks map to an
av01 sample entry; MP4 labels show the AV1 profile.

All-intra 8-bit MP4 and 10-bit WebM files seek sample-exactly against
libdav1d. Inter frames still return "unsupported" until inter prediction
lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:18:49 -04:00
Brandon Thomas d90b9c8ee2 fix: document that the caption track margin is a fraction of the frame height
captions.setStyle {margin: 60} (pixels, as one would guess) was silently clamped to 0.45 and
put subtitles mid-frame. The parameter doc and docs/captions.md now give the unit and range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:18:06 -04:00
Brandon Thomas a2517bff08 README: new hero — Apollo 11 documentary edit (public domain)
Replaces the Night of the Living Dead trailer screenshot with a real job: a 3:10
documentary cut of NASA's Apollo 11 film (images.nasa.gov, US Government works) built
through the control channel — 49 picture cuts with dissolves, B-roll, lower-third titles
set by the text engine, subtitles from the NASA air-to-ground transcript, mission audio,
a CC0 Chopin bed ducked by Essential Sound, a Lumetri grade with keyframes, markers and a
rendered section. Sidecar lists every source and the reproduction steps; NASA does not
endorse this project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:17:08 -04:00
Brandon Thomas be1ce4943e M9.7: AV1 loop filter, CDEF, super-resolution upscaling, loop restoration
Loop filter (7.14: all filter sizes, deltas, segment/ref/mode adjustments),
CDEF (7.15), superres upscaling (7.16) and loop restoration (7.17: Wiener,
self-guided, switchable, stripe handling) in decode_frame_wrapup.

All-intra libsvtav1 fixtures with every in-loop filter (64/128 superblocks,
edge filter on/off, 8/10-bit) and libaom's av1-1-b8-02-allintra conformance
vector (39 frames, downloaded on first use) are bit-exact against libdav1d.
Frames coded slightly larger than the sequence maximum are accepted, like
other decoders do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:16:44 -04:00
Brandon Thomas b351559ffe M5.5: mask tracking (Shi-Tomasi features, pyramidal Lucas-Kanade with forward-backward check, RANSAC similarity/rigid/translation fit) as a background job writing Mask Path keyframes; track buttons + method menu in Effect Controls
masks.track {direction, frames?, method?, wait?}: progress + cancel via jobs.*, keyframes written live as one undo step per run. Synthetic known-motion tests: <0.75 px drift over 10 frames (render), 0.29 px max vertex error over -8..+12 frames end to end (engine).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:14:37 -04:00
Brandon Thomas 650a266352 M12.2: multicam and sync — Synchronize (In/Out/timecode ± hours/clip marker/audio), Merge Clips, Create Multi-Camera Source Sequence (camera names, audio camera 1/all/switch, Processed Clips bin), multi-camera clips (angle render, Switch Audio mix, GPU plan passthrough), switch angle / Ctrl+N cut / keys 1–9, live recording as one undo step, Enable/Flatten/Edit Cameras, audio follows video; nested sequence audio now plays; project schema v7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:08:45 -04:00
Brandon Thomas 908ce3e8d8 M12.1: audio synchronisation (GCC-PHAT-β coarse search on decimated audio, full-rate refinement): sample-accurate offsets between recordings with different gains, microphones and noise
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:08:38 -04:00
Brandon Thomas f0eb8cc9a0 fix: timeline waveforms of near-silent clips no longer drawn full scale
Waveforms are normalised to the source's peak so quiet recordings stay readable, but the
boost was unbounded: an empty audio stream at -52 dBFS (silent archive film) was drawn as
loud as dialogue. The normalisation is now capped at +12 dB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:05:30 -04:00
Brandon Thomas 1813bbaca2 M9.7: AV1 headers, symbol decoder, CDFs, intra decoding, transforms, intra prediction
New L0 crate filmcraft-av1 from the AV1 Bitstream & Decoding Process
Specification v1.0.0 with Errata 1 (tables extracted from the spec's Markdown
source by tools/extract_tables.py).

Stages: OBU parsing, sequence and uncompressed frame headers (all fields),
reference state (set_frame_refs, load_previous, reference update,
show_existing_frame), symbol decoder with CDF adaptation and
init/load/save/frame-end CDF handling, tiles, intra frame mode info
(partitions, segment ids, delta q/lf, CDEF index, modes, angle deltas, CfL,
palette, filter intra, tx size), coefficient decoding, dequantisation,
inverse transforms (DCT 4-64, ADST, identity, WHT), intra prediction (all
modes, edge filter/upsampling, recursive filter, CfL, palette), LR syntax.

All-intra libsvtav1 streams with in-loop filters disabled decode bit-exactly
against libdav1d (8/10-bit, 128x128..1280x720, odd sizes, presets 2-8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:00:03 -04:00
Brandon Thomas c14fc8e1b7 fix: timeline waveforms from the previous project after File > Open
Waveform peaks were cached by item id and never cleared, and item ids repeat across
projects: after opening a project the timeline drew the previous project's waveforms
(a 7-minute mission-audio clip showed as silent). The cache is now reset with the media
pool, and an item whose source is not available is no longer left pending forever.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 10:56:50 -04:00
Brandon Thomas 226c139741 M9.6: DNxHD/DNxHR (SMPTE ST 2019-1 VC-3) decoder and DNxHR encoder
New L0 crate filmcraft-dnx, written from SMPTE ST 2019-1:2016 + Amd 1:2023
(tables extracted from the standard's text by tools/extract_tables.py).

Decoder: every compression ID (DNxHD 1235-1260 incl. field-coded and
macroblock-adaptive interlace, thin rasters, RGB 4:4:4; DNxHR 1270-1274
LB/SQ/HQ/HQX/444), 8/10/12-bit, 4:2:0/4:2:2/4:4:4, DCT and lossless alpha,
macroblock rows in parallel. Matches ffmpeg within IDCT precision (max 2 LSB,
<=50 per million beyond 1, 87-99% identical) on 22 ffmpeg fixtures; follows
ffmpeg where it departs from the standard's text (reconstruction offset,
CID 1271 weights, 4:4:4 signalling) - documented in the README.

Encoder: DNxHR LB/SQ/HQ/HQX(10/12-bit)/444, CBR at the eq. 7.1 frame sizes,
uniform-qsf binary search + per-macroblock refinement; ffmpeg decodes every
profile with -xerror (HQ luma PSNR 58.8-66.3 dB).

Wiring: MOV AVdn/AVdh import (codec label from the CID), export
Format::DnxHr (MOV AVdh, dnxProfile lb|sq|hq|hqx) in the export dialog and
file.exportMedia.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 10:53:02 -04:00
Brandon Thomas fbaf487237 M5.5: effect masks (ellipse / 4-point polygon / pen Bezier) with keyframable path, feather, opacity, expansion, inverted, modes; opacity masks; WGSL coverage parity; on-monitor editing
- project:😷 MaskPath (cubic Bezier, clip pixels) as ParamValue::Path (vertex-wise keyframe interpolation), Mask, MaskMode, TrackMethod; schema v7 (no-op migration)
- render:😷 analytic antialiased coverage via signed distance + feather falloff in linear light; masked effect = lerp(original, effected, coverage); opacity masks before Motion; adjustment layers
- gpu::GpuMask: same coverage + mix in WGSL compute (max |cpu-gpu| ~3e-6)
- engine masks.* commands (add/remove/set/moveVertex/translate/addVertex/removeVertex/toggleVertexSmooth/select/list); keyframe commands take "mask"
- UI: Effect Controls mask rows; Program monitor overlay (vertices, handles, feather/expansion handles, body drag, pen tool) with automation ids
- goldens: mask_blur, mask_color, mask_inverted, mask_opacity

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 10:48:47 -04:00
Brandon Thomas 54e2ca0994 fix: Effect Controls shows LUT, text and curve params readably
Lumetri's Input LUT and Look LUT rows printed the Rust debug value (Text("")), and
curve params would print Curve([[0.0, 0.0], ...]). They now read None / the LUT's name,
the text itself, and Default / Custom (n points).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 10:14:55 -04:00
Brandon Thomas a426bdfb2d fix: Save As names the project after its file
After file.saveAs to 'Apollo 11 - Tranquility.fcproj' the title bar, Project panel and
recovery list still said 'Untitled'. Save As now renames the project (and its root bin)
to the file stem, without an undo step or dirtying the project; Save a Copy keeps the name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 10:05:53 -04:00