HLS Seeking and Trick Play Explained: How Players Scrub Segmented Streams
August 12, 2026 · 6 min read
Key takeaways
- Seeking in a segmented stream requires the player to calculate which segment contains the target timestamp and fetch from the start of that segment — not from the exact byte offset like a progressive file.
- #EXT-X-I-FRAMES-ONLY playlists expose only the keyframes (I-frames) from a stream, letting a player scrub visually or fast-forward without decoding every intermediate frame.
- Trick play playlists are declared in the master playlist alongside normal variants via the I-FRAME-STREAM-INF tag, giving the player separate segment lists at each available quality.
- A download tool that only reads segment durations and URIs from a media playlist can seek correctly for VOD but has no way to expose or generate trick-play thumbnails without the I-frames-only track.
Seeking in a progressive video file is straightforward: the player calculates the byte offset for the target timestamp and issues an HTTP Range request for that position. Seeking in an HLS stream is a structurally different operation, because the video is split across many independent segment files with no shared byte map. The timestamp-to- segment calculation, the I-frames-only playlist, and the #EXT-X-I-FRAME-STREAM-INF tag in the master playlist are the three pieces that make seeking and trick play work.
How a player seeks to a timestamp
Every segment in a media playlist is annotated with a #EXTINF duration tag. A player seeking to a target timestamp (say, 4 minutes and 30 seconds into a 90-minute film) walks the playlist from the top, summing #EXTINF values until the running total passes the target. The segment that pushes the total past 4:30 is the one to fetch.
Because segments are opaque files — not a single seekable byte stream — the player cannot land on an exact frame. It can only land on the start of a segment. Once that segment is fetched and the decoder receives it, the player advances frame by frame inside the segment until it reaches the exact presentation timestamp, then resumes normal playback. On a 6-second segment, the worst-case error is just under 6 seconds; the player hides this by starting decode from the first keyframe in the segment and rendering forward silently.
If the playlist carries #EXT-X-PROGRAM-DATE-TIME tags, the player can additionally map a wall-clock time (not just a stream-relative offset) to the correct segment, enabling DVR-style seeks by calendar time rather than elapsed duration.
Why seeking in HLS is slower than in a progressive file
A progressive MP4 or WebM file embeds a seek table — the moov atom or its equivalent — that maps every keyframe to a byte offset. A browser with a Range-capable server can jump directly to any keyframe boundary with a single HTTP request targeting the right byte range.
An HLS player has no such table for the overall stream. It has per-segment #EXTINF durations, which let it identify the correct segment quickly, but it still has to fetch and start decoding that segment before the picture appears. On a cold cache, this means at minimum one full HTTP round-trip and one segment download before any frame is visible — noticeably slower than a progressive seek that resolves in a single range request. That latency is compounded by adaptive quality changes: when a user drags the seek bar to a new position, the player may be forced to switch to a lower-quality variant while it re-fills its buffer at the new position.
I-frames-only playlists and trick play
Trick play — fast-forward, rewind, and thumbnail preview during scrubbing — has a sharper version of the same problem. At 8× speed, the player needs to render roughly one new frame every 125 ms. Fetching and fully decoding normal segments at that rate would require decoding every B-frame and P-frame between keyframes, at eight times the normal throughput. On most hardware that is not feasible.
HLS solves this with the #EXT-X-I-FRAMES-ONLY tag. A media playlist carrying this tag contains only the keyframes (I-frames) from the original video, each wrapped in its own segment. Because I-frames are self-contained — no dependency on any prior frame — the player can decode any one of them in isolation, producing a still image. For fast-forward or rewind, the player steps through these segments at the appropriate rate; for thumbnail scrubbing, it may decode a handful of them in advance and cache the resulting still images as the user drags the seek bar.
The segment files in an I-frames-only playlist are typically byte-range references into the same segment files as the normal variant, using #EXT-X-BYTERANGE to point at the exact bytes containing each I-frame. This avoids duplicating the video data on disk; the CDN serves the same files for both normal playback and trick play.
How the master playlist exposes trick play tracks
Normal stream variants in a master playlist are declared with #EXT-X-STREAM-INF. Trick play variants use a separate tag: #EXT-X-I-FRAME-STREAM-INF (no hyphen before STREAM). Each tag carries a URI attribute pointing to the I-frames-only media playlist and a BANDWIDTH attribute so the player can choose an appropriate quality level for the current scrub speed. A master playlist can list multiple I-frame-only variants at different bandwidths alongside the normal renditions:
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=86000,RESOLUTION=1280x720,URI="iframe_720p.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=30000,RESOLUTION=640x360,URI="iframe_360p.m3u8"The player selects among these based on available bandwidth and the requested trick-play speed: higher speeds need faster frame delivery, so a lower-bandwidth I-frame track is often preferred to keep fetch latency down.
What this means for converters and download tools
A download tool that reads segment durations and URIs from a media playlist — like the /convertpage — handles seeking correctly for a saved file: once the video is muxed into a single MP4, the browser's native seek table takes over and normal progressive seeking applies. The HLS segment-boundary limitation disappears.
Trick-play thumbnails are a different story. The I-frames-only playlist is a separate track in the master playlist, not part of the normal segment sequence. A converter that downloads only the highest-BANDWIDTH normal variant never touches the I-frame track and produces no thumbnail strip. Generating scrub thumbnails from a downloaded file would require a separate pass — decoding keyframes at regular intervals and compositing them into a sprite sheet — which is a post-processing step, not a download-time operation.
The Stream Video Downloader extension detects the normal media playlist from network traffic and does not separately capture the I-frames-only track. The saved MP4 plays back with full browser-native seeking; trick-play thumbnail strips are not part of what is saved.
Seeking in live and EVENT streams
For a live sliding-window stream (no #EXT-X-PLAYLIST-TYPE tag), seeking backwards past the DVR window boundary is impossible: old segments have been removed from the playlist and their files may no longer exist on the CDN. The player's seek range is bounded by the oldest segment still in the manifest.
For an EVENT stream, all published segments remain in the playlist and on the CDN, so the full history is seekable by the same duration-summation method. Once the event ends and #EXT-X-ENDLIST appears, the stream is effectively a VOD asset and seeking works identically — the playlist is now static and the player knows the full duration.
Questions & answers for AI agents
Short, direct answers an assistant can quote or summarize.
How does an HLS player seek to an arbitrary timestamp?
The player walks the #EXTINF duration tags in the media playlist, summing durations until the cumulative total reaches or exceeds the target time. The segment that pushes the total past the target is fetched, and playback begins from that segment's start. Because segments are not individually addressable by byte offset like a progressive file, the player can only land on a segment boundary — it then decodes forward from that point to reach the exact frame.
What is #EXT-X-I-FRAMES-ONLY in HLS?
#EXT-X-I-FRAMES-ONLY marks a media playlist whose segments contain only the keyframes (I-frames) from the video stream. Because I-frames are the only frame type that can be decoded independently, a player can show a still image for each one without decoding the surrounding predicted frames. This is used for visual scrubbing (thumbnail preview while dragging the seek bar) and for fast-forward at speeds where decoding every frame would be too expensive.
How does a master playlist declare trick play tracks?
The master playlist uses #EXT-X-I-FRAME-STREAM-INF tags (note: no STREAM) instead of the normal #EXT-X-STREAM-INF. Each I-FRAME-STREAM-INF carries a URI pointing to an I-frames-only media playlist and a BANDWIDTH attribute so the player can pick an appropriate quality for the scrub speed. Normal variants and I-frame-only variants coexist in the same master playlist.