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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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
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>
- 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#312Fixes#200Fixes#315
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
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>
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
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>
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
Normalize explicit relink prefixes, compare native paths in portable tests, close fixture sessions before directory moves, and preserve exact GPU effect-source pixel centres. Keep the hardware-dependent mixer benchmark opt-in with its 4x target unchanged.
Shortcut portability changes reused from storytold/filmcraft#37 (bd944ee and f2b36fe). The existing export fix from #282 remains in its original parent commit.
Assisted-by: Codex
`filmcraft-cli commands | head -c 10` panicked with "failed printing to stdout: Broken pipe
(os error 32)". Output now goes through `outln!` / `out!`. When stdout fails, later output is
dropped but the program does not stop: the rest of `exec`, `run` and `import` (later script
lines, `--save`, `--save-as`) still runs and the exit status still reports a failing command.
Exiting at the first failed print would report success while skipping the save, e.g.
`filmcraft-cli run edits.jsonl --project p.fcproj --save | head -1`. A closed pipe is not an
error; any other stdout write error is reported and makes the exit status 1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- register() asks the HEVC probe on a thread of its own (the first probe is
about half a second: D3D11 device + NVENC session), so the first draw of
Export's format list does not wait for it; tests/nvenc_hevc_warm.rs.
- A machine with no HEVC encoder is not a declined hardware attempt: the
factory returns None without counting `declined`.
- HEVC tests skip only when the probe says there is no HEVC encoder; on a
machine that has one, a configuration NVENC refuses fails the test.
- Wording: NVENC is FilmCraft's only HEVC encoder on Windows (Windows itself
ships others).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One NVENC session, ring and NV12 path now serve H.264 and HEVC (Codec enum,
Profile::HevcMain). HEVC Main 8-bit 4:2:0 SDR BT.709, MP4/MOV hvc1, parameter
sets only in an hvcC built from the SPS the encoder wrote. The H.265 format is
available through a cached NVENC probe; choosing it is the opt-in, declines are
counted errors. ABI asserts regenerated from nvEncodeAPI.h 12.1 (no drift) and
extended for HEVC; tests, docs and roadmap updated.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Loudness Auto-Match metered every clip as the stereo pair clip_signal
plays, so a mono source (or a mono pick from Modify > Audio Channels /
Breakout to Mono), copied onto both sides, read 3.01 LU louder than the
file and got 3 dB too little gain. BS.1770 and ffmpeg's ebur128 measure
a mono programme as one channel; now so does clip_loudness, through a new
render::audio::clip_is_mono. Stereo and wider sources are unchanged, as
are the export loudness pass and the Meters panel (they measure the real
output mix).
Regression test: the same speech as a 1-channel WAV and as dual-mono
stereo measure 3.01 LU apart, the mono clip agrees with a one-channel
meter over the file within 0.1 LU, and a mono pick counts as mono.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>