Commit Graph
1238 Commits
Author SHA1 Message Date
Miguel Ángel 360ca9cf61 chore: release v0.8.220 (#6781) 2026-10-30 03:37:22 +00:00
Miguel Ángel 54c98b5906 fix(engine): a video on a non-square pixel grid renders at its display shape (#6772)
* fix(engine): a video on a non-square pixel grid renders at its display shape

* chore(engine): drop comments the names already carry

* fix(engine): a rotated clip with a non-square pixel grid keeps its display shape

* test(engine): the frame probes end their options with -- like every ffprobe call
2026-10-30 03:00:25 +00:00
Miguel Ángel 8fb08f2a7c fix(engine): a render no longer waits for a sub-composition timeline no script can register (#6764)
* fix(engine): a render no longer waits for a sub-composition timeline no script can register

* fix(engine): the timeline wait matches a twice-mounted id and a template-literal key
2026-10-30 02:56:22 +00:00
Miguel Ángel a30a520970 chore: release v0.8.219 (#6775) 2026-10-30 02:07:39 +00:00
James Russo f7db6ba40c chore: release v0.8.218 (#6758) 2026-10-29 23:31:55 +00:00
Miguel Ángel 4e2a1c215a chore: release v0.8.217 (#6751) 2026-10-29 15:13:36 +00:00
Miguel Ángel a3ff1c4902 revert(engine): late-starting videos play to their last frame (#6746)
Reverts #6736. Its end-of-clip read fails intermittently on Windows, and the fallback
then expects frames past the clip's end.
2026-10-29 14:14:21 +00:00
Miguel Ángel 22b53c0115 fix(engine): late-starting videos play to their last frame (#6736)
* fix(engine): late-starting videos play to their last frame

A video whose first frame is after timestamp 0 could end early (frozen
tail) or late: ffprobe's stream duration does not run from the first
frame in every container (fragmented MP4, Matroska). Such a video's end
is now read from its last packet, once, where its facts are probed.

* test(engine): the WebM-with-audio case measures its first frame from the file

* test(engine): the first-frame probe ends its arguments with the input file
2026-10-29 12:05:27 +00:00
Miguel Ángel e1a8c7f173 fix(engine): long films show progress during the effect check and never wait minutes on it (#6697)
* fix(engine): long films start capturing at once instead of after a full effect scan

* fix(engine): give the effect scan two minutes, under the app's stall limit

* fix(engine): show effect scan progress so a long scan reads as preparing, not stalled
2026-10-29 10:35:12 +00:00
Miguel Ángel 6df754fbf3 chore: release v0.8.216 (#6735) 2026-10-29 10:01:01 +00:00
Miguel Ángel be05c86932 perf(engine): encode high quality with the x264 fast preset (#6640)
* perf(engine): encode high quality with the x264 fast preset

* test(engine): name the NVENC p5 case by its preset, not the high tier
2026-10-29 06:40:21 +00:00
Miguel Ángel 17f5d67643 chore: release v0.8.215 (#6719) 2026-10-29 06:19:54 +00:00
WaterrrForever cd003e2010 perf(engine): size render workers from measured heap and the container's CPU quota (#6641)
* perf(cli): give render the heap its auto workers need in small containers

Auto worker sizing caps capture workers at (V8 heap - 1024 MB) / 640 MB.
Node sizes its default heap from visible memory, so in a 10 GB container
the heap is 2,096 MB and every render captures with one worker, whatever
the core count.

When no --workers is given, no --docker, no heap was set by hand, and the
heap is the only bound holding workers back, render relaunches itself once
with --max-old-space-size set to what CPU and memory allow (capped at half
of memory). The engine exposes heapMbForAutoWorkers() for this.

* fix(cli): count a heap-relaunched render once, keep detached renders alive

The relaunched child skips the CLI's command telemetry, update and skills
notices, and app-history notice; the parent already records and prints
them. A detached render no longer gets SIGHUP forwarded, which its
default handler would treat as a kill. A heap set as --max_old_space_size
counts as set by hand.

* fix(engine): keep the desktop app's per-worker heap figure at 640 MB

Inside Electron the heap is a hard 4,192 MB cage, and that is where the
field OOM behind the old figure happened (#5149: 5 auto workers on a heavy
export). The new 320 MB figure is measured only in a system Node, so the
desktop app keeps 640 MB (4 workers there) until a heavy desktop export is
measured. Containers and plain Node keep 320.

* fix(engine): know the packaged desktop app by its client tag, which runs the CLI on plain Node
2026-10-29 06:17:07 +00:00
Miguel Ángel a5496b1887 fix(producer): a BeginFrame capture that draws no first frame in 20 s switches to screenshot (#6701)
* fix(producer): a BeginFrame capture that draws no first frame in 20 s switches to screenshot

* test(cli): cover the Chrome launch failure messages a failed render prints
2026-10-29 00:49:04 +00:00
Miguel Ángel 9830059bdb fix(engine): downloads refuse hosts that resolve to private addresses (#6571)
* fix(engine): downloads refuse hosts that resolve to private addresses

* fix(core): shorten the env proxy doc comment

* test(producer): remote-media tests stub the download fetch seam
2026-10-28 20:08:50 +00:00
Miguel Ángel 3ca1005a81 feat(producer): report which element set the film length (#6689)
* feat(producer): report which element set the film length

* fix(core): keep the duration guard and comment share in step with the length helper
2026-10-28 19:05:59 +00:00
Miguel Ángel cdc86117c7 fix(engine): a render from an app that bundles the engine stamps the engine's version (#6686)
* fix(engine): a render from an app that bundles the engine stamps the engine's version

* test(engine): the bundled-layout fixture names a generic app
2026-10-28 17:51:43 +00:00
Vance IngallsandClaude Opus 5.5 c569760a7a fix(core): grade groups resolve per composition; freeze frames keep their lane (#6685)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 10:51:17 -07:00
Vance Ingalls 4719543e97 chore: release v0.8.214 (#6684) 2026-10-28 10:17:04 -07:00
Vance IngallsandClaude Opus 5.5 09b1290474 feat(core): grade groups grade a whole lane from one hf-color-group (#6678)
An inert <hf-color-group> holds a lane's data-color-grading; <video>, <img>
and <canvas> join with data-color-group. A member's own grading overrides
its group's. The runtime discovers members, regrades them when the group's
grading or a member's data-color-group changes, and ungrades them when the
group element or its grading goes, drawing only members on screen.

Render keeps group-graded video at full size like directly graded video,
and lint accepts (and still validates) grading on hf-color-group.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 10:10:42 -07:00
Miguel Ángel c6af88d2e6 chore: release v0.8.213 (#6673) 2026-10-28 16:40:44 +00:00
Miguel Ángel 4db1214e7d test(engine): the multi-chunk encode test gets the 30 s the other ffmpeg tests have (#6663)
* test(engine): the multi-chunk encode test gets the 30 s the other ffmpeg tests have

* test(engine): the mixed-path concat test gets the same 30 s
2026-10-28 13:13:18 +00:00
Miguel Ángel 437784038b fix(engine): late-starting MP4 and WebM videos render every frame the preview shows (#6664)
* fix(engine): late-starting MP4 and WebM videos render every frame the preview shows

The browser counts an MP4 or WebM from timestamp 0, but FFmpeg seeks from the file's
earliest stream start. A file whose first frame comes after 0 (a fragment cut from a
longer stream, an edit-list offset, a WebM with a start offset) was extracted early and
short, so renders tripped the video coverage gate. Every video seek now maps media time
to FFmpeg's timeline, and the video begins where the browser shows it.

* fix(engine): audio from late-starting MP4 and WebM plays when the preview plays it

The mixer seeked and trimmed audio by FFmpeg's clock, which starts at the file's earliest
stream. In an MP4 or WebM whose streams all start after 0, the browser plays that audio
later, so the render heard it early by the same amount. The mixer now maps media time onto
FFmpeg's clock with the same offset frame extraction uses.

* fix(engine): a late-starting file's picture shows on the clock its audio plays on

* test(producer): vfr-screen-recording baseline shows each frame at its timestamp
2026-10-28 13:09:53 +00:00
Miguel Ángel eba596d026 chore: release v0.8.212 (#6660) 2026-10-28 12:29:35 +00:00
Miguel Ángel b6eaed7cae fix(cli): a check page forces a WebGL drawing buffer but keeps no list of 2d canvases (#6650) 2026-10-28 10:41:22 +00:00
Miguel Ángel 7758d9b8fd fix(engine): a Windows browser that will not start says where and why (#6647)
* fix(cli): a Windows browser that will not start says where and why, not just spawn UNKNOWN

* fix(engine): the launch diagnosis names a browser file Windows refuses to run

* fix(engine): the launch diagnosis names a browser file Windows refuses to run (engine part)
2026-10-28 09:41:17 +00:00
Miguel Ángel 5ed694264e chore: release v0.8.211 (#6623) 2026-10-28 09:30:08 +00:00
Miguel Ángel 6553b1f6ba perf(producer): --gpu renders encode while frames are captured (#6631) 2026-10-28 09:24:27 +00:00
Miguel Ángel 8e63faf846 perf(engine): a --gpu render probes the GPU encoders once, not twice (#6638)
* perf(engine,cli): a machine's GPU encoder probe runs once, not on every render

* refactor(engine): one shared probe per process, no answer kept on disk
2026-10-28 08:44:28 +00:00
Miguel Ángel e6476c2cd5 perf(engine): Macs with a hardware GPU render with more capture workers (#6636)
* perf(engine): Macs with a hardware GPU render with more capture workers

* perf(engine): Apple-GPU worker sizing skips layered renders; fewer comment lines

* test(producer): format
2026-10-28 08:42:31 +00:00
Miguel Ángel 6cf4b56697 fix(engine): a render on Windows opens no console windows (#6613)
* ci(windows): probe that a render opens no visible window

* ci(windows): the probe names what opened each window

* ci(windows): the probe spawns each binary alone, with and without detached

* ci(windows): the probe logs the processes started during the render

* ci(windows): the probe also spawns Chrome one consoleless hop down

* ci(windows): the probe logs each child started without windowsHide

* ci(windows): the probe logs every child process with its windowsHide and detached

* fix(engine): Chrome keeps the CLI's console on Windows, so a render opens no window

* fix(cli): every child the CLI starts on Windows is hidden unless it opts out

* ci(windows): the probe bisects Chrome's flags and keeps each command's output

* ci(windows): the probe names the Chrome process behind each window

* ci(windows): the probe loads a page in Chrome directly and one hidden hop down

* ci(windows): the probe prints the Chrome main command line and renders with the reporter's flags

* ci(windows): the probe narrows the CLI's Chrome arguments to the ones that open a window

* ci(windows): the probe launches the CLI's Chrome arguments one hidden hop down

* ci(windows): the probe launches Chrome through the engine's browser pool

* ci(windows): the probe varies what the engine passes to Puppeteer

* fix(engine): renders on Windows launch Chrome with a Puppeteer that keeps it attached

* refactor(cli): hideChildConsoles copies its arguments and keeps one comment line
2026-10-28 07:48:40 +00:00
Miguel Ángel bf7ebe961e fix(cli): local servers never bind a port Chromium refuses to load from (#6620) 2026-10-28 05:16:42 +00:00
Miguel Ángel e5b4f2bf78 chore: release v0.8.210 (#6600) 2026-10-28 00:49:27 +00:00
Miguel Ángel 313792408d fix(producer): HDR sources are tone-mapped for formats that cannot carry HDR (#6597)
* fix(producer): HDR sources are tone-mapped for formats that cannot carry HDR

* refactor(producer): one owner for which output formats can carry HDR

* refactor(producer): drop comments the helper names already carry

* fix(engine): SDR clips are not lifted to HDR when the render tone-maps to SDR
2026-10-27 23:09:15 +00:00
Miguel Ángel 3b2058a2b7 fix(engine): extraction waits out the decode up to a deep seek in a long-GOP video (#6583)
* fix(engine): extraction waits out the decode up to a deep seek in a long-GOP video

* chore(engine): shorten the keyframe gap doc comment

* fix(engine): cancelling an extraction during the keyframe probe reports a cancel

* fix(engine): a segment stopped by another's failure reads as stopped, not cancelled
2026-10-27 20:09:05 +00:00
Miguel Ángel 957df5c268 feat(cli): render --prores-profile picks ProRes 4444, hq, 422, lt or proxy for MOV (#6581)
* feat(cli): render --prores-profile picks ProRes 4444, hq, 422, lt or proxy for MOV

* fix(cli): drop a comment line that raised the comment share

* fix(cli): the render plan args type carries --prores-profile
2026-10-27 19:28:49 +00:00
Akshar Patel 1d4aadc1fb fix(engine): mux uppercase WebM exports with Opus audio (#6579)
* fix(engine): mux uppercase WebM exports with Opus audio

* test(engine): terminate ffprobe options before input
2026-10-27 18:15:39 +00:00
Miguel Ángel c391b50163 test(engine): the test Chrome warms its first page in beforeAll; browser hooks get 30 s (#6568)
A first page of a fresh Chrome stalled past vitest's 10 s hook limit on a contended Windows runner and failed the first test of its file. The first page is now opened inside beforeAll, with the launch and first-page times logged, and the browser project's hooks get the 30 s the CLI's Chrome project uses.
2026-10-27 15:49:13 +00:00
Miguel Ángel 53c9759666 chore: release v0.8.209 (#6562) 2026-10-27 14:34:53 +00:00
Miguel Ángel d6e16aa187 fix(studio-server): undo and redo on Windows wait out a briefly held file (#6559)
* fix(studio-server): undo and redo on Windows wait out a briefly held file

* style(core): format the atomic write test
2026-10-27 14:28:43 +00:00
Miguel Ángel c1da4a760e fix(engine): audio effects launch Chrome like every other render, sandbox retry included (#6550)
Audio effects launched Chrome with its own two flags and no retry, so inside
an agent's macOS seatbelt Chrome died at startup with "Target closed" while
the CLI's own browser launch recovered. The sandbox launch policy now lives
in the engine; the engine's Chrome launch retries once in one process over a
pipe when the sandbox refuses it, and audio effects use the shared Chrome
flags in software GPU mode. The CLI imports the same policy from the engine.
2026-10-27 13:26:01 +00:00
Miguel Ángel cfef528d3a fix: phone videos with an undecodable first audio track check, preview and render (#6551)
* fix: phone videos with an undecodable first audio track check, preview and render

* fix(engine): a rate-lane clip bakes its ramp from the decodable audio track

* test: phone-clip tests end ffprobe options before the input
2026-10-27 13:09:02 +00:00
Miguel Ángel f007882ca7 chore: release v0.8.208 (#6529) 2026-10-27 11:12:48 +00:00
Miguel Ángel 2634a343dd fix(engine): a Chrome shell that ignores SIGTERM can no longer freeze the CLI at launch (#6547)
The start probe waited for the shell to exit after SIGTERM, so a shell that stalled under load blocked the whole process. Kill it outright at the timeout.
2026-10-27 11:09:05 +00:00
Miguel Ángel ae2c4b3942 fix(engine): a GPU probe cancelled by its caller no longer sets software mode for the process (#6541)
The GPU probe's answer is kept for the whole process and the first caller's probe is the
one every later caller waits on. When that first caller cancelled it (a prelaunched
browser dropped, a stopping check), the probe died with "This operation was aborted",
and that cancellation was kept as the answer: every browser the process launched after
it ran in software mode, with a log line blaming the GPU probe. A cancelled probe is now
forgotten and the next caller probes again.
2026-10-27 10:08:51 +00:00
Miguel Ángel 6989271600 perf(producer): a parallel chunk checks BeginFrame on its first worker, with no separate browser (#6500)
* perf(producer): a parallel chunk checks BeginFrame on its first worker, with no separate browser

* style(producer): format

* fix(producer): a chunk whose first worker dies before its check settles instead of hanging
2026-10-27 09:08:54 +00:00
Miguel Ángel 9e5da67409 fix(cli): a Chrome that fails to start says how it ended, and a slow start says so (#6516)
* fix(cli): a Chrome that fails to start says how it ended, and a slow start says so

A failed launch only reported "Protocol error (Target.setDiscoverTargets): Target closed". It now
runs the browser once more on its own with the same flags and reports its exit code (Windows
codes named: missing runtime, out of memory, security software), its last stderr lines, or that
it stayed up. The CLI and the engine's render launch both use it. A start slower than 5 s prints
"Chrome is still starting...", and a --timeout that looks like seconds says it is milliseconds.

* chore(cli): cut the Chrome launch diagnosis comments to the comment limit

* fix(cli): the Chrome startup check runs Chrome as puppeteer does and can be cancelled

The check started the browser with only the caller's flags, so a full Chrome ran headful and
was blamed for a missing X server. It now uses puppeteer's default arguments (headless
included). The check is stopped when the CLI is stopped, and the GPU probe, whose failure
falls back to software anyway, skips it.

* fix(cli): a Chrome launch error is never replaced by a failure to explain it

The startup diagnosis asks puppeteer for its default arguments before re-running
Chrome. If that call fails, its error used to replace the launch error the caller
needed. The launch error is now reported as it was. The core package size budget
rises to cover the new chromeStartup module (about 4.7 KB unpacked).

* refactor(engine): the Chrome startup diagnosis lives in the engine, not core

Both callers launch Chrome through the engine (the CLI already imports it), so the
engine owns the diagnosis. Core's package size budget is back to its old value.
2026-10-27 07:49:04 +00:00
Miguel Ángel 019b17b4b7 fix(engine): a failed video extraction says what ffmpeg reported, without paths or URLs (#6527) 2026-10-27 07:29:03 +00:00
Miguel Ángel 527ab66905 test(engine): Chrome-driving tests run in their own project after the rest (#6517)
* test(engine): Chrome-driving tests run in their own project after the rest

* ci: test reachability understands inline vitest projects
2026-10-27 05:38:33 +00:00
Miguel Ángel 619b8bc4d7 chore: release v0.8.207 (#6510) 2026-10-27 04:33:06 +00:00