Files
skills/docs/media/video/video-thumbnails/src/sprite-sheet/sprite-sheet.md
2026-05-29 08:20:56 +01:00

3.1 KiB
Raw Blame History

SpriteSheetGenerator

(no submodules)

Purpose

SpriteSheetGenerator renders an N×M grid of thumbnails into a single image using ffmpeg's tile filter. A sprite sheet is the canonical artefact for video scrubbers and timeline previews — one HTTP fetch, one decode, then arbitrary in-page hovers slide a background- position. The generator delegates the actual ffmpeg invocation to an injectable FfmpegRunner (default: FluentFfmpegRunner with bundled ffmpeg/ffprobe binaries) and auto-detects video duration via the runner's probe when the caller does not pass one explicitly.

Features

  • Configurable grid: columns, rows, thumbnailWidth, thumbnailHeight, interval, format.
  • Auto-detection of video duration via runner.probe when caller omits duration.
  • Frame count is capped at columns × rows and at floor(duration / interval) — whichever is smaller — so short videos do not produce padded grids.
  • Zod boundary validation with code-specific failures (INVALID_DIMENSIONS, FORMAT_UNSUPPORTED, INVALID_OPTIONS).
  • OTel: video_thumbnails.sprite_sheet.duration_ms{outcome,format} plus video_thumbnails.sprite_sheet.frames{format}.
  • AbortSignal propagated through every call; aborts surface as VIDEO_THUMBNAILS.ABORTED.

Usage: Basic

import { SpriteSheetGenerator } from "@suaveplan/video-thumbnails/sprite-sheet";

const generator = new SpriteSheetGenerator();
const result = await generator.generate("/data/clip.mp4", "/tmp/sprite.jpg");
console.log(result.frameCount, result.columns, result.rows);

Usage: Advanced

import { SpriteSheetGenerator } from "@suaveplan/video-thumbnails/sprite-sheet";

const generator = new SpriteSheetGenerator({
    columns: 8,
    rows: 6,
    thumbnailWidth: 192,
    thumbnailHeight: 108,
    interval: 2,
    format: "jpg",
});

const controller = new AbortController();
const result = await generator.generate(
    "/data/long-movie.mp4",
    "/tmp/movie-sprite.jpg",
    7200,
    controller.signal,
);
// result.width === 8 * 192, result.height === 6 * 108, result.frameCount === 48

API Reference

  • class SpriteSheetGenerator
    • constructor(config?: SpriteSheetConfigInput, runner?: FfmpegRunner)
    • generate(inputPath, outputPath, duration?, signal?): Promise<SpriteSheetResult>

Throws VideoThumbnailsError on INVALID_DIMENSIONS, FORMAT_UNSUPPORTED, INVALID_OPTIONS, VIDEO_INVALID, EXTRACT_FAILED, PROBE_FAILED, or ABORTED.

Implementation Notes

rows is recomputed against the actual frameCount (rather than blindly using the configured upper bound) so a 5-second clip with a 10-frame grid does not produce four trailing black cells. The generator never directly invokes ffmpeg — every call routes through the supplied runner so consumers can swap in a hardware-accelerated or hosted variant without touching this class. OTel records before throwing on failure so dashboards distinguish counts from timings even on errors. duration is validated when passed explicitly: non-finite or non-positive values are rejected with VIDEO_INVALID, mirroring the probe path.