Commit Graph
6 Commits
Author SHA1 Message Date
bflatasticandClaude Opus 5.5 50c9549529 Import: image sequences with a Sequence option, ranges, folders and missing frames (#297)
Image sequences were found only by the desktop media prober: one picked
numbered still brought its whole run, with no way to import just that
frame, picking every frame made one sequence item per frame, the browser
couldn't make sequences at all, and a gap in the numbering closed up
silently.

The engine now groups numbered stills itself (engine/src/sequence.rs):
one picked file brings its run from its folder, several picked files of
one run import as that range, a picked or dropped folder imports its
files with each run as a sequence, and Force Alphabetical Order takes
every image of that type in the folder by name. `file.import` takes
`sequence` (default on), `alphabetical` and `frameRate`; Replace Footage,
Reload, proxies and render outputs probe the same way. The media layer
probes one file; the browser lists its file table for the run and
registers every frame with its media pool.

File > Import > File... asks, like After Effects' "PNG Sequence"
checkbox, whether picked numbered stills import as a sequence, with
Force Alphabetical Order and the frame rate. Sequences are named
`shot_[0001-0250].png`.

Interpret Footage gains Missing Frames (Show Placeholder, colour bars as
in After Effects, the new default; Hold Previous Frame; Skip) and Start
Frame (the frame number at the footage's first frame: trims or pads the
head). Saved projects keep Skip, so their sequences play as before.

Form notes keep a readable width and the form fits its rows, so OK stays
in view. docs/footage.md explains importing footage and sequences.

Test: tests_sequence (engine: run, picked range, every frame, Sequence
off, folder, alphabetical, Interpret Footage Missing Frames / Start
Frame, Replace Footage and Reload), project sequence unit tests,
sequence_gaps_show_placeholders_hold_or_close_up (media),
import_dialog_offers_the_image_sequence_option and
dropped_frames_import_as_one_sequence_with_sequence_interpretation (UI).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:00:07 +07:00
Claude a2f22bb35b Web: a replaced file goes to reused workers again, even at the same size (#218)
Job workers remembered the files they were sent by path and byte
length, so footage replaced by different bytes of the same length at
the same path was never resent: a Render Queue export through a reused
worker rendered the old image while the page showed the new one.
Frame workers remembered paths only, so they never got a replacement
at all.

Every write of a stored file now gets a version, and both kinds of
worker remember the version they were sent.

Tests: versions_change_with_every_write (store) and
apps/effectcraft-web/tests/workers.mjs (Node, fake Worker: the
replacement is sent once, an unchanged file not again).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018gnTnH3Jmk5zr4tMq1Mc9f
2026-10-07 22:33:04 +00:00
Brandon ThomasandClaude Opus 5.5 3921e6c680 M13.30: Content-Aware Fill in a job worker on its GPU
contentFill.generate sends its plan (FillPlan) to a browser job worker:
the layer's frames render in passes on the worker's WebGPU device, the PNG
sequence goes back to browser storage (Services::store_file), and the page
adds the fill layer when the plan returns (WorkerReply::Fill). The smoke
test checks it; docs updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 03:15:54 -04:00
Brandon ThomasandClaude Opus 5.5 f3715aac32 M13.30: web depth and polish
- GPU in browser job workers: each job worker opens its own WebGPU device
  (deferred readbacks); the Render Queue export and the analyses' frame loops
  are futures (render::passes, offload::run_request_async) whose frames
  render in passes, awaiting the device between them. GPU particles and
  Advanced 3D read back under keys too. workers.jobs reports passes and
  readbacks; the smoke test measures them.
- Layer buffers in the browser's OPFS disk cache: frame workers back their
  layer caches with a PrefetchStore; the page plans what to fetch before a
  request from recent misses (LayerPrefetch over the shared DiskIndex).
- Templates embed footage (default on, size-capped with a warning) and
  creating from a template extracts it next to the new project / into
  browser storage.
- ICC LUT profiles (lut8/lut16/lutAtoB/lutBtoA, from the public ICC spec) in
  Simulate Output > My Custom RGB, baked into a 3D LUT for the viewer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:57:17 -04:00
Brandon ThomasandClaude Opus 5.5 0bee1ab2da M15.2: web app depth (WEB-1): browser storage, Web Audio, worker renders, WebGPU viewer, PWA
- Persistence: settings, shortcuts, recent projects, imported media, saved projects and
  auto-saves live in OPFS (IndexedDB fallback) through an in-memory mirror flushed in the
  background (apps/effectcraft-web/src/store.rs, persist.rs); ConfigStore gains FileOps so
  auto-save / recovery work in the browser store; the session snapshot restores the last
  project + editor state on reload; File > Open Recent works from storage.
- Audio: Web Audio output (AudioWorklet, ScriptProcessor fallback) fed by AudioPlayback::pump
  on wasm32; A/V sync from AudioContext.currentTime; meters; unlock on first gesture.
- Background jobs: engine::offload (WorkerRequest/WorkerReply protocol, Offload trait,
  run_request); Render Queue, tracker, mask tracker, Warp Stabilizer and Roto Freeze run in Web
  Workers (a second engine instance on the shared compiled module), progress streamed back;
  cancel terminates the worker.
- GPU: WebGPU viewer frames drawn straight from the compositor's texture (gpu_display on
  wasm32 when the viewer draws plainly); async readback (Gpu::read_display_async) for pixels.
- PWA: manifest, service worker precaching the build (xtask fills list/version), icons copied
  from assets/app-icon; COOP/COEP kept from cached responses; offline reload works.
- window.effectcraft: saveToBrowser, listStored, removeStored, flush; info() reports storage,
  audio, gpu, workers.
- Tests: native store + protocol + offload (render, track, cancel) tests; smoke.mjs extended
  (GPU path, worker render responsiveness, audio gesture + playback, reload persistence,
  Open Recent, offline reload).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:42:00 -04:00
Brandon ThomasandClaude Opus 5.5 31f192e2a9 M15.1: web build (eframe wasm) + xtask web
- apps/effectcraft-web (L6): eframe web runner booting the shared EffectcraftApp with a browser
  session: in-memory file table, <input type=file> pickers and drag-and-drop for open/import,
  downloads for Save and Render Queue outputs (several files as one stored .zip), and the
  window.effectcraft promise API over the control channel. Demo project on start.
- wasm32 runtime fixes: web-time for Instant/SystemTime (render, engine, export, ui-egui);
  Frames renders queued jobs on the UI thread (Frames::pump) instead of a thread pool;
  Render Queue runs inline; relative outputs resolve under / ; control PNGs inline.
- effectcraft-export: per-job output Sink (files to memory instead of disk); host FileExporter
  carries it; test that sink exports touch no file.
- xtask web [--dev] [--serve PORT] (wasm-bindgen 0.2.129, optional wasm-opt, COOP/COEP server);
  effectcraft-web in WEB_CRATES. docs/web.md, headless Chrome smoke test, favicon (+attribution).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 00:19:35 -04:00