* feat(playback): plan v3 routes from pooled node capabilities
Protocol v3 planning previously gated every server transformation on the
API host's local ffmpeg probe, so deployments whose toolchain lives on
transcode nodes (libx264/aac/dovi_rpu on nodes, minimal binary locally)
received conversion terminals before transport preparation ever consulted
the selected node's capabilities.
Planning now draws on two registries split by executor pool:
- Registry stays the local probe and keeps gating progressive remux
routes, which execute in this process and can never offload.
- HLSRegistry widens availability for HLS deliveries with the pooled
transcode nodes' advertised transformations (name and recipe version
pinned to the local specs), fetched concurrently under a short planning
deadline through the existing TTL cache. Failures are now negatively
cached so an unreachable node costs one timeout per window rather than
one per start.
The remux family picks the executor per branch: a recipe needing
transformations only nodes carry skips the progressive remux and ships
the same recipe on the HLS remux delivery instead. The local-fallback
path in prepareTransportV3 now validates plans against the local
registry's advertised set — mirroring the per-node validation — and
returns the existing retryable transcode_node_capability_unavailable
terminal when no executor can run the recipe, instead of spawning an
ffmpeg that would fail at runtime.
Deferred from PR #398 review (comment 3579105380).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(playback): harden union capability planning from review
Addresses all four review findings on the capability-union feature:
- Select capability-matching nodes: plans carrying server transformations
now restrict node selection to nodes whose advertised capabilities
validate against the plan (nodepool.PlanSessionWith with a set-lookup
predicate), so heterogeneous pools cannot load-balance a recipe onto a
node that would reject it while a capable sibling exists.
Transformation-free plans keep pure load-based selection.
- Split the capability cache by consumer: planning honors negatively
cached fetch failures (one timeout per window), while the transport
path fetches through them — a memoized 3s planning deadline must not
reject an already-selected node that the 10s transport budget could
still validate.
- Gate node-widened availability on the HLS engine: a progressive-only
client that needs audio conversion keeps its specific retryable
audio_conversion_unsupported terminal instead of falling through to a
non-retryable adaptation_unavailable for routes it can never run; the
DV strip union flag is gated identically.
- Make HLSRegistry a lazy, memoized producer: the planner only builds
the widened registry when a route decision depends on node
capabilities, so direct-play and other source-preserving starts never
wait on node capability fetches (or their dead-node deadlines).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>