#10604·shaka-player

DASH live SSAI (MediaTailor): after #9481, a Period whose start and PTO move for one update still makes StreamingEngine re-fetch from ~2 minutes back (follow-up to #9480)

Author: indieboyalexCreated Sep 17, 2026Updated Sep 18, 2026

Have you read the FAQ and checked for duplicate open issues? Yes. This looks like a remaining case of #9480, "Buffer exhausted after Mediatailor inserts breaks", which is closed and was fixed by #9481, "Shift segment timeline with cached presentationTimeOffset":

  • #9481 is in both versions below, and its "Possibly suboptimal manifest detected! presentationTimeOffset is …" warning appears in our log, so the fix is active on this stream.
  • Our case adds two things to a PTO change: the Period's @start moves with it, and the Period being played is missing from that one update.
  • Also related: #8351 (fixed by #8869) and #8839 (fixed by #8842). Both fixes are in the versions below.

If the problem is related to FairPlay, have you read the tutorial? N/A (Widevine).

What version of Shaka Player are you using? 4.16.49 (debug build).

Can you reproduce the issue with our latest release version? Yes. 5.2.10 (debug build) behaves the same, side by side on the same stream.

Can you reproduce the issue with the latest code from main? Not tested.

Are you using the demo app or your own custom app? A minimal test page: plain Shaka, player.load() of the live MPD, no app code and no custom plugins.

If custom app, can you reproduce the issue using our demo app? The stream is a customer's DRM-protected live channel, so we can't use it in the demo app or share it. Trimmed manifest excerpts are below, sanitised logs and manifests are attached, and we're happy to run patched builds against it.

What browser and OS are you using? Chrome 152 on macOS.

For embedded devices (smart TVs, etc.), what model and firmware version are you using? N/A for this report. We have seen similar re-fetching on a Chromecast with Google TV and a Samsung Tizen 4.0 TV in our app.

What are the manifest and license server URIs? We can't share them (a customer's live stream with Widevine DRM). The structure is below.

What configuration are you using? It reproduces with the default configuration; the only settings we applied were DRM (licence server, preferredKeySystems, SW_SECURE_CRYPTO robustness). At the 06:15 break exit:

  • 4.16.49 re-fetched from 132 s back and stalled for over 30 s;
  • 5.2.10 re-fetched from 122 s back and stalled for 24 s.

See attachment a7. Most of the other evidence was captured with our app's configuration:

javascript
{
  abr: { enabled: true, useNetworkInformation: false, defaultBandwidthEstimate: 2000000,
         restrictions: { minHeight: 360 }, advanced: { fastHalfLife: 4, slowHalfLife: 12 } },
  manifest: { defaultPresentationDelay: 30, dash: { ignoreSuggestedPresentationDelay: true } },
  streaming: { bufferBehind: 10, bufferingGoal: 20, rebufferingGoal: 3, lowLatencyMode: false },
  drm: { preferredKeySystems: ['com.widevine.alpha'] /* + SW_SECURE_CRYPTO robustness */ }
}

What did you do?

  1. Played a live DASH stream with server-side ad insertion (AWS MediaTailor) on the test page.
  2. Waited for an ad break to leave the 180 s live window.

What did you expect to happen? After each manifest update, playback continues from the playhead.

What actually happened? As the last ad period ages out, the packager publishes one update in which:

  • the programme Period currently being played is missing;
  • an earlier Period with the same @id as before has its @start (and presentationTimeOffset) moved 30–45 s earlier, and now lists the programme segments.

The next update, 6 s later, reverts this. As discussed in #9480, we understand you'd prefer the PTO to stay constant within a Period, and we're raising this update with the packager too. We're reporting it here because, even with #9481, the player's reaction turns one bad update into a long stall.

What Shaka does, in both versions:

  • Wrong segment: straight after the bad update, video StreamingEngine fetches a segment 125–144 s behind the playhead: timeNeeded is 146844.81, but it fetches ref(146700.81-146704.01).
  • Useless loop: it then appends that segment, immediately evicts it (buffer behind too large ... bufferedBehind=126), and advances one segment at a time.
  • Result: the forward buffer drains while it catches up, and playback stalls until the re-fetch reaches the playhead.

It can also leave video stuck. At another exit (06:00:41, 4.16.49, attachment a6), the same kind of update was followed by more than the re-fetch:

  • E Possible encoding problem detected! Unexpected buffered range for reference ref(150388.18-150391.38): the references now carry times that don't match their media, which lands at 150409 and later;
  • then (video:3) advancing to next segment null;
  • then timeNeeded=150397.78 ... updating in 1 seconds on every tick. Video made no further requests, and playback stalled a second time when the video buffer ran out, until player.load().
06:01:24.054  E Possible encoding problem detected! Unexpected buffered range for reference ref(150391.38-150394.58) ...
06:01:26.055  E Possible encoding problem detected! Unexpected buffered range for reference ref(150394.58-150397.78) ...
06:01:26.056  D (video:3) advancing to next segment null
06:01:26.056  D (video:3) timeNeeded=150397.7846888882
06:01:26.056  D (video:3) update_: presentationTime=150418.765799 bufferedAhead=9.56621200000518
06:01:26.056  D (video:3) updating in 1 seconds
   ... same every second; video buffer runs out at 150428.3, buffering from 06:01:36 with no video requests ...

It happened at every break exit we checked on 17 Sep (6 of 6, with both configurations). The effect ranged from no visible stall (when the re-fetch caught up in time) to stalls of over 30 s on both versions.

Timeline (4.16.49, UTC, from the V2 log; 5.2.10 is the same to within a second):

05:01:08.552  New manifest 146625.996666666 - 146684.81      (ad/filler Period)
05:01:08.553  New manifest 146684.81 - Infinity              (programme Period)
05:01:13.886  (video:2) advancing to next segment ref(146844.81-146848.01)
05:01:14.522  New manifest 146595.93 - Infinity              <- the bad update: one Period, start moved earlier;
                                                                no "Creating TSI", so an existing Period id was reused
05:01:16.396  (video:2) update_: presentationTime=146825.179203 bufferedAhead=19.63
05:01:16.396  (video:2) fetchAndAppend_: presentationTime=146825.179203 reference.startTime=146700.81 reference.endTime=146704.01
05:01:18.317  (video:2) finished fetch and append [{"start":146700.81,"end":146704.01},{"start":146815.21,"end":146844.81}]
05:01:20.072  (video:2) buffer behind too large: presentationTime=146827.100659 bufferedBehind=126.29 ... evicted 116.29 seconds
05:01:20.552  New manifest 146684.81 - Infinity              <- next update: programme Period restored
05:01:21.891  (video:2) advancing to next segment ref(146710.41-146713.61)
   ... one old segment every ~2 s, each appended then evicted ...
05:01:35      buffering (forward buffer exhausted at 146844.8)
05:02:02      re-fetch reaches the playhead
05:02:07      playing again (stall ~32 s)

The update sequence (captured at a later break exit, 05:09; trimmed to one video Representation; timescale 90000; segments are 3.2 s):

xml
<!-- publishTime 05:09:34: filler Period + programme Period -->
<Period id="147103.926" start="PT40H52M13.992666666S">
  <SegmentTemplate media="video_$Number%07d$.m4s" presentationTimeOffset="13242059339" startNumber="45993" timescale="90000">
    <SegmentTimeline><S d="288000" r="4" t="13245984960"/></SegmentTimeline>
</Period>
<Period id="147193.610" start="PT40H53M13.61S">
  <SegmentTemplate media="video_$Number%07d$.m4s" presentationTimeOffset="13247424960" startNumber="45998" timescale="90000">
    <SegmentTimeline><S d="288000" r="52" t="13247424960"/></SegmentTimeline>
</Period>

<!-- publishTime 05:09:40: ONLY the filler id, start/PTO moved 30.067 s earlier, now listing the programme segments -->
<Period id="147103.926" start="PT40H51M43.926S">
  <SegmentTemplate media="video_$Number%07d$.m4s" presentationTimeOffset="13239353340" startNumber="45995" timescale="90000">
    <SegmentTimeline><S d="288000" r="57" t="13246560960"/></SegmentTimeline>
</Period>

<!-- publishTime 05:09:46: programme Period back, filler gone -->
<Period id="147193.610" start="PT40H53M13.61S">
  <SegmentTemplate media="video_$Number%07d$.m4s" presentationTimeOffset="13247424900" startNumber="45997" timescale="90000">
    <SegmentTimeline><S d="288000" r="57" t="13247136960"/></SegmentTimeline>
</Period>

Segment numbers and presentation times stay consistent across all three updates (for example, #45995 is at 147184.011 in both of the first two). Only the Period structure changes.

Attachments (shaka-issue-A-attachments.zip; URLs, key IDs, PSSH and SCTE-35 data redacted):

  • a1-shaka-4.16.49-v2-log-0501.txt: the full V2 log for the timeline above (05:00:55–05:02:10).
  • a2-shaka-5.2.10-v2-log-0501.txt: the same window from 5.2.10, running side by side.
  • a3-test-page-events-0501.txt: the test page's event log for both players (segment numbers requested, buffered ranges).
  • a4-manifest-0509-*: the three updates shown above (before, bad update, restored).
  • a5-*: the same pattern at 05:53, with the manifests and event log from the same 4.16.49 session. Segment #46838 was requested 125 s back 3.6 s after the bad update.
  • a6-*: the 06:00 exit above, with the manifests, V2 log and event log from one 4.16.49 session (the stuck-video case).
  • a7-default-config-*: the 06:15 exit with the default configuration: manifests, the 4.16.49 V2 log, and the event log for both versions.

Other context

  • MPD: type="dynamic", timeShiftBufferDepth="PT180S", minimumUpdatePeriod="PT6S", SegmentTemplate + SegmentTimeline with $Number$, 3.2 s segments.
  • Programme Periods: CENC-encrypted, 2 video AdaptationSets, 2 audio (es, en), 1 text (wvtt).
  • Ad Periods: clear, 1 video AdaptationSet and 1 audio AdaptationSet.
  • A break adds ad Periods <id>_1, <id>_2, ... then a filler Period with id <id> (the break's start time) whose @start is after the ads.
  • Workaround we ship: an app-side watchdog reloads (or seeks to the live edge) when playback stops progressing.

Source: shaka-project/shaka-player