3.1 KiB
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.probewhen caller omitsduration. - Frame count is capped at
columns × rowsand atfloor(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}plusvideo_thumbnails.sprite_sheet.frames{format}. AbortSignalpropagated through every call; aborts surface asVIDEO_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 SpriteSheetGeneratorconstructor(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.