StreamTest

Live DASH UTCTiming and Clock Drift Explained

Clock drift breaks live DASH because the player calculates which segments are currently available using its own wall clock against the manifest's availabilityStartTime, not by asking the server what time it is; if the client clock is wrong and no UTCTiming element corrects it, the player requests segments that are too new (not yet published, causing 404s) or falls needlessly far behind the true live edge. UTCTiming exists specifically to give the player a way to synchronise against a trusted time source instead of trusting its own clock.

This matters most on live streams because VOD manifests are static and do not depend on wall-clock alignment at all. For live, every segment's availability window is a function of Period start, segment duration, and current UTC time, so a few seconds of drift is enough to move a viewer's stream from smooth playback to constant rebuffering.

The fix is almost always one of: add or correct a UTCTiming element, choose a scheme the target players actually support, or fix the client-side clock source feeding the calculation.

Why does a live MPD need a UTC time source at all?

A dynamic MPD declares availabilityStartTime, the wall-clock moment Period 0 began. From that anchor, plus each Representation's segment duration and the current time, a compliant DASH client works out which segment index is "now" and how far back it can seek within timeShiftBufferDepth. This calculation only works if the client's idea of "now" matches the encoder's idea of "now" at packaging time.

Device clocks are frequently wrong by seconds to minutes: unsynced NTP, a smart TV that has never phoned home, or a set-top box with a dead RTC battery. UTCTiming exists so the player does not have to trust its own OS clock; it fetches or derives an authoritative time and uses that instead when computing the live edge.

What UTCTiming schemes exist and how do they differ?

urn:mpeg:dash:utc:http-xsdate:2014 and urn:mpeg:dash:utc:http-iso:2014 point at a URL that returns the current time as an xs:dateTime or ISO 8601 string in the response body; the player fetches it once (or periodically) and computes an offset against its local clock.

urn:mpeg:dash:utc:http-head:2014 uses an HTTP HEAD request and reads the server's Date response header instead of a body, which is cheaper and works against almost any web server without a dedicated time endpoint. urn:mpeg:dash:utc:ntp:2014 points at an NTP server address for clients with an NTP client built in, and urn:mpeg:dash:utc:direct:2014 embeds the current time directly as the value attribute in the MPD itself, which only stays accurate until the next manifest refresh.

Support across players is uneven: http-head is broadly supported because it needs no special parsing beyond reading a standard header, while ntp requires the player to embed an NTP client, which many browser-based dash.js/Shaka builds do not. Pick a scheme your actual target players implement, and consider listing more than one UTCTiming element so a player can use whichever it supports.

What does clock drift actually look like in playback?

If the client clock runs ahead of true time, the player believes segments are available sooner than they are and requests them before the origin has published them, producing 404s or empty responses right at the point it thinks is "live". If the client clock runs behind, the player computes a live edge that is behind the real one and the viewer watches a stream that never catches up to true live, often described as "stuck a few seconds/minutes back".

A subtler variant is drift that accumulates slowly rather than starting large: a device with a slightly fast clock will work fine at stream start and degrade over a long viewing session as the offset grows past the segment duration, so a bug report of "it starts fine but breaks after twenty minutes" is a strong signal to check clock sync rather than the manifest structure.

How do suggestedPresentationDelay and timeShiftBufferDepth interact with drift?

suggestedPresentationDelay tells the player how far behind the live edge to intentionally sit, which acts as a safety margin absorbing small clock and network jitter; a value that is too small leaves no room for drift before the player runs out of published segments to fetch.

timeShiftBufferDepth defines how far back a live stream can be seeked; if clock drift pushes a player's computed position outside that window, it will either seek to the start of the available window or stall depending on the client implementation. Widening timeShiftBufferDepth does not fix drift, but it does make a stream more tolerant of it.

How do I test whether drift is the actual cause of a playback failure?

Compare the value returned by the UTCTiming endpoint (or NTP source) against true UTC using a trusted reference; a discrepancy of more than a couple of seconds on an http-head or http-xsdate source points at a misconfigured time endpoint rather than the player. Then separately check the playback device's own system clock against true UTC with the UTCTiming source removed, to isolate whether the device or the manifest's time source is at fault.

If the manifest has no UTCTiming element at all, that is itself the likely root cause on any device whose local clock is not tightly synced, and adding one scheme the target player supports is the direct fix rather than adjusting buffer or delay values.

What manifest-side mistakes commonly cause drift symptoms even with correct clocks?

An availabilityStartTime that does not match when the encoder actually started Period 0 produces the same symptoms as clock drift even with perfect time sync, because the live-edge calculation is wrong from the anchor point rather than from "now". Similarly, a UTCTiming http-head or http-xsdate URL that itself sits behind a CDN with a stale cached Date header will silently feed players the wrong time; make sure that endpoint is served with no-cache.

Step by step

  1. Confirm the MPD includes at least one UTCTiming element with a scheme your target players support.
  2. Fetch the UTCTiming URL directly and compare its returned time against a trusted UTC source.
  3. Check that the UTCTiming endpoint itself is not cached by a CDN with a stale Date header.
  4. Verify availabilityStartTime matches the real wall-clock moment Period 0 started on the encoder.
  5. Test playback on a device with a known-wrong system clock to confirm the player actually applies the UTCTiming offset rather than trusting local time.
  6. If drift symptoms appear only after long sessions, check for slow clock skew rather than a one-time offset.

Run it yourself

Free, no sign-up, and every finding links to an explainer.

Frequently asked questions

Does VOD DASH need UTCTiming?
No. A static (VOD) MPD does not depend on wall-clock time to determine which segments are available, since the whole timeline is fixed and known in advance. UTCTiming only matters for dynamic (live) manifests.
Which UTCTiming scheme should I use if I only pick one?
http-head is the safest default because it works against nearly any web server by reading the standard Date response header, and does not require the player to implement a dedicated NTP client. Add a second scheme only if you have confirmed a specific target player needs it.
Can a player ignore UTCTiming and still work?
Some players fall back to their own system clock if UTCTiming is absent or unsupported, which works fine as long as the device clock happens to be accurate. This is exactly why drift-related bugs are inconsistent across devices in the field.
Is direct:2014 a reliable UTCTiming scheme?
It embeds the current time as a literal value at the moment the manifest was generated, so its accuracy decays immediately and depends entirely on how often the player refetches the manifest via minimumUpdatePeriod. It is a reasonable fallback but not as reliable as a live endpoint.

DASH findings, explained

Read next

Last reviewed 2026-09-16.