Commit Graph

402 Commits

Author SHA1 Message Date
vangel76 a8de199aca #783: Object Matte fidelity plan; gaps and parity notes updated
Problem: Object Matte had no After Effects comparison, and none can be made
on this Linux machine (no After Effects). The gap notes still listed the
viewer tool, background job and disk cache as missing.

Fix: docs/fidelity/object-matte.md states plainly that nothing is measured
yet and pins down the comparison for when an After Effects 26.2+ reference
is available: four original or openly licensed clips (the synthetic moving
disk from the engine tests, the disk with a jump, two objects with a box
prompt, one CC0/CC BY real clip), the prompt and settings, where reference
mattes stay (gitignored), and the metrics: per-frame IoU against After
Effects (headline), IoU against ground truth, boundary distance, soft-edge
error, temporal stability, drift and time per frame, plus a proposed pass
bar left to the maintainers. Linked from docs/fidelity/README.md.
docs/gaps.md (#14) and docs/target-app-parity.md now list what landed and
leave the comparison as the one remaining item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:07:22 +02:00
vangel76 3466538d0e #783: Object Matte mattes persist in the disk cache
Problem: computed Object Matte segmentations lived only in the in-memory
cache, so every restart or memory eviction segmented the shot again (After
Effects 26.5 keeps Object Matte results in its disk cache).

Fix: the persistent disk cache gets a third entry kind, Matte (folder
`mattes`, LZ4-compressed FrameSeg bytes, same checksum, atomic writes, LRU
eviction under the one size limit, purged with the rest). Entries are keyed by
the segmentation's chain key and scale; chain keys already hash the Input Key
(the layer's source, timing, masks and effects above), the prompt, the mode and
the model, so any change simply misses. The effects crate gets a SegStore
trait behind its memory cache: Chain::ensure reads from it on a memory miss
and writes what it computes. The engine installs the session's DiskCache as
the store (held weakly, so switching the disk cache off drops it). Roto Brush
segmentations go through the same chain and are persisted too. Frozen mattes
already persist in the project (the Frozen parameter).

Tests: engine tests_roto::object_matte_mattes_persist_in_the_disk_cache (a
second session on the same folder and project gets all tracked frames back
without being able to read a single input frame, renders identically, and a
moved prompt finds nothing); render disk_cache
segmentations_round_trip_and_reopen (round trip, reopen, damaged file is a
miss, size limit evicts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:06:33 +02:00
vangel76 560767dfe7 #783: Object Matte tracks in the background and freezes
Problem: Object Matte computed its frames only on demand while rendering, so
playing a shot stalled on every untracked frame, there was no progress or way
to stop, and nothing kept the mattes once computed.

Fix: Object Matte runs through Roto Brush's job machinery (one job slot,
cancellable with roto.cancel, a worker thread on the desktop, a Web Worker in
the browser, never the UI thread). objectMatte.propagate computes the frames
around the reference frame (clipped to the layer) outward, filling the same
content-keyed segmentation cache the renderer reads; the engine's sync now
queues an instance for background tracking when its frames or prompt change.
objectMatte.freeze stores the final mattes in a new hidden Frozen parameter
(Roto Brush's FrozenCache format) under a key of the input, prompt, span,
model and matte settings; renders use them without segmenting while the key
matches; a frozen prompt is refused until objectMatte.unfreeze. Freeze is one
undo step and is dropped if the prompt changed meanwhile.
objectMatte.status reports progress, frozen state and computed frames. Effect
Controls shows Freeze / Unfreeze and Track / Stop with a status line (progress
banner). The frontend now polls Roto Brush / Object Matte jobs on their own:
before, a finished job (and so a Freeze result) was only picked up while a
Warp Stabilizer job was active. Job progress is set before the worker starts.

Tests: engine tests_roto::object_matte_background_job_cancel_and_freeze
(queued by the edit, returns at once with progress, cancel keeps a partial
result, completion computes all 25 frames, frozen renders recompute nothing,
unfreeze recomputes, undo restores); effects object_matte job_frames and
frozen-matte tests (stored pattern used, key mismatch and damaged data
ignored); ui-egui ui_object_matte Effect Controls Freeze end to end.
docs/agents.md: Object Matte section; docs/effects.md regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:02:50 +02:00
vangel76 953fbbc730 #783: Object Matte effect from a point / box prompt, tracked
Problem: After Effects 26.2's Object Matte (pick an object with a click,
optionally a box, get a matte that follows it) had no counterpart; only
stroke-driven Roto Brush existed.

Fix: an Object Matte effect (Effect > Matte, ec.matte.objectmatte) turns
the Object Point (and optional box) on a Reference Frame into Roto Brush
strokes and segments them with Roto Brush's engine, content-keyed cache
and the model chosen in Settings > Roto Brush (MobileSAM, classical graph
cut without it). Track Object carries the matte frame by frame up to 600
frames each way; otherwise every frame is segmented on its own. Feather,
Contrast, Shift Edge, Invert and a Matte view. The engine keeps its Input
Key current so upstream edits recompute it. objectMatte.apply creates one
from agents / the CLI. Unusable prompts pass the layer through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:32:10 +02:00
skylar taylor-barrick 9a7d3e7699
Merge pull request #689 from skylartaylor/codex/ui-suite-integration-20261010
Share docking transactions and preserve viewer lifecycle
2026-10-10 20:10:35 -06:00
skylar taylor-barrick 83ae6218ef UI.9: retain shared docking across upstream workspace changes 2026-10-10 19:25:49 -06:00
Brandon Thomas f953cd2855
Release prep: 0.8.0 and a Linux riscv64 release build (#669)
* Release prep: bump to 0.8.0 and add a Linux riscv64 release build

- release.yml: new `linux-riscv64` job, ported from GridCraft. It cross-compiles on
  ubuntu-24.04 against riscv64 libraries from ports.ubuntu.com (the Linux job's X11/Wayland/GL
  -dev packages plus ALSA), ships effectcraft-<v>-linux-riscv64.tar.gz, and smoke-tests
  effectcraft-cli under qemu-riscv64. The draft-release job now needs it, so its tarball is
  uploaded and covered by SHA256SUMS.txt.
- packaging/linux/package.sh: cross-compiles when CROSS_ARCH/CROSS_TARGET/CROSS_COMPILE are set
  (cargo --target, the cross strip, the EMULATOR smoke test), as GridCraft's does.
- Version 0.7.0 -> 0.8.0 (cargo xtask version set), Cargo.lock refreshed.
- README and docs/releasing.md list the riscv64 tarball.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix FreeBSD CI: pointer_wrap test harness, wasm32 target, clippy as_chunks

- pointer_wrap tests: the harnesses dropped run_ui's FullOutput with the font atlas upload still
  in textures_delta, and epaint 0.36's drop check panics on that in debug builds. Every
  pointer_wrap test failed on every platform; FreeBSD is the only CI that runs them. Clear the
  delta, as the other UI tests do.
- freebsd.yml: install wasm32-unknown-unknown in the VM. Without it the host plug-in test's build
  of examples/plugins/posterize-bands failed (E0463, no std) and the test skipped silently; now
  it builds and runs.
- media/convert.rs: chunks_exact(2) -> as_chunks::<2>() (clippy chunks_exact_to_as_chunks,
  new in Rust 1.99); same pairs, same dropped remainder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:08:18 -04:00
skylar taylor-barrick 3dba472943 UI.9: share docking transactions and preserve viewer lifecycle
Preserve legacy selection repair, modifier routing, viewer lifecycle and workspace persistence through the shared docking integration. Qualify the complete workspace gate by refreshing the 18 stale Audio Spectrum hashes for the existing linear renderer, with an independent synthetic-tone regression.
2026-10-10 17:14:12 -06:00
Claude 1ac09c7fa3
Issue fixes: #591 GPU allocation and device loss, #553 motion-path vertex tools, #488 rename focus, #511 macOS sheet dialogs, #500 MCP file confinement, #343 desktop shortcut 2026-10-10 23:06:04 +00:00
Claude 8fb4281632
MCP: --automation-read-root / --automation-write-root confine the agent's file access (#500)
`effectcraft-cli mcp` had no way to keep an agent's file access to a folder;
the flags were unknown options. Both now take a folder (repeatable, as in
PhotoCraft): with either given, files are read only under a read or write root
and written only under a write root (none: no writes). Defaults are unchanged.

automation::confine::Confinement checks every engine command the backend runs
(execute_command, command_run, open/save_project, each engine.batch step), in
both headless and bridge mode, before it runs: the file parameters of the
commands that read or write files must be absolute paths inside the roots
(symbolic links resolved through the longest existing ancestor, `..` refused),
as must any other absolute path in a command's parameters. Commands that write
where they aren't told are checked against the target they would write: Save /
Increment and Save the open project's file, renderQueue.render every queued
output (renderQueue.list). Scripts, Execute File, Reveal in Finder, Open Recent
by index, `$N` file-path references in a batch, render_frame/screenshot paths
outside a write root and the bridge's UI-driving tools are refused while
confined. docs/mcp.md describes it.

Test: a confined headless server opens and saves inside its roots and is refused
outside them, for a relative path, `..`, a batch step, a `$N` path, Save to a
read-only root's project, the Render Queue's default output there, a symbolic
link out of the write root, and scripts; the unconfined server still writes
anywhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 22:54:57 +00:00
Claude 0b91b465df
Merge pull request #650 from KattKnight/auto-bezier-spatial-tangents
# Conflicts:
#	crates/expr/src/tests.rs
2026-10-10 22:28:40 +00:00
Johnstocker b2d8abdd1c fonts: extra font folders from EFFECTCRAFT_FONT_DIRS
A tool can hand EffectCraft its own font library (a path list) without
installing the fonts system-wide; the folders are scanned like the
system ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 05:10:45 +07:00
Katt 6240ed646e Keyframes: auto-Bezier spatial tangents follow After Effects
Measured against After Effects 26.3 with the original
examples/ae-spatial-tangents.jsx (three paths, ten keys, even and uneven
timing): an auto-Bezier key's out tangent is (next - previous) / 6 and
the in tangent its mirror, whatever the key times; an end key uses its
one neighbour, (neighbour - key) / 6. EffectCraft gave end keys none and
scaled middle tangents by segment length, so paths with auto-Bezier keys
ran up to 28 px from AE's. All ten tangents now match; path samples are
within 0.05 px.

Tests that relied on end keys having no tangent now expect AE's: Spatial
Bezier keeps auto keys' handles (linear keys still get a third), the
motion-path handle is drawn at a sixth, and a straight loopOut path is
compared within 1e-9. docs/fidelity records the method and scores.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:44:49 +05:30
Claude 5e2c7560d6
Import: only dropped files default to stills; scripts and agents naming a frame still get its run (#431)
The UI behaves as in After Effects (the Import dialog's Sequence checkbox
starts off, dropped files are stills, dropped folders make sequences), but
file.import without sequence or drag keeps importing a numbered still's
run, so existing scripts and agents keep working.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 20:15:24 +00:00
Claude 3ba43b20c7
Effect Controls: file parameters get Choose…, Apply Color LUT asks for its LUT on apply, and text parameters get a field (#514, #473)
Cause: Apply Color LUT's only parameter, `lut`, was ParamUi::Hidden (set only
through commands), so the effect could not be used from the UI. Effect
Controls also had no widget for any ParamUi::Text parameter (only EXtractoR's
channels had one), so Cryptomatte's Selection, the OCIO effects' config file /
file / config names and Colorama's Output Cycle could not be set either.

Fix: a new ParamUi::File { filters } for paths. Effect Controls shows the
file's name (None when empty) and a Choose... button that opens the host's
file dialog with those extensions and sets the path (prop.set, so agents use
the same command). As in After Effects, applying an effect with an empty file
parameter from the UI (Effect menu, Last Effect, drops, Effects & Presets)
opens the file dialog straight away; cancelling keeps the effect without a
file. Apply Color LUT's LUT (.cube) and the OCIO Config File (.ocio) and File
(.cube/.3dl/.csp/.cc/.ccc/.cdl/.spi1d/.spi3d/.spimtx) use it. Text
parameters get a single-line field that sets the value when it loses the
focus (Esc keeps the old text). Saved projects are upgraded on open: a
Hidden or Text parameter whose spec is now a File parameter takes the File
UI and keeps its path (effects::migrate). docs/effects.md regenerated.

This covers #473's first part (the Selection field); picking mattes in the
viewer, the layer popup from the file's metadata, the GPU path and quoted
commas are separate.

Tests: effects hidden_and_text_paths_become_file_parameters (migration); ui
file_and_text_parameters_have_widgets (the LUT is asked for on apply and
inverts red to cyan, the Choose... button picks another LUT, typing into
Cryptomatte's Selection sets it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
(cherry picked from commit 403863f703999d19d3a83d9976f76bdc7577e682)
2026-10-10 19:48:25 +00:00
Claude 40e87709d5
Import: numbered stills import as stills unless the Sequence option is on; dropped folders make sequences (#431)
Cause: SequenceOptions::from_params defaulted `sequence` to true for
file.import, so any numbered still (IMG_0001.jpg) brought its whole numbered
run from its folder, and several picked or dropped stills with a common
prefix became one sequence. Dropped files never asked, and the Import
dialog's "<format> Sequence" checkbox started ticked.

Fix, matching After Effects: file.import takes picked and dropped files as
stills unless `sequence: true` (the Import dialog's Sequence checkbox, which
now starts unticked; Force Alphabetical Order implies it), while the numbered
stills inside a picked or dropped folder still import as sequences
(SequenceOptions::folders), and `sequence: false` (Alt-drag of a folder)
imports a folder's files one by one. Replace Footage, reload, proxies and
render outputs keep detecting their sequence (SequenceOptions::default and
from_params are unchanged), and mediaBrowser.import keeps bringing a numbered
still's run unless `sequence: false`. docs/footage.md and docs/agents.md
describe the new defaults.

Tests: sequence import_takes_stills_unless_asked_for_a_sequence and engine
numbered_stills_import_as_stills_by_default (one dropped still and two picked
IMG_ stills stay stills, a dropped folder makes one sequence, the checkbox
brings the run); the existing sequence tests pass `sequence: true`; ui
import_dialog_offers_the_image_sequence_option (unticked by default: a still;
ticked: the run) and a_dropped_folder_imports_as_one_sequence_with_sequence_interpretation
(two dropped frames: two stills; the folder: one sequence).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
(cherry picked from commit aa3c31db9ab3a774ee2f8ba867e1bafc1fce7aba)
2026-10-10 19:48:25 +00:00
Claude 25adc36e21
Merge remote-tracking branch 'origin/main' into int2 2026-10-10 18:44:27 +00:00
Brandon Thomas 1e61b4e04b
Progress docs: target-app parity, gaps, alpha gate, readiness by audience (#617)
Progress docs per craftrules standards/progress-docs.md: target-app parity, gaps, roadmap with alpha gate, readiness by audience (full / mainstream / essentials) with Opus 5.5 hours, and feature, format, hardware, UI and localization parity docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:09:10 -04:00
Claude 4de3354806
Merge pull request #589 from JeremyYao/fix/amd-vulkan-launch-guard
The two test-only conflicts keep main's versions, which already carry the
same fixes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 16:29:06 +00:00
Claude 6e591786f1
Merge pull request #578 from KattKnight/footage-reload 2026-10-10 16:28:05 +00:00
Claude 616574439e
Integrate community PRs: relink's params doc and menu rows, pt-BR in the language list, MCP docs, test fixes
- file.relinkFootage (#461): close the params doc so checked execution
  (MCP, control channel) rejects unknown keys; translate its menu entry.
- general.language lists Português (Brasil) (#217).
- docs/agents.md: set_property / add_keyframe take timeBase (#522).
- #299's MCP test no longer sends get_property a value.
- The Automatically Reload Footage sequence test uses PNG frames.
- h264_frames_at_reduced_sizes (#507): the bar depends on the fixture's
  encoder; 50 dB with ffmpeg 6.1's x264.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 15:15:11 +00:00
Jeremy Yao d86c4aff52 Startup: a launch that stops as its window is shown switches the next to OpenGL
On an ASUS G513QY (Radeon RX 6800M, Adrenalin 26.9.2, Windows 11) every
launch died with STATUS_ACCESS_VIOLATION inside amdvlk64.dll, on a
driver worker thread, a moment after the first frame: eframe shows the
window it created hidden, the resulting resize re-creates the swapchain,
and the driver crashes there (same offset on two driver versions, with
the OBS/Steam/Epic Vulkan layers disabled, and with FIFO, immediate and
latency-1 presentation). DirectX 12 and OpenGL open the window fine.

A crash in a driver can't be caught, and the launch guard (#243) removed
its marker at the first frame, so this looked like a successful launch
every time and Window Graphics never switched. The marker now stays
until the window has kept drawing for SETTLE (3 s) or the app quits
normally before that; frame_drawn returns the time left and the app
asks for a repaint then, so an idle window settles too. The notice,
the Settings note and docs/preferences.md describe the new rule.

Verified on that machine with a scratch settings folder: launch 1
(Vulkan) crashed and left the marker, launch 2 switched to OpenGL with
the notice and closed with exit code 0, launch 3 stayed on OpenGL
without the notice.

Tests: effectcraft launch_guard
a_launch_that_stops_after_its_first_frame_switches_the_next_to_opengl
(a first frame then drop: the next launch gets GL and the notice; a
normal quit in that time leaves no marker), and the existing test now
asserts that the first frames don't settle a launch (marker present at
SETTLE/2, gone at SETTLE).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-10 09:36:59 -04:00
Claude 816fc855d8
Merge pull request #217 from RicSchonfelder/i18n-pt-br
Ported onto the current language plumbing next to Spanish (catalog codes,
Match System for pt-* locales, native menu Services label, docs, tests);
the language list and settings validation stay the shared LANGUAGES table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:57:01 +00:00
Claude b8d23801ff
Merge pull request #460 from llopjulen/i18n/es
Ported onto the current language plumbing next to Ukrainian (catalog
codes, Match System, native menu Services label, docs, tests), and the
stale Ease Presets row (a ScriptUI panel since #404) dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:55:58 +00:00
Claude c7b02cc9a3
Merge pull request #472 from dmatviichuk/i18n/ukrainian-panel-followup
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/ui.rs
#	docs/preferences.md
2026-10-10 12:53:37 +00:00
Claude e87f8a8d6d
Merge pull request #469 from haranishi/i18n-japanese-panels 2026-10-10 12:53:19 +00:00
Claude d8c1711f52
Merge pull request #519 from luniiya/feat/system-appearance 2026-10-10 12:53:19 +00:00
Claude 57bd68c86e
Import: Automatically Reload Footage is Off / Non-Sequence Footage / All Footage, as in After Effects; a reload never shows disk-cached frames from before (#578 follow-up)
Image sequences are watched only with All Footage (the default,
Non-Sequence Footage, leaves them alone). Purge also forgets the viewer's
per-revision disk keys, which hash footage files' size and time, so a
file reloaded without a new revision is keyed again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:53:09 +00:00
Claude 6039e86a04
Merge pull request #466 from tylerjenningsw/enhance/windows-installer-folder
# Conflicts:
#	contributors/people.toml
2026-10-10 12:51:31 +00:00
Katt 98cdc981ad Footage: a file that can't be read is tried again once it changes, not on every look
A footage file the automatic reload couldn't read (still being written, or
one the importer doesn't read) kept its old stamp, so every two-second look
saw it as changed and probed it again. It now keeps its new stamp and is
tried again once it changes again (when the other app finishes writing it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 18:21:21 +05:30
Claude 22345370ac
Merge pull request #517 from sawizzle/docs/installed-release-mcp 2026-10-10 12:51:16 +00:00
Claude a5feb441e9
Merge pull request #499 from tylerjenningsw/enhance/project-shift-delete 2026-10-10 12:51:16 +00:00
Claude 85d71011ac
Merge pull request #458 from storybored379/fix/mcp-review-followups 2026-10-10 12:51:16 +00:00
Claude 5e28ecd53b
Merge pull request #578 from KattKnight/footage-reload 2026-10-10 12:50:18 +00:00
Claude 37cff1f547
Merge pull request #427 from vbasky/pr/measured-ae-fidelity 2026-10-10 12:50:18 +00:00
Claude b5c6eb7d5e
Merge pull request #461 from vbasky/feature/recursive-footage-relink 2026-10-10 12:50:18 +00:00
Claude 82d95d4c72
Merge pull request #299 from DWAA1660/fix/property-group-diagnostic-263 2026-10-10 12:50:18 +00:00
Claude 790f57ef24
Merge pull request #442 from cdinhoo/codex/live-preview-updates
# Conflicts:
#	docs/architecture.md
2026-10-10 12:50:18 +00:00
Claude 9093fd1804
Merge pull request #507 from daijro/perf/footage-playback 2026-10-10 12:49:56 +00:00
Claude f27c834196
Merge pull request #451 from sanyamsingh001/fix/cli-template-rendering 2026-10-10 12:49:17 +00:00
Claude 21a9486d8a
Merge pull request #522 from sanyamsingh001/fix/property-key-time-bases 2026-10-10 12:49:17 +00:00
Katt e6d37c2fa6 Reload Footage shows new pixels and keeps Photoshop layers; Reload Footage Changed on Disk
Reload Footage (Cmd+Alt+L) updated an item's metadata but left the media
pool's decoded frames and the layer cache in place, so the old image kept
rendering until Edit > Purge. It also replaced the footage with a probe of
the merged document, so a Photoshop layer item lost its layer and its
Retain Layer Sizes bounds.

Reload now re-reads only what the file decides (size, a movie's duration,
streams and frame rate, codec, a data file's text), keeps the layer or
page and the interpretation, finds a Photoshop layer again by name, and
makes the media layer forget the file (FootageSource::forget, which also
drops the EXR aux-channel cache) and clears the layer cache.

Settings > Import > Reload Footage Changed on Disk (on by default): the
desktop app stamps footage files (size + modification time) on a worker
thread every two seconds and when the window comes back to the front, and
reloads what changed. Not an undo step and it doesn't modify the project;
a file still being written is retried on the next check.
footage.reloadChanged runs one check (CLI, MCP, agents).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:36:50 +05:30
Sawizzle abbf38f716 docs: drop the third-party link; the Windows path is the default install folder
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:50:57 -07:00
sanyamsingh001 a7a6295bb0 Issue 257: support explicit keyframe time bases
Co-authored-by: Codex <codex@openai.com>
2026-10-10 11:12:14 +10:00
Luniiya fe27c375e3 feat: standardise system appearance modes with PhotoCraft 2026-10-10 02:15:26 +02:00
Sawizzle fbe028717e docs: register the MCP server from an installed release
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 17:06:42 -07:00
daijro 74b151cedc Footage: reduced-resolution renders get movie frames converted at their size
Cause: at Half, Third and Quarter resolution (the viewer's Auto resolution
in most windows) every movie frame was converted from Y'CbCr to f32 RGBA at
full size and then resampled down. In the browser (wasm, one thread) that
was about 8 ms converting a 1080p frame, 6 ms resampling it and 2 ms
zeroing a 33 MB buffer, per layer and frame, for a frame shown at a
quarter or a ninth of its pixels; the footage frame cache held the
full-size frames.

Fix: FootageSource::frame_at_size asks for a frame shown at a given size
(default: the full frame, as before). The renderer asks for it where it
resampled footage (below 3/4 scale; not for proxies, fields or Interpret
Footage's pixel options, which need the full frame). MediaPool makes opaque
4:2:0 movie frames of the footage's own size there: it box-filters them to
half size in Y'CbCr before converting (each 2x2 block of luma, and the
[1 6 1]/8 neighbourhood of its chroma sample, which is the mean of the
upsampled chroma its pixels get), resamples the rest of the way and caches
the result per size. Conversion is linear until colours clip, so this is
the RGB box filter resample starts with, except in blocks where some
colours clip. Other frames convert at full size and resample as before.
In the browser the conversion and resampling take about 4 ms instead of
16. Docs (architecture).

Tests:
- convert::scaled_conversion_matches_resampling_the_converted_frame: half,
  third, quarter and odd sizes of an unclipped 4:2:0 frame are within 1e-5
  of resampling the converted frame; larger sizes, odd frame sizes and
  4:4:4 convert at full size.
- tests_footage_size::reduced_renders_take_footage_resampled_by_the_source:
  a source that resamples frames itself renders the same frames as one
  that doesn't, at 8 and 32 bpc and every resolution, and is asked only
  below 3/4 scale, and not with Invert Alpha.
- footage::h264_frames_at_reduced_sizes (ffmpeg fixture): 1080p H.264
  testsrc2 frames, whose saturated colours clip, at 960x540, 640x360,
  480x270 and 323x182 are 58-62 dB from the resampled full frames, and
  are cached per size.
- convert's ignored 1080p bench also times the conversion at a third.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 16:44:49 -05:00
daijro 2ccc66e73b Web: the layer and footage caches stay small enough for eight stacked clips
Cause: the browser build kept the desktop's cache budgets (1 GB layer
cache, 1 GB footage frame cache) inside the page's memory, which wasm32
caps at 4 GiB. FilmCraft's decoders keep up to 384 MB of decoded frames
per open movie beside them, so a comp of eight stacked 1080p H.264 clips
grew the page by about 55 MB/s while playing and ran it out of memory
after about 50 s ("unreachable": a failed allocation).

Fix: in the browser Prefs::cache_budgets keeps the Layer Cache within
512 MB and the Footage Frame Cache within 256 MB (WEB_LAYER_CACHE,
WEB_MEDIA_CACHE); smaller settings and the desktop are unchanged, and
the RAM preview keeps its budget. Docs (web, preferences) say so.

Tests: tests_m145::web_cache_budgets_leave_room_for_the_decoders: with
4 GB settings the web budgets are the caps, the desktop's are the
settings, and smaller settings stay as they are.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 16:44:15 -05:00
tylerjenningsw 80a23372df Docs: gaps.md records the #484 Shift+Delete tests 2026-10-09 16:27:50 -04:00
Dmytro Matviichuk 4823c08d9c
G9: expand Ukrainian UI coverage (#333)
Translate the 396 current panel catalog rows and route Ukrainian Reveal
labels for Finder, Explorer and File Manager. Enforce catalog parity,
placeholder preservation and platform label coverage; update language docs.
Use a fixed-size OCIO row iterator to satisfy the current Clippy gate.

Co-authored-by: Codex <noreply@openai.com>
2026-10-09 20:54:14 +02:00