Thumbnails
Transcodely can generate thumbnails from your video alongside transcoding outputs. Thumbnails are configured at the job level and support multiple extraction modes — from a single poster frame to sprite sheets for video scrubbing.
Thumbnails are configured in the thumbnails array of a Create Job request. Each job supports up to 5 thumbnail specifications.
Thumbnails are free — they’re bundled with the transcoding cost and add no feature multiplier. See Pricing for details.
The ThumbnailSpec object
| Attribute | Type | Required | Description |
|---|---|---|---|
mode | enum | Yes | Extraction mode. One of: single, interval, sprite, timestamps, animated. See Modes. |
format | enum | No | Image format. One of: jpeg, png, webp. Default: jpeg. See Formats. |
width | integer | No | Output width in pixels (16—3840). If only width is set, height is calculated to maintain aspect ratio. |
height | integer | No | Output height in pixels (16—2160). If only height is set, width is calculated to maintain aspect ratio. |
quality | integer | No | Image quality (1—100). Default: 80. Applies to JPEG and WebP. Not allowed for PNG — setting quality with format: "png" is rejected as a validation error (PNG is lossless). |
timestamp | number | No | Time in seconds to extract the frame. Only valid for single mode. When omitted, the worker smart-selects a representative non-black frame from the opening of the video (deterministic per input); an explicit value — including 0 — extracts exactly that frame. |
interval_seconds | number | No | Interval between frames in seconds (0.5—300). Optional for interval and sprite modes; defaults to 10 if unset. Forbidden for other modes. |
timestamps | array of numbers | No | Specific timestamps in seconds to extract. Required for timestamps mode. |
sprite_columns | integer | No | Number of columns in the sprite sheet (1—20). Only valid for sprite mode. Default: 10. |
duration_seconds | number | No | Total length of each animated preview clip, in seconds (2—30). Only valid for animated mode. Defaults to 4 (applied worker-side). The animated WebP is hard-capped at 10 s — see Animated previews. |
fps | integer | No | Frames per second of the animated preview (8—15). Only valid for animated mode. Defaults to 12 (applied worker-side). |
start_offsets | array of numbers | No | Explicit clip start offsets in seconds from the source start (max 3, each >= 0). Only valid for animated mode. When set, these replace the default 25% / 50% / 75% sampling marks; the worker clamps each offset to the source duration. |
path_template | string | No | Per-thumbnail storage path override (max 512 chars). Supports {job_id}, {video_id}, {date}, {timestamp}, {uuid}, {format}, {thumb_index} (0-based), {thumb_time} (seconds), and {thumb_time_ms} (milliseconds). Precedence: this field, then the output origin’s path_template, then the default {job_id}/thumbnails/thumb_{thumb_index}. Must not start with / or contain .., and must reference a uniqueness token ({job_id}, {video_id}, or {uuid}). |
{
"mode": "single",
"format": "jpeg",
"width": 1280,
"height": 720,
"quality": 90,
"timestamp": 5.0
}Modes
Each thumbnail spec requires a mode that determines how frames are extracted from the video.
| Mode | API Value | Description | Output |
|---|---|---|---|
| Single | single | Extract a single frame — at a specific timestamp, or smart-selected when omitted. Use for poster images, social media thumbnails, or preview images. | One image file. |
| Interval | interval | Extract frames at regular intervals throughout the video. Use for storyboard generation or content review. | Multiple image files. |
| Sprite | sprite | Combine interval-extracted frames into a single sprite sheet image. Use for video scrubbing / seek preview in players. | One sprite sheet image + WebVTT file. |
| Timestamps | timestamps | Extract frames at specific timestamps. Use when you need frames at exact moments (scene changes, chapter markers). | Multiple image files. |
| Animated | animated | Generate short animated hover-preview loops for card / grid previews. By default produces both an animated WebP and a muted MP4 loop from the same samples. | Animated WebP + muted MP4 loop. See Animated previews. |
Formats
| Format | API Value | Best For | Notes |
|---|---|---|---|
| JPEG | jpeg | General use, poster images | Lossy compression. Smallest file size. quality parameter applies. Default. |
| PNG | png | Screenshots, UI overlays | Lossless compression. Larger files. Setting the quality parameter is rejected as a validation error. |
| WebP | webp | Web delivery | Lossy compression with better quality-to-size ratio than JPEG. quality parameter applies. Also the still-image format of the animated preview. |
jpeg and png are invalid for animated mode. Animated previews always emit a WebP loop (format: "webp") plus a muted MP4 loop; the MP4’s result carries the free-form format: "mp4" (it is not a ThumbnailFormat enum value). See Animated previews for the WebP 10-second cap.
Sprite sheets
Sprite sheets combine multiple thumbnails into a single image in a grid layout, paired with a WebVTT file that maps each thumbnail to its timecode. Video players use this for seek preview (showing a thumbnail when the user hovers over the progress bar).
sprite_columns controls the number of columns in the grid. Rows are calculated automatically based on the total number of frames and columns.
For a 2-minute video with interval_seconds: 10 and sprite_columns: 5:
- 12 frames extracted (one every 10 seconds)
- Grid: 5 columns x 3 rows (15 slots, 12 filled)
- Output: 1 sprite sheet image + 1 WebVTT file
The generated WebVTT file maps each frame to its position in the sprite sheet:
WEBVTT
00:00:00.000 --> 00:00:10.000
sprite.jpg#xywh=0,0,320,180
00:00:10.000 --> 00:00:20.000
sprite.jpg#xywh=320,0,320,180
00:00:20.000 --> 00:00:30.000
sprite.jpg#xywh=640,0,320,180Animated previews
Animated mode produces short hover-preview loops for card and grid UIs. Like every thumbnail mode it is free — it adds no cost to the job.
By default the worker produces both an animated WebP and a muted MP4 loop from the same samples, so a consumer can pick whichever its surface supports. Set format: "webp" to emit only the WebP.
Deterministic sampling. Unless start_offsets is set, clips are taken at fixed 25% / 50% / 75% marks of the source duration — no scene detection. Provide up to three start_offsets (seconds from the source start) to override those marks; the worker clamps each to the source duration.
Smart defaults (applied worker-side; the API stores exactly what you send): 4 s duration_seconds, 12 fps, 320 px width.
The 10-second WebP cap. The animated WebP is hard-capped at 10 seconds. When duration_seconds exceeds 10, the WebP is skipped and the output is MP4-only — documented behavior, not an error. The exception: if you set format: "webp" explicitly, a duration_seconds above 10 is rejected at job creation instead.
Valid config for this mode: width, height, quality (WebP encode quality), duration_seconds, fps, start_offsets, and path_template. The single / interval / sprite / timestamps fields (timestamp, interval_seconds, timestamps, sprite_columns) are not valid here.
{
"mode": "animated",
"width": 320,
"duration_seconds": 4,
"fps": 12,
"start_offsets": [3.0, 7.5, 12.0]
}Results surface in thumbnail_results with mode: "animated" — one entry with format: "webp" (the WebP loop) and one with format: "mp4" (the muted MP4 loop). See Thumbnail results.
Examples
Single poster frame
Extract a poster image at the 5-second mark.
{
"thumbnails": [
{
"mode": "single",
"format": "jpeg",
"width": 1280,
"height": 720,
"quality": 90,
"timestamp": 5.0
}
]
}Interval thumbnails
Extract a thumbnail every 30 seconds for content review.
{
"thumbnails": [
{
"mode": "interval",
"format": "jpeg",
"width": 640,
"height": 360,
"quality": 80,
"interval_seconds": 30
}
]
}Sprite sheet for video scrubbing
Generate a sprite sheet for seek preview in your video player.
{
"thumbnails": [
{
"mode": "sprite",
"format": "jpeg",
"width": 320,
"height": 180,
"quality": 70,
"interval_seconds": 10,
"sprite_columns": 10
}
]
}Specific timestamps
Extract frames at chapter markers or scene changes.
{
"thumbnails": [
{
"mode": "timestamps",
"format": "webp",
"width": 1920,
"height": 1080,
"quality": 85,
"timestamps": [0, 15.5, 45.0, 120.0, 300.0, 600.0]
}
]
}Animated hover previews
Generate a 320 px hover-preview loop — an animated WebP plus a muted MP4 — sampled at custom offsets.
{
"thumbnails": [
{
"mode": "animated",
"width": 320,
"duration_seconds": 4,
"fps": 12,
"start_offsets": [3.0, 7.5, 12.0]
}
]
}Multiple thumbnail specs in one job
Combine a poster frame and a sprite sheet in a single job.
{
"thumbnails": [
{
"mode": "single",
"format": "jpeg",
"width": 1920,
"height": 1080,
"quality": 95,
"timestamp": 10.0
},
{
"mode": "sprite",
"format": "jpeg",
"width": 320,
"height": 180,
"quality": 70,
"interval_seconds": 5,
"sprite_columns": 10
}
]
}Complete job example
A full Create Job request with HLS outputs, a poster frame, and a sprite sheet for seek preview.
- Transcodes the source into a single HLS output with a three-rung ABR ladder (1080p, 720p, 480p).
- Captures a 1280×720 JPEG poster frame at the 5-second mark.
- Builds a 320×180 JPEG sprite sheet every 10 seconds for scrubbing previews.
{
"input_url": "gs://my-bucket/uploads/video.mp4",
"output_origin_id": "ori_x9y8z7w6v5",
"outputs": [
{
"type": "hls",
"video": [
{"codec": "h264", "resolution": "1080p", "quality": "standard"},
{"codec": "h264", "resolution": "720p", "quality": "standard"},
{"codec": "h264", "resolution": "480p", "quality": "economy"}
]
}
],
"thumbnails": [
{
"mode": "single",
"format": "jpeg",
"width": 1280,
"height": 720,
"quality": 90,
"timestamp": 5.0
},
{
"mode": "sprite",
"format": "jpeg",
"width": 320,
"height": 180,
"quality": 70,
"interval_seconds": 10,
"sprite_columns": 10
}
],
"priority": "standard"
}Thumbnail results
Generated thumbnails are surfaced on the Job response in the thumbnail_results array, populated once the job completes. Each entry mirrors how output_url surfaces rendition results — the worker builds the storage key and URL, and the API echoes them verbatim.
A single spec can yield several results: interval and timestamps modes produce one entry per frame, sprite mode produces the sprite sheet image plus a .vtt sidecar (reported with format: "vtt"), and animated mode produces the animated WebP (format: "webp") plus the muted MP4 loop (format: "mp4"). Correlate each result back to the spec that produced it via mode + index.
| Attribute | Type | Description |
|---|---|---|
storage_key | string | Storage key relative to the output origin (e.g. job_a1b2c3d4e5f6/thumbnails/thumb_0.jpg). Stable identifier for the file. |
url | string | Fully-qualified storage URL built by the worker (e.g. gs://bucket/prefix/job_a1b2c3d4e5f6/thumbnails/thumb_0.jpg). |
signed_url | string | null | Ready-to-fetch HTTPS URL for the same file, signed and time-limited. Managed-storage destinations only, on Get and Watch but never List, and it expires. The sprite mode’s .vtt sidecar is signed so that the sprite image its cues reference inherits the same authorization. See Signed asset URLs. |
mode | string | Generation mode that produced this file. One of: single, interval, sprite, timestamps, animated. |
format | string | File format: jpeg, png, or webp. The sprite sheet’s WebVTT sidecar uses vtt; the animated mode’s muted MP4 loop uses mp4 (a free-form format string, not a ThumbnailFormat enum value). |
width | integer | Pixel width. 0 when not applicable (e.g. the .vtt sidecar). |
height | integer | Pixel height. 0 when not applicable (e.g. the .vtt sidecar). |
index | integer | 0-based index within a multi-file spec (interval frames, sprite tiles). |
For a worked thumbnail_results payload, see the Job object response.
Validation rules
Transcodely validates thumbnail configuration at job creation time. The following constraints are enforced:
| Rule | Description |
|---|---|
| Maximum 5 specs | Each job supports up to 5 thumbnails entries. |
| Mode required | Every thumbnail spec must have a mode set. |
timestamp requires single | The timestamp field is only valid when mode is single. |
interval_seconds requires interval / sprite | The interval_seconds field is only valid when mode is interval or sprite. Optional within those modes — defaults to 10 when unset. |
timestamps required for timestamps mode | The timestamps array must be non-empty when mode is timestamps. |
sprite_columns requires sprite | The sprite_columns field is only valid when mode is sprite. |
duration_seconds / fps / start_offsets require animated | These three fields are only valid when mode is animated. |
quality forbidden for PNG | The quality field must not be set when format is png (PNG is lossless). |
jpeg / png forbidden for animated | Animated mode emits WebP + MP4 only; format: "jpeg" or format: "png" is rejected. |
webp + duration_seconds > 10 | Setting format: "webp" and a duration_seconds above 10 is rejected (the WebP is capped at 10 s). Without an explicit format, a duration above 10 s silently yields MP4-only instead. |
| Dimension range | width must be 16—3840. height must be 16—2160. |
| Quality range | quality must be 1—100. |
| Interval range | interval_seconds must be 0.5—300. |
| Sprite columns range | sprite_columns must be 1—20. |
| Animated duration range | duration_seconds must be 2—30. |
| Animated fps range | fps must be 8—15. |
| Animated start offsets | start_offsets accepts at most 3 entries, each >= 0. |
| Path template length | path_template must not exceed 512 characters, must not start with / or contain .., and must reference a {job_id}, {video_id}, or {uuid} token. |