feat: compute-aware ABR feedback for Shaka and dash.js plugins#137
Merged
Conversation
Adds a segment-level perf bus on which SegmentTranscoder publishes a SegmentPerfStat (speedX = segDurMs / totalMs, width, height, frames) for every successfully transcoded segment. A new ComputeAwareDecider rolls those measurements through a hysteresis window and emits subtractive cap decisions (lower / raise / hold). Player-specific adapters wire the decider to each player's ABR knobs: - Shaka: handle.attachComputeAware(player, opts?) -> player.configure with abr.restrictions.maxHeight + maxBandwidth caps - dash.js: attachHevcSupport accepts adaptiveCompute -> updateSettings on a maxBitrate cap ON BY DEFAULT. Bandwidth-based ABR has no way to observe transcode cost, so a perfectly reachable variant can still saturate the device's CPU. Default opt-in matches the actual cost shape of this library; pass adaptiveCompute: false to opt out. Defaults tuned for the compute-aware shape: - measureWindow: 2 (was 8) - lowerAfter: 1 (was 2) — buffer underrun is much worse than a brief unnecessary cap dip, so the decider reacts in ~2 segments instead of waiting for an 8-window average - raiseAfter: 6, targetSpeedX: 1.3 (unchanged — still need real hysteresis on the raise side) attachComputeAware(player, opts?) merges register-time options with runtime options — convenient when the telemetry sink (onObservation) is only known once the UI exists. onObservation now receives the decision reason (init | hold | lower | raise) for richer diagnostics. The decider snapshots state before each decision so applyCap failures (player destroyed, etc.) can be reverted in-band. Cold-start guard prevents raising before any lower has happened. Both plugins re-export subscribeSegmentStat + SegmentPerfStat from @hevcjs/core for custom telemetry on the raw perf bus. Demos wired with a compute-aware live overlay (active quality + segment speedX + cap + reason) and a diagnostic perf-bus probe. README + per-package READMEs + site docs updated. Closes #127
Contributor
Benchmark Results (GitHub Actions runner)
Auto-generated by CI benchmark |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a segment-level perf bus on which SegmentTranscoder publishes a
SegmentPerfStat (speedX = segDurMs / totalMs, width, height, frames)
for every successfully transcoded segment. A new ComputeAwareDecider
rolls those measurements through a hysteresis window and emits
subtractive cap decisions (lower / raise / hold). Player-specific
adapters wire the decider to each player's ABR knobs:
with abr.restrictions.maxHeight + maxBandwidth caps
on a maxBitrate cap
ON BY DEFAULT. Bandwidth-based ABR has no way to observe transcode
cost, so a perfectly reachable variant can still saturate the device's
CPU. Default opt-in matches the actual cost shape of this library;
pass adaptiveCompute: false to opt out.
Defaults tuned for the compute-aware shape:
unnecessary cap dip, so the decider reacts in ~2 segments instead of
waiting for an 8-window average
hysteresis on the raise side)
attachComputeAware(player, opts?) merges register-time options with
runtime options — convenient when the telemetry sink (onObservation)
is only known once the UI exists. onObservation now receives the
decision reason (init | hold | lower | raise) for richer diagnostics.
The decider snapshots state before each decision so applyCap failures
(player destroyed, etc.) can be reverted in-band. Cold-start guard
prevents raising before any lower has happened.
Both plugins re-export subscribeSegmentStat + SegmentPerfStat from
@hevcjs/core for custom telemetry on the raw perf bus.
Demos wired with a compute-aware live overlay (active quality + segment
speedX + cap + reason) and a diagnostic perf-bus probe. README +
per-package READMEs + site docs updated.
Closes #127