Commit Graph
743 Commits
Author SHA1 Message Date
Santhi Prakash f75ca076b7 fix(engine): harden ffprobe parsing and command arguments (#2740)
- parseFrameRate now rejects malformed ratios (e.g. "30/", "30/0") instead of NaN.

- Add "--" before file paths so names starting with "-" are not parsed as options.

- cICP PNG chunk no longer returns before IHDR supplies width and height.

- Add regression tests for option injection, frame rates, and cICP ordering.
2026-07-30 12:54:50 -07:00
Vance Ingalls 12ee861123 chore: release v0.7.85 2026-07-30 10:38:10 -07:00
Vance Ingalls 065293ecf3 chore: release v0.7.84 2026-07-30 01:39:54 -07:00
Vance IngallsandClaude Opus 5 c61a24b510 fix(producer): unbias the static element count and stop zeroing failures
Review findings on #2891. Two of them bite directly on this PR's own
purpose — making the fleet element-count distribution readable — so they
are fixed rather than noted.

countElementTags counted `</` + letter anywhere, including inside inline
JS. A compiled comp containing `const h = "</div>"` or a template literal
building `</span>` inflated the count once per occurrence. Compiled comps
embed large inline scripts, so the bias is systematic, not noise, and it
lands entirely on the ~83% of renders with no probe session — precisely
the cohort this PR exists to characterize. Script and style bodies are
now stripped before matching; losing their own closing tags costs 1-2
counts against a threshold in the thousands.

The new elementCount fell back to 0 when its page.evaluate threw,
following the tweenCount pattern beside it. For this field that pattern
is wrong: evaluate failures concentrate on the huge-DOM compositions the
field is meant to observe, and a 0 there is indistinguishable from a
legitimately empty comp, so the fleet p50/p99 would absorb both silently.
It is now undefined on failure, the INIT console line omits the token
entirely rather than emitting a zero, and the parser reports absent —
mirroring the live/static provenance split the routing resolver already
uses.

Also documented: the "every render reaches this path" claim holds only
for renders that survive to end of init, so the tail is survivor-biased
and should be read as a lower bound; and the two element-count fields now
say plainly which is which — composition_element_count gates routing,
observability_init_element_count is the observational counterpart — so
the follow-up analysis can't query the wrong one.

Nits: envInt is integer-only per its name, both live-DOM reads use
getElementsByTagName (live collection length, no NodeList materialized on
the 40k-node tail), and the attribution block notes that it runs with
routing off by design.

Fault injection confirms the new tests bite: disabling script stripping
fails 4, and the zero-vs-undefined case is pinned separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 23:51:14 -07:00
Vance IngallsandClaude Opus 5 d74afc7b7d feat(engine): measure live DOM size on every render, not just probed ones
The short-comp routing gate can only read a live element count when a
probe session exists, and the first v0.7.83 data shows that is far rarer
than estimated: 17% of renders (86/503), not the ">=28%" the video-presence
proxy suggested. The other 83% fall back to a static source scan, which
is exactly blind to the shape that motivated the live count — small
markup, thousands of script-created nodes.

That leaves the fleet element-count distribution unknowable for most
renders, and the observed distribution is already surprising: p99 ~900,
max 1,420 against a 2,500 ceiling calibrated on 7k/20k/40k synthetic
nodes. Either the ceiling is close to irrelevant, or the large-DOM tail
is hiding in the 83% we cannot see. Both readings change what PR B
should do, and neither is decidable from probed renders alone (they are
a biased sample — they got a probe *because* they carry media or
unresolved compositions).

So measure it where every render already goes: capture-session init.
`collectSessionInitTelemetry` gains a querySelectorAll("*") count beside
the tween count it already collects, riding the same channel to
`observability_init_element_count`. This is observational only — capture
has begun, far too late to route on — and it deliberately does not feed
the gate. It answers the distribution question the gate cannot.

Coverage for this channel is proven rather than assumed: the tween-count
fix that shipped in v0.7.83 took the clamped-parallel bucket from 0/272
renders to 217/217, and 23.1% -> 100% overall.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 22:55:12 -07:00
Vance Ingalls 5244dde5f1 chore: release v0.7.83 2026-07-29 18:37:58 -07:00
Vance Ingalls b2e7d76d67 Merge pull request #2875 from heygen-com/feat/de-short-inversion
feat(producer): short-comp DE inversion band — baseline release (telemetry only, routing off)
2026-07-29 17:37:57 -07:00
Miguel Ángel b7160f69bb fix: exclude hidden audio from render mix (#2870)
* fix: exclude hidden audio from render mix

* fix(engine): honor hidden media ancestry in audio mix
2026-07-29 22:10:21 +02:00
Miguel Ángel 85f0c9d354 fix(cli): select host-compatible cached browser (#2861)
* fix(cli): select host-compatible cached browser

* test(engine): make browser cache fixture portable

* fix(browser): reject foreign ARM cache binaries
2026-07-29 20:51:01 +02:00
Vance IngallsandClaude Opus 5 23854f7c6a feat(producer): surface init telemetry from parallel workers — the band's missing motion axis
The routing surface the short-comp benchmarks validated is (motion x DOM
size x frames). After the baseline release, fleet telemetry carries DOM
size (composition_element_count) and frames on every render — but the
motion proxy, observability_init_tween_count, has 0% coverage on the
exact renders the band routes: parallel workers' console buffers (and so
the [FrameCapture:INIT] line the summary parses) only propagate to the
orchestrator on FAILURE. Single-worker screenshot renders report it;
the multi-worker clamp bucket never does. Verified against 7d of fleet
data: 35k screenshot renders carry tween counts, 0 of 9,600 band renders.

Fix rides the one channel parallel workers already return on success —
the per-worker CapturePerfSummary. Sessions record initTelemetry on
every init path; the perf summary now carries it; the orchestrator
max-merges across workers (same multi-session semantics the console
parser uses) and feeds it to the observability summary as a structured
fallback, console lines still refining when present.

With this, every band render carries full coordinates — (elements,
tweens, frames, path, speed) — which buys two reads: regressing wild DE
speed against element count on the existing 900+ inversions validates
the bench's 0.50ms/element slope BEFORE the routing flip, and any
post-flip misroute can be reproduced locally by feeding its telemetry
row straight into gen-crossover-comp's knobs (--movers ~ tween count,
--static ~ element count) and re-benching.

(Also drops a now-stale fallow suppression in render.ts — the test-only
reset export it guarded gained real test importers, so the issue it
suppressed no longer exists and the gate flags the leftover.)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 10:54:24 -07:00
Miguel Ángel b904343949 chore: release v0.7.82 2026-07-29 11:25:04 +00:00
James 0d42d65525 chore: release v0.7.81 2026-07-29 06:11:11 +00:00
Miguel Ángel 5829515932 chore: release v0.7.80 2026-07-29 02:22:54 +00:00
Miguel Ángel 4f344c50b0 Merge pull request #2855 from heygen-com/fix/secure-runtime-dependencies
fix: remove vulnerable runtime dependency paths
2026-07-29 01:14:46 +02:00
Miguel Ángel a68729bcf1 chore: release v0.7.79 2026-07-28 23:06:45 +00:00
Miguel Ángel 13ac9e3905 fix: remove vulnerable runtime dependency paths 2026-07-28 20:45:43 +00:00
Vance Ingalls c691869e22 chore: release v0.7.78 2026-07-28 05:27:29 -07:00
Vance IngallsandClaude Opus 5 4520cd240b fix(engine): bucket gpu_renderer + cover the failure cohort (review)
Three review findings on the win32 drawElement PR:

1. gpu_renderer shipped the raw UNMASKED_RENDERER_WEBGL string — unbounded,
   driver-authored, GPU-model-specific, and |-joined across parallel
   sessions, i.e. high cardinality by construction, against this file's own
   convention of sanitizing engine-sourced strings (deGateReason is a
   bucket; error messages go through redactTelemetryString). Now bucketed at
   the source by classifyGpuRenderer to <backend>/<vendor>
   (metal/apple, d3d11/nvidia, swiftshader/other, ...), which is the whole
   analytic signal the win32 rollout needs and nothing else. The raw string
   never leaves the engine.

2. gpu_renderer reached render_complete only, so a crashed render — the
   cohort the field exists to attribute — carried no backend. It now rides
   RenderCaptureObservability (deGpuRenderer, sourced from the live probe
   session like the de_* counters), so both render_complete and
   render_error carry it and a hard failure still reports its GPU backend.
   On render_complete the perfSummary value still wins by spread order.

3. Restore the fallow-ignore-next-line suppression above
   __resetDeParallelRouterTrialStateForTests: CLI test files are not fallow
   entry points, so removing it fails the CI dead-code audit (local
   pre-commit passed only because of its changed-file scope).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 00:55:10 -07:00
Vance IngallsandClaude Opus 5 cb30157ebb feat(engine): open drawElement fast capture to Windows hardware GPU
Widen the default-on drawElement clamp from darwin-only to darwin|win32
(still requiring a non-software-GPU browser). The darwin restriction was a
validation envelope, not an architectural limit — the CanvasDrawElement
Chrome flag ships on every platform, and every safety layer that made the
macOS default-on release (v0.7.38) survivable is platform-neutral:
compile-time gates, the SwiftShader init gate, per-render worker-encode
self-verification with screenshot fallback, and the blank guard. Worst case
on an unvalidated D3D11 backend is the same as on Metal: verify catches a
bad frame and the render re-runs on the screenshot baseline.

Why now: 30-day telemetry shows ~206k non-CI hardware-GPU Windows renders
(~78% of the win32 fleet, 18k installs) held on the slow screenshot path by
the clamp — the second-largest perf population after macOS, carrying ~1,550
capture-hours/month in the DE-eligible >=700-frame band alone at a measured
~2x speedup opportunity.

Instrumentation for the new cohort: drawElement session init now records the
raw WebGL UNMASKED_RENDERER_WEBGL string (detectSwiftShader generalized to
detectGpuBackend — same single evaluate, the string was previously read and
discarded) and threads it session -> CapturePerfSummary -> RenderPerfSummary
-> render_complete as `gpu_renderer`. drawElement damage proved
compositor-backend-specific throughout the macOS rollout, so D3D11-cohort
failures must cluster by ANGLE backend + GPU vendor (NVIDIA/AMD/Intel), not
just `os`.

The two DE clamp branches are extracted into a pure, unit-tested
`resolveDefaultDrawElement` (platform + GPU mode + worker-encode + explicit
opt-in), which also drops resolveConfig's cyclomatic complexity. The win32
streaming-encode compound tests collapse onto one shared helper.

Linux stays excluded: that fleet is headless/Docker SwiftShader, where DE
has no speedup and known rendering defects. Kill switches unchanged:
PRODUCER_EXPERIMENTAL_FAST_CAPTURE=false, --experimental-fast-capture=false.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 00:00:21 -07:00
Miguel Ángel 3c857d768b chore: release v0.7.77 2026-07-28 02:12:41 +00:00
James 5cad2bc312 chore: release v0.7.76 2026-07-27 05:08:40 +00:00
James 45b458c007 chore: release v0.7.75 2026-07-27 03:38:16 +00:00
James 96cafb47c6 fix(producer): fallback distributed capture safely 2026-07-27 03:08:40 +00:00
James Russo 0cc78c1d42 chore: release v0.7.74 (#2818) 2026-07-26 21:57:54 -04:00
James Russo 58869f0878 fix(producer): accept partial color metadata in plan v2 (#2814)
* fix(producer): accept partial color metadata in plan v2

* test(engine): make partial color probe hermetic

* fix(producer): validate plan v2 sentinels in fallback mode
2026-07-26 21:48:51 -04:00
James 2a284a8e3a fix(gcp): enforce effective BeginFrame capture 2026-07-27 00:02:37 +00:00
James 527751c871 chore: release v0.7.73 2026-07-26 21:25:03 +00:00
James 33ca1de063 fix(render): aggregate extraction launch failures 2026-07-26 19:47:33 +00:00
James c01e1a5f96 fix(producer): narrow extraction error shapes honestly 2026-07-26 19:47:33 +00:00
James 9b63646c8a fix(producer): type video extraction failures 2026-07-26 19:47:33 +00:00
James 2e84faeb28 fix(engine): block future-use IPv4 downloads 2026-07-26 19:00:41 +00:00
James 4b81f78586 fix(engine): close downloader trust-boundary gaps 2026-07-26 19:00:41 +00:00
James 5ce2eb879d fix(engine): narrow network error shapes honestly 2026-07-26 19:00:41 +00:00
James c01f6b4468 fix(engine): make video downloads atomic and retry transient failures 2026-07-26 19:00:41 +00:00
James Russo 72ae39e3d0 chore: release v0.7.72 (#2800) 2026-07-26 02:01:10 -04:00
Miguel Ángel 4b116b9880 fix(producer): normalize padded audio on sample timeline 2026-07-25 21:14:18 +00:00
Miguel Ángel 63bc525ca9 fix(engine): stop mux at shortest normalized stream 2026-07-25 21:14:18 +00:00
Miguel Ángel 20188d637b test(render): cover duration-capped audio mux 2026-07-25 21:14:18 +00:00
Miguel Ángel 19258ea5ba fix(render): cap final mux to video duration 2026-07-25 21:14:18 +00:00
Miguel Ángel 9289551e98 fix(render): scope M4A priming preservation to trims 2026-07-25 21:14:17 +00:00
Miguel Ángel 59c56d3257 fix(render): preserve normalized M4A edit timing 2026-07-25 21:14:17 +00:00
James Russo 8c50770684 fix(engine): preserve bounded ffprobe diagnostics (#2772)
* fix(engine): preserve bounded ffprobe diagnostics

* test(engine): harden ffprobe diagnostic redaction
2026-07-25 17:12:43 -04:00
James Russo 37b88688e7 fix(audio): preserve causes and use portable padding (#2769)
* fix(audio): preserve causes and use portable padding

* fix(audio): address failure taxonomy review
2026-07-25 17:12:31 -04:00
Ular Kimsanov 7cf64164ed Merge pull request #2752 from heygen-com/feat/media-treatment-runtime
feat(runtime): render media treatments deterministically
2026-07-24 12:05:14 -07:00
James d07d1874b6 chore: release v0.7.71 2026-07-24 19:03:16 +00:00
ukimsanov 944640c328 feat(runtime): render media treatments deterministically 2026-07-24 11:17:22 -07:00
Vance Ingalls b9c3e3a4b6 chore: release v0.7.70 2026-07-23 20:59:30 -07:00
Vance Ingalls 4889b779c9 fix(engine): lazy-promisify execFile in psnr so partial child_process mocks don't crash at import 2026-07-23 17:57:15 -07:00
Vance Ingalls 9fc1c2f159 fix(producer): verify sequential disk drawElement samples too 2026-07-23 15:07:35 -07:00
Vance Ingalls 060b6f8ae5 fix(engine): self-verify parallel disk drawElement samples (PRINFRA-352) 2026-07-23 14:41:25 -07:00