Commit Graph
466 Commits
Author SHA1 Message Date
lloydandClaude Opus 5.5 ff8728af08 Anamorphic media: pixel aspect ratio in placement, monitors and New Sequence From Clip
A 1440x1080 clip with 4:3 pixels showed squeezed: the demuxers read its
pixel aspect ratio, but nothing after import used it. New Sequence From
Clip made a 1440x1080 sequence with square pixels, the Motion transform
sized clips from storage pixels (pillarboxed at 1440 wide in a 1920x1080
sequence), and the monitors drew the frame at its storage aspect.

- project: checked_par / sane_par / par_ratio / conformed_size treat
  file and project ratios as hostile (a zero term, or more than 8:1
  either way, is square). MediaClip::pixel_aspect (Interpret Footage
  wins over the file), Project::source_par (subclips follow the parent,
  nested sequences have their own, graphics and adjustment layers have
  none) and Project::conformed_source_size.
- render: motion_matrix takes the source's ratio and works in square
  display units (anchor in source pixels, position in sequence pixels,
  scale and rotation at the display aspect); Scale to Frame Size fits
  the display size. CPU, GPU plan, adjustment regions and the mask /
  graphics overlays share it.
- engine: New Sequence From Clip, New Sequence from an item and
  multicam sequences copy the clip's ratio; default media scaling and
  Fit / Fill frame use the display size; generators made for a
  non-square sequence get its pixels; transcodes render pixel for
  pixel. clip.interpretFootage takes pixelAspect ([num, den] or "file").
- ui: the Source and Program monitors draw the picture at its display
  aspect; overlays map both axes; Sequence Settings shows the display
  aspect (16:9 for 1440x1080 at 4:3).

Tests: render par_tests (fill, GPU plan parity, Scale to Frame Size,
non-square sequences, rotation, Interpret Footage, hostile ratios),
engine par_tests (New Sequence From Clip, overwrite into 1920x1080,
default scaling, Fit / Fill, Interpret Footage with undo and refused
values, hostile file ratios, generators, and ffmpeg-made MP4 and MKV
files), project unit tests, and the headless par_ui monitor test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:28:56 +02:00
Brandon ThomasandClaude Opus 5.5 12f2ea17d6 CJK fonts: Chinese faces after the Japanese ones, so Japanese keeps Japanese glyph forms
The two share code points; putting the Chinese faces first drew Japanese UI text's kanji
with Chinese shapes. Also clears the test's texture deltas (epaint 0.36 panics on
dropping them unapplied).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:02:38 -04:00
Brandon Thomas e9c09d243a Merge remote-tracking branch 'origin/main' into fix-363 2026-10-09 10:56:40 -04:00
Brandon Thomas b32d1cd5ed Merge remote-tracking branch 'origin/main' into fix-361 2026-10-09 10:17:58 -04:00
Brandon Thomas 81eb842e2e Merge remote-tracking branch 'origin/main' into fix-353 2026-10-09 10:13:59 -04:00
Brandon Thomas 38f4255735 Merge remote-tracking branch 'origin/main' into fix-386 2026-10-09 10:13:01 -04:00
Brandon ThomasandClaude Opus 5.5 f267a941fb Merge origin/main into feat/nvenc-export
main gained NVENC H.265 Main / Main 10 (#328, #360), export stage timings
(#370) and VA-API decoding (#358). Resolution: main's NVENC session, FFI and
export factory, with this PR's changes ported onto them:
- ffi: the portable Guid (now also for the HEVC GUIDs), NV_ENC_DEVICE_TYPE_CUDA;
- session: device.rs (Direct3D 11 / retained CUDA primary context), the
  Linux libnvidia-encode.so.1 loader, Device::KIND;
- export: factory_with and its tests, the even-size check, the saturating
  max bitrate; H.265 through NVENC stays Windows-only (the factory declines
  it on Linux, where nothing probed or tested it);
- Cargo.toml: main's Linux libloading dependency covers both users;
- docs: README / ROADMAP / architecture now say NVENC H.264 runs on Windows
  and Linux; ADR and platform README keep both addenda / test rows;
- abi_tests: note why the MSVC-generated expectations hold on LP64 Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:12:46 -04:00
Brandon Thomas 5f4e2d7c99 Merge remote-tracking branch 'origin/main' into fix-353
# Conflicts:
#	crates/engine/src/keyboard.rs
#	crates/engine/src/lib.rs
#	crates/ui-egui/src/panels/monitor.rs
2026-10-09 10:11:15 -04:00
Brandon Thomas 560355f3d2 Merge remote-tracking branch 'origin/main' into fix-338 2026-10-09 10:09:57 -04:00
Brandon ThomasandClaude Opus 5.5 285e81b5da Merge origin/main into m8/export-stage-timings
NVENC export: keep main's Main 10 / Main dispatch and time both colour
conversions (rgbf_to_yuv420_10, rgba_to_yuv420_8) as Stage::Convert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:08:35 -04:00
Brandon ThomasandClaude Opus 5.5 701d7c7111 Merge origin/main into multi-stream audio
Keeps #359's contiguous_starts audio timing, now per stream in Mp4Audio /
MkvAudio (starts and preroll in source sample frames). MP4 audio streams and
their decoders are built from the same (track, info) pairs so they stay
index-aligned. Adapts new main code to audio_streams / TrackItem::audio_stream.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:08:09 -04:00
Brandon Thomas e196de8f64 Merge remote-tracking branch 'origin/main' into fix-338
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/commands.rs
#	crates/engine/src/lib.rs
#	crates/ui-egui/README.md
#	crates/ui-egui/src/panels/monitor.rs
2026-10-09 10:06:01 -04:00
Brandon Thomas 95230b9072 Merge pull request #360 from SaymonMaster14/m3/nvenc-hevc-main10
Windows: NVENC H.265 Main 10 HDR (PQ / HLG) export
2026-10-09 10:05:10 -04:00
Brandon ThomasandClaude Opus 5.5 c9e2bfcac0 Merge origin/main into m3/nvenc-hevc-main10
Export panel: the HEVC profile labels go through tl! with Spanish entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:04:58 -04:00
Brandon ThomasandClaude Opus 5.5 a66be150e3 WINCI: ignore the mixer throughput benchmark only where it times wall clock
On Unix the benchmark measures the test thread's CPU time, so suite load
does not move it and it keeps running. Without a per-thread CPU clock
(Windows) it falls back to wall time, which is load-dependent and flaky on
shared CI runners; ignore it only there and document how to run it.
The GPU effect-source hunks were dropped in the merge in favour of #376's
fs_fx_source, now on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:59:45 -04:00
Brandon Thomas efa89a7d2d Merge remote-tracking branch 'origin/main' into fix-337
# Conflicts:
#	crates/gpu/src/fx_tests.rs
2026-10-09 09:59:26 -04:00
Brandon Thomas 0d2c21163c Merge pull request #299 from dcarnelutti/export/trim-pool-when-done
export: free the frame pool when an export ends
2026-10-09 09:56:07 -04:00
Brandon ThomasandClaude Opus 5.5 79a3b623fe Pool trim: free only the float shelf, and only after a standalone export
pool::trim() from Pipeline::drop flushed the whole process-wide pool after every
render-preview segment and proxy, and threw away playback's U8/U16 planes too.
Now Pipeline::drop calls pool::trim_f32() only when !settings.part_of_batch.
PoolStats gains f32_idle_bytes so the tests can check the float shelf alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:55:47 -04:00
Brandon Thomas 6ebc21f093 Merge remote-tracking branch 'origin/main' into fix-360
# Conflicts:
#	README.md
#	ROADMAP.md
#	crates/platform/README.md
2026-10-09 09:46:48 -04:00
Brandon Thomas 97a8eaffec Merge remote-tracking branch 'origin/main' into fix-299
# Conflicts:
#	docs/control-protocol.md
2026-10-09 09:45:27 -04:00
txiki739andClaude Opus 5.5 17921200d7 #346: the from-source Flatpak includes the CLI and MCP server
The release bundle manifest installs filmcraft and filmcraft-cli; the
from-source manifest built and installed only the desktop app, so a
Flatpak built from source had no headless CLI or stdio MCP server.

It now builds -p filmcraft -p filmcraft-cli and installs
/app/bin/filmcraft-cli. The default command stays filmcraft; the CLI
runs with `flatpak run --command=filmcraft-cli ai.storyteller.filmcraft`
(the manifest header and docs/releasing.md show it). Runtime, SDK and
finish-args are unchanged.

packaging-lint now also checks that both manifests install the same
programs, {filmcraft, filmcraft-cli}; it fails on the old manifest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 15:37:09 +02:00
Brandon Thomas 570d06d5bd Merge remote-tracking branch 'origin/main' into fix-328
# Conflicts:
#	Cargo.lock
#	README.md
#	ROADMAP.md
#	crates/platform/Cargo.toml
#	crates/platform/README.md
#	docs/architecture.md
2026-10-09 09:34:12 -04:00
Manuel CamachoandClaude Opus 5.5 7b73c8e887 GPU3d: GPU export rendering is Auto by default (#30)
Merlin's effects-heavy bench scene (GPU3c) settles it: with layers and
effects the GPU compositor exports 2.4x faster at 1080p (13.0 -> 5.0-5.6 s,
737 -> 238 CPU ms/frame) and 3.2x at 4K (38.7-39.3 -> 12.0 s, 2955 -> 775
CPU ms/frame); a single plain clip takes the same time either way
(decoding / encoding bound). Every Auto row rendered all its frames on the
GPU, without fallbacks. The CPU reference renderer stays the fallback for
anything the GPU stage does not run.

Trade-off: the GPU matches the CPU within the compositor's parity
tolerance, not bit for bit, so an export's bytes can depend on the
machine's GPU; Off keeps them byte-reproducible (the determinism tests
register no GPU renderer and are unaffected).

- settings: GpuRendering::Auto is the #[default]; ExportSettings::default.
- test: the default, settings saved without the field, and "off".
- docs/performance.md: GPU3 results (1080p and 4K).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 06:31:57 -07:00
Brandon Thomas a739ffea84 Merge remote-tracking branch 'origin/main' into fix-256
# Conflicts:
#	crates/ui-egui/tests/keyboard_ui.rs
#	docs/control-protocol.md
2026-10-09 09:29:27 -04:00
Brandon Thomas bf0f2bd8ff Merge pull request #305 from Pathos0925/fix/296-mono-loudness
#296: Auto-Match measures a mono clip as one channel
2026-10-09 09:24:45 -04:00
Brandon Thomas 5d69487925 Merge pull request #307 from justjohn12345/pr/bugfix
Keyframes: Properties gets Premiere's navigator, Effect Controls a time ruler
2026-10-09 09:23:44 -04:00
Brandon Thomas 354bb86332 Merge pull request #304 from justjohn12345/pr/monitor-follows-drags
Program monitor: the picture follows a value that is dragged
2026-10-09 09:23:37 -04:00
Brandon Thomas 929e05d996 Merge pull request #303 from MarekSpodBiedry/issue-139
Issue #139: portable.txt next to the exe keeps the data directory beside it
2026-10-09 09:23:25 -04:00
Brandon Thomas e919d3f80b Merge pull request #249 from switch87/desktop-log-file
Desktop: write log records to standard error and a rotating log file
2026-10-09 09:23:08 -04:00
Brandon Thomas d16f9adb0a Merge pull request #387 from txiki739/fix/linux-tar-installer
#214: install script for the Linux tarball
2026-10-09 09:23:02 -04:00
Brandon Thomas bfa819a448 Merge pull request #358 from JordyUSA/vaapi-h264-decode
HW5: Linux VA-API hardware decoding for H.264 and HEVC (Main / Main 10)
2026-10-09 09:22:56 -04:00
Brandon Thomas 3e6043c46a Merge pull request #263 from XusBadia/dmg-background
macOS DMG: branded window background and icon layout
2026-10-09 09:20:31 -04:00
Manuel Camacho ab334b2adf GPU5: Video Limiter on the GPU compositor (#30)
Move Video Limiter from CPU (crates/render/src/vfx/color.rs) to the GPU
compositor (filmcraft_render::gpufx::FxOp, crates/gpu/src/fx.rs, crates/gpu/src/fx.wgsl).
Parity matches CPU reference within 9.28e-6 across all axis modes, clip levels,
compressions, and gamut warning color.

🤖 Written by agy (Antigravity Agent, Gemini 3.8 Flash)
2026-10-09 06:18:17 -07:00
Manuel Camacho d2b608605e GPU4: Vignette on the GPU compositor (#30)
Add Vignette effect to the GPU effect stage (render::gpufx, gpu::fx,
fx.wgsl). Evaluated parameters are shared between the CPU reference and
GPU compute passes. Replaces old CPU vignette body in vfx::color with
gpufx::FxOp::eval and gpufx::FxOp::apply.

Gates: fmt, clippy, test -p filmcraft-render, test -p filmcraft-gpu,
layers, wasm all verified.

🤖 Written by agy (Antigravity Agent, Gemini 3.8 Flash)
2026-10-09 06:18:17 -07:00
Brandon Thomas 9c24778039 Merge pull request #399 from ItzBloxy/fix/259-trim-hit-testing
#259: the edge you press is the edge you trim
2026-10-09 08:17:17 -04:00
BloxyandClaude Opus 5.5 4eb34ae6c7 #259: the edge you press is the edge you trim
Pressing a clip edge and dragging inward selected and moved the clip: the press was hit-tested
only once egui recognised a drag, 6 pt later, by when the pointer had left the 7 px edge zone.
And at a cut the left clip's Out edge claimed both sides, so the right clip's In edge could not
be grabbed.

What a press grabs is now worked out on the frame the button goes down (timeline_hit::grab_at,
shared by the cursor, the press and ui.timeline.hit) and acted on by both the click and the
drag. Inside a clip beats outside it, so the side of a cut picks the clip; zero-width clips
have no edges. Trims, rolls, rate stretches and remixes move by how far the pointer moved since
the press, and a moved clip stays under the point it was grabbed by. ui.timeline.hit takes
`modifiers` and reports `kind`, the trim a press would start.

Unit tests for the zones and tools; headless UI tests that drag a pixel or a few per frame at
60 fps (before: the clip moved, the wrong clip was trimmed, a wobbly click selected the clip, a
moved clip lagged).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:27:48 +02:00
txiki739andClaude Opus 5.5 ae09ba904c #214: install script for the Linux tarball
The tarball now ships install.sh. It installs filmcraft, filmcraft-cli,
the desktop entry, icons, MIME type, metainfo and docs under ~/.local
without sudo; --prefix takes any absolute path (sudo ./install.sh
--prefix /usr/local for all users). Running it again updates.

The desktop entry's Exec/TryExec point at the installed binary's
absolute path, escaped per the Desktop Entry spec, so the menu entry
works without ~/.local/bin on PATH. The script checks the bundle is
complete before writing, refuses /, prefixes inside the extracted
bundle and characters launchers cannot express (=, %, control
characters), and treats the cache refresh tools as optional.

packaging/linux/test_install.py covers install and update, launching
through gio, bad arguments, an incomplete bundle, --help and a real
package.sh tarball build; Packaging lint runs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:54:20 +02:00
Xus BadiaandClaude Opus 5.5 10b71eec85 macOS DMG: branded window background and icon layout
The DMG opened as a plain Finder window. It now shows the app icon's figure on
the FilmCraft colour, with FilmCraft.app and the Applications link side by side.
Same approach as PhotoCraft's and VectorCraft's (storytold/photocraft#1201,
storytold/vectorcraft#493).

- packaging/macos/dmg/: background.svg (source; text outlined, no paper grain,
  the figure an <image> of assets/app-icon), background.tiff (1x + 2x HiDPI,
  16-colour palette, Deflate, sRGB; ~106 KB)
  and dmg-layout.DS_Store (Finder view settings: window, icon size 128,
  positions, background).
- generate.py writes the TIFF and the layout on any OS, byte-for-byte
  reproducible, with nothing from the machine that ran it (no paths, users,
  disk names or volume UUIDs).
- package.sh copies them into the staging folder; the image is still built with
  hdiutil makehybrid. Nothing extra runs in the signing job.
- The volume name drops the version: the layout finds the background through
  an alias that includes the volume name. The DMG file name keeps the version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:43:43 +02:00
Davi AndreiandClaude Sonnet 5.5 9510e26584 Export: render the next batch while the current one is encoded
A step now renders batch k+1 on the rayon pool while the calling thread
encodes, muxes and mixes the audio of batch k. The file is byte-identical
with or without overlap. A prefetch that hits pending media is dropped and
rendered again, cancel frees it, a render panic becomes an error, and wasm
never overlaps. perf.stats export.stages gains waitMs.

Memory: up to 2 x batch x frame bytes of finished frames are in flight, so
the batch is capped to a 512 MiB budget (1080p keeps 16, 4K SDR 8, 4K HDR 2
frames). Measured peak RSS vs before: 1080p +67..+158 MB; 4K SDR -535..-927
MB; 4K HDR about -2.6 GB (5.2 -> 2.6 GB). Wall time 1.06-1.16x faster.

Known pre-existing web issue, untouched: AudioOut::pull advances before the
pending check, so a retried audio group is lost.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:26:41 -03:00
storybored379andOpenAI Codex ea79751a5c platform: enable existing NVENC H.264 export on Linux
Runtime-load the NVIDIA encode and CUDA driver libraries, retaining the primary context through session destruction. Preserve the Windows Direct3D path and default-off selection, and test driver rejection and deterministic software fallback.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
2026-10-08 20:40:01 -07:00
Cathy Shapiro ac145dbaa8 M3.12: Dismiss Export Frame when clicking outside
Cancel the export draft when clicking outside the dialog, including top menus and mode tabs, while allowing the background control to receive the click. Keep the dialog's own format and depth dropdowns interactive.

Cover dismissal for both monitors, mode switching, dropdown selection, and background monitor clicks in a UI regression. No frame is exported when clicking away.

Assisted-by: Codex
2026-10-08 21:57:30 -05:00
Davi AndreiandClaude Sonnet 5.5 dbae11b843 Windows: NVENC H.265 Main 10 HDR (PQ / HLG) export
HDR sequences export as real 10-bit HEVC Main 10 through NVENC where the GPU
reports 10-bit HEVC: float BT.2020 R'G'B' -> rgbf_to_yuv420_10 -> P010 input;
VUI BT.2020 + PQ/HLG; HDR10 mastering-display / content-light as SEI on every
IDR (PQ); colr/mdcv/clli in the sample entry. New register_hdr_probe /
hdr_available in the export crate; macOS and GPUs without 10-bit keep
tone-mapping HDR sequences to 8-bit SDR HEVC. ABI asserts extended and
re-verified against nvEncodeAPI.h 12.1 (0 drift). 8-bit SDR HEVC unchanged;
the two #328 tests that asserted HDR is declined now expect Main 10.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:38:14 -03:00
Idiotic f146d7ba9f feat(media,engine): implement multi-stream container audio support and schema v13
- Update MediaInfo to store all discovered audio streams in audio_streams

- Retain independent stream metadata and decoder state for MP4/MOV and Matroska/WebM

- Update audio_placement_specs to allocate successive tracks via ensure_audio_tracks

- Isolate clip rendering to read assigned audio stream rather than replaying stream 0

- Bump project schema to v13 with backwards compatibility for legacy v12 projects

Resolves #312

Fixes #200

Fixes #315
2026-10-08 22:36:45 -04:00
jnohclee-rgb 0bfea22e1b cli: make --help print usage successfully
Fixes #344. Handle the leading help flag before command parsing and decoder registration; cover output and exit status with a native CLI regression.
2026-10-09 10:14:06 +08:00
Cathy Shapiro 6c0e3ecc39 M3.12: Match Export Frame timecode to its monitor
Display the captured frame with the same frame rate and drop-frame timecode format as Source or Program, instead of decimal seconds. Keep the captured timecode fixed while the export dialog is open.

Add a UI regression comparing both monitor labels at standard and NTSC rates, with Program drop-frame formatting and playhead movement after capture.

Assisted-by: Codex
2026-10-08 21:11:44 -05:00
JordyUSAandClaude Opus 5.5 e741267125 HW5: Linux VA-API HEVC hardware decoding, Main and Main 10 (#30)
HEVC through VA-API the same way as H.264: the software HEVC decoder's
parsers and DPB (now generic over the picture type in filmcraft-hevc:
POC, reference picture sets, reference lists, output order, RASL
handling) drive the stateless hardware. Main, Main 10 and Main Still
Picture, 4:2:0 8/10-bit (P010 read-back); scaling lists, tiles, WPP,
dependent slices, weighted prediction. Missing references and range
extensions go to the software decoder.

Tests: hardware parity on HEVC Main / Main 10 incl. open GOP, scaling
lists, slices+WPP, weighted prediction, tskip+AMP, 1080p/2160p (streamed
comparison to stay within memory); HEVC front end against a recording
stand-in on every OS; ABI checks extended to va_dec_hevc.h. Benchmark on
Iris Xe: 4K HEVC 203 -> 10 ms CPU per frame, 4K Main 10 212 -> 18 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:00:30 +07:00
jerrykimo 34cf6005d0 ui: Render Chinese document names with font fallbacks 2026-10-08 20:50:09 -05:00
Cathy Shapiro 9f0ed51b49 M3.12: Export frames from Source and Program monitors
Wire both camera buttons to captured-monitor frame export with original media at full resolution. Add a movable settings dialog with format/depth selection, a visible destination folder, Browse, overwrite confirmation, and optional project import.

Reuse existing 8-bit still encoding; add JPEG and direct float-to-16-bit PNG/TIFF encoding. Cover monitor routing, captured frame time, proxy bypass, hostile parameters, depth, import, cancellation, overwrite, and fractional header movement with synthetic regressions.

Assisted-by: Codex
2026-10-08 20:46:12 -05:00
JordyUSAandClaude Opus 5.5 3496e553e7 HW5: Linux VA-API H.264 hardware decoding (#30)
Stateless VA-API decoding with FilmCraft's own H.264 host side: the
software decoder's SPS/PPS/slice-header parsers and its DPB (now generic
over the picture type in filmcraft-h264) drive the GPU, so reference
marking, reference lists and output order are shared and the pictures are
bit-exact with the software decoder. libva is loaded at run time; no libva
or driver means software decoding as before. frame_num gaps (open-GOP
seeks) get the software decoder's stand-in frames. HybridDecoder keeps the
transparent software fallback.

Tests: hardware parity on 7 H.264 streams incl. 1080p/2160p, seeks,
flushes, forced failures, fuzzing, concurrency; front end against a
recording stand-in on every OS; ABI checks against va.h. Docs: platform
README, ADR 0001 addendum, architecture, performance (H.264 2160p CPU per
frame 417 -> 11 ms on Iris Xe), roadmap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:35:57 +07:00
Cathy Shapiro 8a7275c821 M3.12: Source playback and monitor range editing
Play source video and audio, drag marked ranges as video, audio, or a linked pair, and route Source commands to clip marks and markers. Add shared draggable In/Out handles and range movement, preserving scrubber priority and explicit-only Program marks.

Include original code-drawn controls, documentation, attribution, and regression coverage for playback, placement, routing, undo, cancellation, and hostile parameters.

Assisted-by: Codex
2026-10-08 18:58:46 -05:00