Skip to Content
API ReferenceMedia Operations

Media Operations

Seven static methods for the everyday changes to a single file: trim it, speed it up, play it backwards, make a GIF, crop it, rotate it, take the sound out. All are static: no project instance required.

Every operation writes a new file and leaves the input alone. Video output is always the same web-safe MP4 the transcode() web-mp4 preset writes: H.264 high/4.1, yuv420p, even dimensions, HDR retagged as SDR, AAC stereo, +faststart.

Every operation runs under the same hardening as transcode(): spawn with no shell, SIGKILL-backed timeout, AbortSignal support, an output size cap, and partial-output cleanup on failure. Failures throw TranscodeError with the same code discriminators, plus INPUT_TOO_LONG where an operation has a length limit.

Rotated phone video (a 1080×1920 portrait clip stored as 1920×1080 with a rotation flag) is turned upright before any filter runs. Crop rectangles and rotations are measured on the picture as it is displayed, and the output carries no rotation flag.

These options are shared by every operation below:

OptionTypeDefaultDescription
outputPathstring—.mp4 for video operations (.gif for toGif())
crfnumber23x264 quality, integer in [0, 51]
maxOutputBytesnumber524288000Maps to ffmpeg -fs (500 MB)
timeoutMsnumber300000Hard timeout, SIGKILL-backed
threadsnumber2Maps to ffmpeg -threads
onProgress(pct) => void—0–99 during encode, 100 on success
signalAbortSignal—Cancel; rejects with code: "ABORTED"

SIMPLEFFMPEG.trim(inputPath, options)

Keep [start, end] of a file. A .mp4 output is re-encoded, so the cut is frame-accurate. An audio output (.mp3, .m4a, .aac, .wav, .flac, .ogg, .opus) trims the sound only, from an audio file or a video’s soundtrack, with a micro-fade at each cut so it never clicks.

await SIMPLEFFMPEG.trim("./interview.mp4", { outputPath: "./answer.mp4", start: 12.4, end: 31, }); // Just the soundtrack of the same range await SIMPLEFFMPEG.trim("./interview.mp4", { outputPath: "./answer.m4a", start: 12.4, end: 31, });
OptionTypeDefaultDescription
startnumber—Start, in seconds
endnumber—End, in seconds; clamped to the input’s length
fadeMsnumber5Audio output only: micro-fade at each cut

SIMPLEFFMPEG.changeSpeed(inputPath, options)

Speed a video up or slow it down, with its audio. The audio uses the same atempo time-stretch as audioTempo(), so voices keep their pitch.

await SIMPLEFFMPEG.changeSpeed("./pour.mp4", { outputPath: "./pour-slowmo.mp4", speed: 0.5, });
OptionTypeDefaultDescription
speednumber—Factor in [0.25, 4]; 2 is twice as fast

SIMPLEFFMPEG.reverse(inputPath, options)

Play a video backwards, with its audio reversed too.

await SIMPLEFFMPEG.reverse("./splash.mp4", { outputPath: "./splash-rewind.mp4" });
OptionTypeDefaultDescription
maxMemoryBytesnumber1073741824Refuse clips whose decoded frames are estimated above this

ffmpeg’s reverse filter holds every decoded frame in memory. A clip past maxMemoryBytes is refused up front with code: "INPUT_TOO_LONG", and the message names the longest length that fits at that size. At the 1 GiB default that is about 11 s of 1080p30, or 25 s of 720p30. Trim first for longer clips.


SIMPLEFFMPEG.toGif(inputPath, options)

Make an animated, looping GIF from a video segment. The palette is built from the clip itself, so the colours hold up instead of collapsing into the default 256-colour dither.

await SIMPLEFFMPEG.toGif("./clip.mp4", { outputPath: "./reaction.gif", start: 1.5, duration: 3, width: 360, });
OptionTypeDefaultDescription
startnumber0Start, in seconds
durationnumberto the endLength, in seconds
fpsnumber12Frame rate, in (0, 50]
widthnumber480Output width; never upscales; height keeps the aspect
maxDurationSecnumber30Longer segments are refused with code: "INPUT_TOO_LONG"

SIMPLEFFMPEG.crop(inputPath, options)

Crop a video to a rectangle. Centered unless x/y are given. Odd sizes are rounded down to even for the encoder.

// A centered 9:16 slice of a 1920x1080 clip await SIMPLEFFMPEG.crop("./wide.mp4", { outputPath: "./tall.mp4", width: 608, height: 1080, });
OptionTypeDefaultDescription
width / heightnumber—Crop size in pixels
x / ynumbercenteredTop-left corner in pixels

A rectangle that does not fit the picture throws SimpleffmpegError before ffmpeg runs.


SIMPLEFFMPEG.rotate(inputPath, options)

Rotate a video clockwise by a quarter or half turn, relative to how it is displayed.

await SIMPLEFFMPEG.rotate("./sideways.mp4", { outputPath: "./upright.mp4", degrees: 90 });
OptionTypeDefaultDescription
degrees90 | 180 | 270 | -90—Clockwise; -90 is a quarter turn counter-clockwise

SIMPLEFFMPEG.mute(inputPath, options)

Remove a video’s sound. A web-safe input keeps its picture byte for byte (stream copy, near-instant); anything else is re-encoded to the web-safe MP4.

await SIMPLEFFMPEG.mute("./clip.mp4", { outputPath: "./clip-silent.mp4" });

Leveling a video’s sound

normalizeLoudness() takes keepVideo: true to level a video’s audio and keep its picture, writing an MP4:

await SIMPLEFFMPEG.normalizeLoudness("./interview.mp4", { outputPath: "./interview-leveled.mp4", keepVideo: true, });
Last updated on