> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://fastpix.com/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://fastpix.com/docs/_mcp/server.

# Generate advanced spritesheets for hover previews

Add frame-accurate hover previews to a long video by generating a dense thumbnail spritesheet at the interval you choose, with a matching WebVTT track and JSON manifest your player can read. Advanced spritesheets work on ready on-demand video.

\


## What an advanced spritesheet is

An advanced spritesheet is a single JPEG grid of video thumbnails captured at a fixed interval you choose, from 1 to 10 seconds, with a matching WebVTT file and JSON manifest so a player can show hover previews on the seek bar. FastPix generates it on demand, one sheet per interval, and a media can hold up to ten of them.

The [standard spritesheet](/docs/video-on-demand/create-timeline-hovers-from-a-video), which every video gets automatically, stays unchanged. The difference is density and control.

|                      | Standard spritesheet                                                             | Advanced spritesheet                                                                     |
| -------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| When it is made      | Automatically when the video is processed                                        | On request, per interval                                                                 |
| Thumbnail spacing    | Computed from the video length (50 tiles up to 15 minutes, 100 tiles above that) | Fixed: 1, 2, 3 ... 10 seconds, chosen by you                                             |
| Thumbnails per sheet | Up to 100                                                                        | Up to 6,300                                                                              |
| Sheets per media     | 1                                                                                | Up to 10 (one per interval)                                                              |
| Grid                 | 5 columns                                                                        | 5 to 64 columns (landscape) or 5 to 102 columns (portrait), sized to the thumbnail count |
| Delivery paths       | `spritesheet.jpg`, `.vtt`, `.json`                                               | `advanced-spritesheet.jpg`, `.vtt`, `.json`, each with `?interval=N`                     |

A two-hour film with the standard sheet gets one thumbnail every 72 seconds, which makes seek-bar previews coarse. With an advanced sheet at two seconds, the same film gets 3,600 thumbnails, so scrubbing is accurate to within two seconds. Shorter intervals mean more tiles, so the longest video an interval can cover shrinks as the interval shrinks. See [Pick an interval](#pick-an-interval).

Each thumbnail is 256 x 160 px for landscape video or 160 x 256 px for portrait. Tiles are laid out in playback order, left to right then top to bottom.

\


## Choose by use case

Every approach produces the same three files. Start from what you are building.

| If you want to                                                 | Use                         | Start at                                                                |
| -------------------------------------------------------------- | --------------------------- | ----------------------------------------------------------------------- |
| Add precise hover previews to a long film, lecture, or webinar | The WebVTT track            | [Serve previews in an HTML5 player](#serve-previews-in-an-html5-player) |
| Build your own scrubber or timeline UI                         | The JSON manifest           | [Build a custom scrubber](#build-a-custom-scrubber)                     |
| Preview private or DRM-protected content securely              | Token-gated URLs            | [Serve private and DRM media](#serve-private-and-drm-media)             |
| Preview a vertical or short-form video                         | The portrait sheet          | [Pick an interval](#pick-an-interval)                                   |
| Preview a past live stream                                     | The recording's playback ID | [Support by media type](#support-by-media-type)                         |

\


## Before you start

* A FastPix account with an active workspace ([Activate your account](/docs/getting-started/activate-your-account)).
* A ready on-demand video. Upload it [from a URL](/docs/video-on-demand-api/input-video/create-media) or [directly from a device](/docs/video-on-demand-api/input-video/direct-upload-video-media) and wait for its status to reach `ready`.
* The media's playback ID.
* A signing key if the media is private or DRM-protected ([Generate JWTs for secure media](/docs/video-security/generate-jwts-for-secure-media)).

\


## Generate an advanced spritesheet

You can generate a sheet from the dashboard or straight from a delivery URL. A programmatic list-and-request API is coming to the API reference. Generation usually takes 30 seconds to 2 minutes, longer for a 1 or 2 second interval on a long video.

### From the dashboard

1. Open the media's detail page and go to **Thumbnails**. On the dashboard, find your video in the **Media** library and open it.

   The media's **Overview** opens with its details and playback ID.

   Open the **Thumbnails** section from the left menu to see the Thumbnail, GIF, and Timeline hovers cards.

2. In the **Timeline hovers** card, switch to the **Advanced** tab. The **Standard** tab shows the automatic sheet.

3. Pick an interval on the 1 to 10 second slider. The slider shows how many thumbnails that interval produces for this video, or a message if the video is too long for it. Click **Generate**.

4. The interval appears as a chip marked processing, then flips to ready. The card shows the sheet with its delivery URL, and hovering the preview scrubs through it.

5. Click **+ Add interval** to generate another. Intervals that already exist are shown but disabled. The button disappears once all ten exist.

The tab uses the media's first-created playback ID. If that playback ID is private or DRM-protected, the dashboard shows the URL with a `token={JWT}` placeholder and no preview, so you substitute your own signed token.

### From a delivery URL

All three files live on the image delivery domain, keyed by playback ID and interval.

**`URL`**

```text URL
https://images.fastpix.com/{PLAYBACK_ID}/advanced-spritesheet.jpg?interval=N
https://images.fastpix.com/{PLAYBACK_ID}/advanced-spritesheet.vtt?interval=N
https://images.fastpix.com/{PLAYBACK_ID}/advanced-spritesheet.json?interval=N
```

* `interval` is a whole number from 1 to 10. Omit it and the service uses 10. `.jpeg` is accepted as an alias of `.jpg`.
* Fetching the `.jpg` for an interval that was never generated starts generation and returns `202 Accepted` with a JSON body saying it is in progress. Fetch again later for the image.
* The `.vtt` and `.json` are computed from the video's duration and never start a job. Hand the `.vtt` to any player that supports thumbnail preview tracks, and use the `.json` to build a custom scrubber.

> **Note:** For one playback ID and interval, the image, VTT, and JSON always agree. The VTT cue count equals the JSON tile count equals `floor(duration / interval)`, every cue is exactly `interval` seconds long, and the `#xywh` coordinates in the VTT match the `x` and `y` in the JSON.

\


## Pick an interval

Shorter intervals produce more thumbnails, and a sheet is capped at roughly 6,300 tiles, so each interval can only cover videos up to a certain length. Nothing over 8 hours is supported at any interval.

| Interval | Maximum video length | Thumbnails at that length |
| -------- | -------------------- | ------------------------- |
| 1 s      | 1 hour               | 3,600                     |
| 2 s      | 3 hours              | 5,400                     |
| 3 s      | 5 hours              | 6,000                     |
| 4 s      | 7 hours              | 6,300                     |
| 5 s      | 8 hours              | 5,760                     |
| 6 s      | 8 hours              | 4,800                     |
| 7 s      | 8 hours              | 4,114                     |
| 8 s      | 8 hours              | 3,600                     |
| 9 s      | 8 hours              | 3,200                     |
| 10 s     | 8 hours              | 2,880                     |

The thumbnail count for a given video is `floor(duration / interval)`. A 1 hour 12 minute video at 3 seconds produces 1,440 tiles. When a request breaks the rule, the error names the fix, for example "Video duration 18000.00s exceeds cap for interval=1s (3600s). Minimum interval for this video: 3s." The dashboard disables intervals the video cannot use and shows the same message on the slider.

A few worked examples:

* **A 90-minute webinar (5,400 s).** Interval 1 is not allowed (cap 1 hour), so the smallest usable interval is 2 (cap 3 hours), giving 2,700 thumbnails. Choosing 1 returns an error naming interval 2 as the minimum.
* **A 6-hour conference recording (21,600 s).** Intervals 1 to 3 are out (caps 1, 3, and 5 hours). Interval 4 (cap 7 hours) is the smallest allowed, giving 5,400 thumbnails. Intervals 5 to 10 also work.
* **A 45-second vertical short at interval 1.** 45 portrait tiles of 160 x 256 px, laid out in 5 columns by 9 rows.

\


## What you receive

Three files per interval, all keyed by the same playback ID and `interval` value.

### The image

`advanced-spritesheet.jpg?interval=N` is one JPEG. Thumbnails run left to right, then down, in playback order. Columns are chosen from the thumbnail count: at least 5, at most 64 for landscape or 102 for portrait, so the sheet stays within roughly 16,384 px on either side. The image is JPEG only, with no width, height, or crop options.

### Serve previews in an HTML5 player

`advanced-spritesheet.vtt?interval=N` is a standard thumbnail track. Each cue is exactly `interval` seconds long and points at a rectangle in the image, so you can hand it to any player that supports WebVTT thumbnail preview tracks.

**`WEBVTT`**

```text WEBVTT
WEBVTT

00:00:00.000 --> 00:00:03.000
https://images.fastpix.com/{PLAYBACK_ID}/advanced-spritesheet.jpg?interval=3#xywh=0,0,256,160

00:00:03.000 --> 00:00:06.000
https://images.fastpix.com/{PLAYBACK_ID}/advanced-spritesheet.jpg?interval=3#xywh=256,0,256,160
```

### Build a custom scrubber

`advanced-spritesheet.json?interval=N` has the same shape as the standard `spritesheet.json` plus an `interval` field. Use it when you render your own timeline UI and need direct access to tile coordinates and timing.

```json
{
  "url": "https://images.fastpix.com/{PLAYBACK_ID}/advanced-spritesheet.jpg?interval=3",
  "tile_width": 256,
  "tile_height": 160,
  "duration": 1288.0,
  "interval": 3,
  "tiles": [
    { "start": 0, "x": 0,   "y": 0 },
    { "start": 3, "x": 256, "y": 0 },
    { "start": 6, "x": 512, "y": 0 }
  ]
}
```

| Field                       | Meaning                                                                                                        |
| --------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `url`                       | The image URL, including `interval` and the token if one was supplied.                                         |
| `tile_width`, `tile_height` | 256 x 160 (landscape) or 160 x 256 (portrait).                                                                 |
| `duration`                  | Video duration in seconds, as reported by the HLS stream.                                                      |
| `interval`                  | Seconds between thumbnails, 1 to 10.                                                                           |
| `tiles[]`                   | One entry per thumbnail in playback order. `start` is its time in seconds; `x` and `y` locate it in the image. |

The `.vtt` and `.json` responses are cacheable for 24 hours, so CDNs and browsers keep them for a day. The in-progress `202` response is never cached.

\


## Serve private and DRM media

All three policies work. Public playback IDs need nothing extra.

* **Private media:** append `&token=<playback JWT>` to all three URLs.
* **DRM media:** append `&token=<DRM JWT>`, the same token used on the DRM stream URL, to all three, including the image.

Without a valid token, each URL returns `401`. For DRM, note that the standard `spritesheet.jpg` still serves without a token, but advanced sheets are token-gated on the image too. See [Generate JWTs for secure media](/docs/video-security/generate-jwts-for-secure-media) and [Set up DRM encryption](/docs/video-security/set-up-drm-encryption).

One sheet is stored per media and interval, so a media with several playback IDs shares the same generated sheets. Requesting interval 3 through one playback ID makes it ready for all of them.

\


## Support by media type

Advanced spritesheets are a feature of ready on-demand video. The service resolves the playback ID to a media record and checks its status, whether it has a video track, and its duration.

| Media type                                           | Supported             | Notes                                                                                            |
| ---------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------ |
| Uploaded video (file upload)                         | Yes                   | Once processing finishes and the media status is `ready`.                                        |
| Video ingested from a URL                            | Yes                   | Same as upload.                                                                                  |
| Clip created from another media                      | Yes                   | A clip is an ordinary on-demand media with its own playback ID and duration.                     |
| Live stream recording                                | Yes, on the recording | When a live stream ends, its recording becomes an on-demand media. Use that media's playback ID. |
| Live stream (in progress)                            | No                    | A live playback ID has no finite duration and does not resolve to an on-demand media.            |
| Audio-only media                                     | No                    | Rejected with `422`. The dashboard hides the Thumbnails section for these.                       |
| Media still processing or errored                    | Not yet               | Becomes available when the status reaches `ready`.                                               |
| Video shorter than 1 second or with unknown duration | No                    | No sheet can be generated.                                                                       |
| Video longer than 8 hours                            | No                    | No interval can cover it.                                                                        |

\


## Limits

| Limit                | Value                                                                                                                 |
| -------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Interval range       | Whole seconds, 1 to 10. Decimals and out-of-range values are rejected.                                                |
| Default interval     | 10 seconds when omitted                                                                                               |
| Minimum video length | The interval itself. A 5-second video cannot have a 6-second sheet.                                                   |
| Maximum video length | 8 hours (28,800 s)                                                                                                    |
| Sheets per media     | 10 (one per interval). Each interval is generated once and reused.                                                    |
| Image format         | JPEG only (`.jpg` or `.jpeg`). No PNG or WebP.                                                                        |
| Tile size            | 256 x 160 px landscape, 160 x 256 px portrait. Not configurable.                                                      |
| Maximum sheet size   | Roughly 16,384 px on either side, inside the texture limit of browsers and mobile GPUs.                               |
| Generation time      | Typically 30 seconds to 2 minutes. A job with no result after 10 minutes is marked failed and can be requested again. |
| Regenerate or delete | Not available. A ready interval cannot be forced to regenerate or removed.                                            |

The standard spritesheet, single thumbnails, and GIF clips keep their existing behavior and limits.

\


## Errors and troubleshooting

| Code | When                                                                                                                                                           | What to do                                                                                   |
| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| 200  | Image, VTT, or JSON served                                                                                                                                     | Nothing.                                                                                     |
| 202  | Image requested before generation finished                                                                                                                     | Wait and retry. The response is a JSON body, not the image.                                  |
| 400  | Playback ID is not a valid UUID, or the extension is not `.jpg` or `.jpeg`                                                                                     | Fix the URL.                                                                                 |
| 401  | Private or DRM media requested without a valid token                                                                                                           | Append a signed playback JWT (private) or DRM JWT (DRM) to the URL.                          |
| 404  | Unknown playback ID, or no media behind it                                                                                                                     | Check the ID.                                                                                |
| 422  | `interval` not a whole number 1 to 10; video shorter than the interval; video too long for the interval; video over 8 hours; media not ready; audio-only media | Read the error description. It names the minimum usable interval when the video is too long. |
| 503  | Transcode service unreachable, or storage temporarily unavailable                                                                                              | Retry later. A failed interval can be requested again.                                       |

\


#### Frequently asked questions

That is the `202` in-progress response. The sheet was not generated yet, and fetching it started the job. Retry after a minute, or request the interval through the dashboard first.

The video is longer than 1 hour, which is the most an interval of 1 can cover. The slider shows the smallest interval that works for the video.

That is expected. Advanced sheets require the DRM token on the image too, while the standard sheet was left open for existing integrations. Append `&token=<DRM JWT>` to the advanced URL.

No. The cue count is `floor(duration / interval)`, so a 65-second video at a 10-second interval has 6 cues, not 7. The final partial interval has no thumbnail.

Not today. Each interval is generated once per media and reused.

\


## What's next

* Add automatic previews to every video: [Create timeline hover thumbnails](/docs/video-on-demand/create-timeline-hovers-from-a-video).
* Secure previews for gated content: [Generate JWTs for secure media](/docs/video-security/generate-jwts-for-secure-media).
* Make a shorter asset to preview: [Clip and trim videos](/docs/video-on-demand/clip-and-trim-videos).