Skip to content

fix(telemetry): meter both bitrate fields over the media played, not the transfer (#514) - #666

Merged
superuser404notfound merged 1 commit into
mainfrom
fix/514-played-bitrate
Sep 29, 2026
Merged

superuser404notfound merged 1 commit into
mainfrom
fix/514-played-bitrate

Conversation

@superuser404notfound

Copy link
Copy Markdown
Owner

Round two of #514, from the reporter's retest on Sodalite 1.0.0 (41).

Cause

Both instantBitrateMbps and averageBitrateMbps were metered from demuxerBytesFetched, the reader's transfer counter. Round one fixed the average's divisor; the numerator was the other half of the same defect. Transfer and playback part ways on every route that reads ahead:

  • VOD: prefetch and seek re-fetches count the moment they arrive, so the average reports the prefetch.
  • Live, paused: the pump keeps draining the origin into the DVR window by design (AE#443), the divisor stands still, the average climbs for as long as the pause runs. The instant field keeps reading the incoming stream.

Fix

  • PlayedMediaLedger: the pumps record the played video and audio packets by presentation time on the source axis (native producer next to the recording tap, software host after its timeline fold, both loops). Exact duplicates are held once, a re-read from far behind drops the stale lead.
  • PlayedBitrateMeter: each sampler tick charges the packets the playhead crossed since the last one, over the media seconds it crossed. A pause does not move the playhead, a seek (a step no playback rate can explain) charges nothing, and a span with no recorded bytes stays nil instead of reading zero.
  • Playhead on the ledger's axis: AVPlayer's clock plus playlistShiftSeconds on native (not sourceTime, which is the item axis on a sequential origin), the synchronizer's source clock on software.
  • The transfer stays where it belongs: networkThroughputMbps and [LagDiag]. The remote-HLS bypass keeps its declared rates.

Verification

aetherctl play over a threaded HTTP origin, main against this branch:

Case main this branch truth
Native VOD, H.264, pause 12 s, seek 15 s avg 723, 103, 52 Mbps 18.4 to 19.0 18.2
Software VOD, VP9, same drill avg 385, 54, 26 8.8 to 9.5 8.9
Native live TS, DVR 300 s, paused 50 s avg climbs 23 to 64 during the pause holds 8.12, then 8.0 8.17
Software live, same avg climbs 29 to 71 holds 8.07, then 8.0 8.17

swift test: 646 XCTest (1 skipped) and 3584 swift-testing tests green. tvOS build green. Issue514AverageBitrateTests now covers the reporter's four cases, seek plus re-fetch, and an off-axis playhead.

🤖 Generated with Claude Code

…the transfer (#514)

Round one fixed the divisor of averageBitrateMbps; the reporter's retest
showed the numerator was the other half of the same defect. Both fields
were metered from demuxerBytesFetched, the reader's transfer counter,
which parts from playback on every route that reads ahead: VOD prefetch
and seek re-fetches counted as they arrived (a 20 Mbps stream read about
35), and a paused live session kept draining its origin into the DVR
window (AE#443) while the divisor stood still, so its average climbed
for as long as the pause ran.

The pumps now record the played video and audio packets by presentation
time into a PlayedMediaLedger (native producer next to the recording
tap, software host after its timeline fold), and PlayedBitrateMeter
charges what the playhead crossed on the same source axis: AVPlayer's
clock plus the playlist shift on native, the synchronizer's source clock
on software. A pause and a seek charge nothing, a re-fetched range is
held once, and a span the ledger holds nothing for stays unmeasured
(nil) rather than reading zero. The transfer stays in
networkThroughputMbps and [LagDiag]; the remote-HLS bypass keeps its
declared rates.

Measured with aetherctl over HTTP, pause at 12 s, seek at 15 s:
- native 18.2 Mbps H.264: main avg 723 -> 103 -> 52, fix 18.4 to 19.0
- software 8.9 Mbps VP9: main avg 385 -> 54 -> 26, fix 8.8 to 9.5
Live 8.17 Mbps TS, DVR 300 s, paused 50 s:
- main avg climbs 23 -> 64 (native), 29 -> 71 (software)
- fix holds 8.12 / 8.07 through the pause, 8.0 after

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@superuser404notfound
superuser404notfound merged commit 4894099 into main Sep 29, 2026
7 checks passed
@superuser404notfound
superuser404notfound deleted the fix/514-played-bitrate branch September 29, 2026 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant