Why is my playback time exceeding the content duration?

It can look like a bug: AV - Playback Time on a content shows more minutes consumed than the content's own runtime. The metric is working correctly — this article explains why the calculation can produce a value above the content's duration, and which patterns to look for.

Why the calculation can exceed duration

AV - Playback Time is the sum of av_playback_duration across all events in a session where playback was active. Several legitimate patterns produce more accumulated time than the content's nominal length:

Pattern 1: Replays inside the same session

If a user reaches the end of a video and immediately replays it, the second playback adds to the session's accumulated playback time without resetting it. A 5-minute video watched twice in one session produces 10 minutes of playback time on a single av_session_id.

Pattern 2: Seek-backs and rewatches

Every time the user scrubs back and watches a section again, the re-watched seconds are counted again. A user who watches the same chapter three times during an exploration session produces playback time well above the content duration.

Pattern 3: Multiple plays before a stop

If the user pauses and resumes repeatedly without the session closing, each play-pause-play cycle continues to accumulate playback time in the same session.

Pattern 4: Real-time vs D+1 duration reallocation

In real-time, durations are placed on the next event rather than the one they belong to — because at the moment of an event, Piano doesn't yet know how long that event will last. The daily optimisation routine (runs ~00:00 your site’s timezone) moves each duration to its correct event and merges consecutive heartbeats into single entries.

The practical implication: DataFlow, Data Sharing, and real-time Data Query queries read from the stream table (pre-D+1 reallocation) and will systematically differ from the D+1 interface views — sometimes by hours per session when long pauses or excluded events are involved. For comparable totals across the two sides, query D+1 data, or account for the reallocation mechanism in your downstream processing.

Pattern 5: Live streams

For live content, the "content duration" isn't a fixed value — it grows as the live program continues. A viewer who joins early and stays through the full broadcast accumulates playback time that exceeds any snapshot of the live content's duration captured at the start.

Pattern 6: Tagging issues — duplicate av.heartbeat events

If your player or SDK integration fires duplicate heartbeats (for example, two heartbeat timers running at once after a misconfigured event listener), each heartbeat adds duration. Inspect the event stream — if you see heartbeats firing twice per interval, you have a tagging bug.

How to investigate

  1. Filter to a single session with an unusually high playback time and inspect its events. If the events show legitimate replays / seek-backs, the metric is correct.

  2. Check the timestamp gap between events. Healthy heartbeats are evenly spaced (typically at your configured frequency). Doubled or irregular intervals point to a tagging issue.

  3. Compare real-time against next-day historical. If the over-count is only visible in real-time and disappears the next day, it's the heartbeat-merging processing — not a bug.

  4. For live content, use av_content_time_consumed (sum of av_cursor_difference) rather than playback time when you want to measure unique time consumed, since cursor difference doesn't double-count replays.

When the number is genuinely wrong

If, after the above, the playback time is still inflated and the event stream looks healthy, the most likely cause is a player integration sending heartbeats while the player is paused (the heartbeat continues to accumulate av_playback_duration even though the user isn't actually watching). Compare playback time to av_position movement — if position is static while playback time grows, the player is mis-reporting its state.