Skip to content

Trickplay Thumbnails ​

Since: 0.11.0

TL;DR ​

Trickplay provides thumbnail seek previews — a grid of preview images at regular intervals that allow you to visually scrub through a video to find a specific scene. When enabled, Phlix generates thumbnail grid images (BIF format) during transcoding, and clients can request specific thumbnails via the trickplay API.

What is Trickplay? ​

Trickplay thumbnails (also called "thumbnail seek" or "preview thumbnails") are still images extracted from a video at fixed intervals. Instead of just showing a progress bar, clients display a grid of thumbnails that:

  • Visual preview — see what's in the video at each point
  • Quick navigation — click a thumbnail to seek to that position
  • Resume support — visually identify where you left off

Phlix generates BIF (Bitmap Index Format) thumbnail grids using FFmpeg and serves them via a dedicated API endpoint.

How It Works ​

Generation ​

When a video is transcoded, the TrickplayGenerator class:

  1. Probes the video duration using FFprobe
  2. Extracts frames at configurable intervals (default: every 10 seconds)
  3. Assembles grids — each grid contains 8×4 = 32 thumbnails (default)
  4. Generates index — BIF XML maps each thumbnail to byte offsets

Output Files ​

For a transcode job with ID abc123, the following files are created:

{trickplay_dir}/trickplay/abc123/
├── bif_00.jpg        # First grid image (thumbnails 0-31)
├── bif_01.jpg        # Second grid image (thumbnails 32-63)
├── bif_02.jpg        # Third grid image (thumbnails 64-95)
└── index.xml         # BIF index mapping byte offsets

BIF Index Format ​

xml
<ThumbList>
  <Thumbs>
    <Thumb index="0" time="0" offset="0" length="4096"/>
    <Thumb index="1" time="10" offset="4096" length="4096"/>
    <Thumb index="2" time="20" offset="8192" length="4096"/>
    <!-- ... -->
  </Thumbs>
</ThumbList>

Each <Thumb> entry contains:

  • index — thumbnail number
  • time — timestamp in seconds
  • offset — byte offset within the grid images
  • length — size of the thumbnail within the grid

API Endpoints ​

Trickplay thumbnails are served via two HTTP endpoints:

GET /trickplay/{jobId}/thumb-{index}.jpg ​

Returns a thumbnail grid image.

Parameters:

  • jobId (path) — Transcode job identifier
  • index (path) — Grid image index (0, 1, 2, ...)

Response:

HTTP/1.1 200 OK
Content-Type: image/jpeg
Content-Length: 4096
Cache-Control: public, max-age=86400

[binary image data]

Errors:

  • 404 Not Found — Trickplay not available for this job

GET /trickplay/{jobId}/index.xml ​

Returns the BIF index XML for mapping thumbnails to byte offsets.

Parameters:

  • jobId (path) — Transcode job identifier

Response:

HTTP/1.1 200 OK
Content-Type: application/xml
Content-Length: 1024
Cache-Control: public, max-age=86400

<?xml version="1.0" encoding="UTF-8"?>
<ThumbList>
  ...
</ThumbList>

Configuration ​

TrickplayConfig ​

The TrickplayConfig value object encapsulates all settings:

ParameterDefaultDescription
interval_seconds10Time between thumbnails
grid_columns8Thumbnails per row in grid
grid_rows4Rows per grid image
thumb_width160Width of each thumbnail in pixels
thumb_height90Height of each thumbnail in pixels
image_formatjpegImage format: jpeg or png
jpeg_quality72JPEG quality (1-100)

Integration with StreamManager ​

To enable trickplay generation during transcoding:

php
use Phlix\Media\Streaming\StreamManager;
use Phlix\Media\Streaming\Trickplay\TrickplayGenerator;
use Phlix\Media\Streaming\Trickplay\TrickplayController;
use Phlix\Media\Streaming\Trickplay\TrickplayConfig;

// Create generator and controller
$generator = new TrickplayGenerator($ffmpegRunner, '/var/media');
$controller = new TrickplayController('/var/media', 'https://phlix.example.com');

// Wire into StreamManager
$streamManager->setTrickplay($generator, $controller);

// Generate trickplay for a transcode job
$result = $streamManager->generateTrickplay($jobId, $inputPath, new TrickplayConfig(
    interval_seconds: 10,
    grid_columns: 8,
    grid_rows: 4,
));

Grid Dimensions ​

The total grid image dimensions are:

  • Width: grid_columns × thumb_width (default: 8 × 160 = 1280px)
  • Height: grid_rows × thumb_height (default: 4 × 90 = 360px)

Thumbnails Per Grid ​

thumbnails_per_grid = grid_columns × grid_rows
# Default: 8 × 4 = 32 thumbnails per grid image

Grid Count Estimation ​

For a 2-hour movie (7200 seconds) with 10-second intervals:

thumbnail_count = ceil(7200 / 10) = 720 thumbnails
grid_count = ceil(720 / 32) = 23 grid images

Client Integration ​

Clients like the Phlix web player use trickplay as follows:

  1. During playback initialization, check if trickplay exists:

    GET /trickplay/{jobId}/index.xml
  2. Display thumbnail strip by rendering grid images:

    GET /trickplay/{jobId}/thumb-0.jpg
    GET /trickplay/{jobId}/thumb-1.jpg
    ...
  3. On user interaction, use the BIF index to determine which thumbnail corresponds to a seek position, then seek to that time.

Implementation Details ​

FFmpeg Frame Extraction ​

Individual frames are extracted using FFmpeg:

bash
ffmpeg -y -hide_banner -loglevel error \
  -i input.mkv \
  -ss 0 -vframes 1 -q:v 2 -f image2 frame_00000.jpg \
  -ss 10 -vframes 1 -q:v 2 -f image2 frame_00001.jpg \
  ...

Grid Assembly ​

Thumbnails are assembled into a grid using FFmpeg's tile filter:

bash
ffmpeg -y -hide_banner -loglevel error \
  -i frame_00000.jpg \
  -i frame_00001.jpg \
  ... \
  -filter_complex "tile=8x4:margin=2:padding=3" \
  -q:v 2 \
  bif_00.jpg

Troubleshooting ​

Trickplay Endpoint Returns 404 ​

  1. Check if trickplay was generated — trickplay is only created when explicitly generated during transcoding
  2. Verify jobId — ensure the jobId matches an existing transcode job
  3. Check file permissions — the trickplay directory must be readable by the web server

Thumbnails Not Loading ​

  1. Check grid index range — ensure the index is within the number of grid images generated
  2. Verify image format — the endpoint checks for both .jpg and .png files
  3. Check Content-Type header — should be image/jpeg or image/png

Poor Quality Thumbnails ​

  1. Increase JPEG quality in TrickplayConfig (higher = better quality, larger files)
  2. Use PNG format for lossless thumbnails (larger file size)
  3. Adjust thumbnail dimensions — larger dimensions preserve more detail

Generation Slow ​

  1. Increase interval — fewer thumbnails = faster generation
  2. Use hardware acceleration — ensure FFmpeg is using GPU when available
  3. Reduce grid count — smaller images (fewer rows/columns) process faster

See Also ​

BSD-3-Clause