3.2 KiB
FluentFfmpegRunner
Purpose
Default FfmpegRunner implementation used by ThumbnailGenerator and
SpriteSheetGenerator when no other runner is injected. It wraps fluent-ffmpeg and pins
ffmpeg to the binary shipped by @ffmpeg-installer/ffmpeg, and ffprobe to
@ffprobe-installer/ffprobe, so the package works on any host without requiring system
ffmpeg/ffprobe to be on PATH. Every operation respects an optional AbortSignal by killing
the underlying child process and rejecting with VIDEO_THUMBNAILS.ABORTED.
Features
- Bundled ffmpeg + ffprobe binaries — zero system dependency.
- Override-friendly: pass
ffmpegPathand/orffprobePathto point at a custom binary. extractissues a single-frame ffmpeg pipeline with the canonical filter frombuildScaleFilterand quality frombuildQualityArgs.tileissues the canonicalfps=…,scale=…,tile=COLSxROWSsprite-sheet pipeline.probereturns a strictProbeResultwith duration, dimensions, codec, fps, bitrate.isAvailablespawnsffmpeg -versionand resolves totrueonly on exit code 0.- Every call honours
AbortSignal:command.kill("SIGKILL")on abort, then reject withABORTED.
Usage: Basic
import { FluentFfmpegRunner } from "@suaveplan/video-thumbnails/runner";
const runner = new FluentFfmpegRunner();
const ok = await runner.isAvailable();
Usage: Advanced
import { FluentFfmpegRunner } from "@suaveplan/video-thumbnails/runner";
const runner = new FluentFfmpegRunner({
ffmpegPath: "/usr/local/bin/ffmpeg-hwaccel",
ffprobePath: "/usr/local/bin/ffprobe-hwaccel",
});
const controller = new AbortController();
setTimeout(() => controller.abort(), 250);
try {
await runner.extract(
{
inputPath: "/data/big.mkv",
outputPath: "/tmp/thumb.jpg",
timestamp: "00:00:10",
width: 640,
height: 360,
fit: "cover",
format: "jpg",
quality: 80,
},
controller.signal,
);
} catch (error) {
// VideoThumbnailsError { code: "VIDEO_THUMBNAILS.ABORTED" } when aborted.
}
API Reference
class FluentFfmpegRunner implements FfmpegRunnerconstructor(options?: { ffmpegPath?: string; ffprobePath?: string })isAvailable(signal?): Promise<boolean>— exit code 0 fromffmpeg -version.extract(input, signal?): Promise<void>— single-frame extraction.tile(input, signal?): Promise<void>— N×M sprite-sheet render.probe(inputPath, signal?): Promise<ProbeResult>— ffprobe metadata.
Implementation Notes
run listens for end and error on the FfmpegCommand, tracks a settled flag so a late
abort cannot double-resolve, and attaches the abort listener with { once: true } to keep
event-emitter memory bounded. probe re-pins the ffprobe path on the module-level
fluent-ffmpeg singleton before each call because ffmpeg.ffprobe (the top-level helper)
does not consult per-instance state — without the re-pin the singleton would happily fall
back to system ffprobe. The probe failure paths split into two: a real ffprobe crash
(PROBE_FAILED) and a structurally invalid response (VIDEO_INVALID, raised when the file
has no video stream or a non-positive duration).