Docs / Animation & video

Animation & video v0.2.0

Animated images and videos behave differently. An animated image stays animated unless you say otherwise. A video gives you a single still frame, and only turns into an animated clip when anim includes a frame, timing, loop or stride setting.

/spinner.gif?w=240&f=webp
/intro.mp4?t=5.25&w=1280&f=webp
/intro.mp4?t=5&anim=frames:36|fps:12&f=webp

Only WebP and GIF can hold more than one frame. Ask for f=webp or f=gif if you need the result to move; JPEG, PNG, AVIF and JXL give you the first selected frame. Keep in mind that f=auto may pick a still-only format based on the browser’s Accept header.

Animated images

Animated GIF and WebP, AVIF and HEIC sequences, and multi-page TIFFs stay animated with no anim parameter at all, keeping their original frame delays and loop count. Multi-page documents rendered to an image can become an animation too.

# Keep the animation, resize every frame.
/loader.gif?w=320&f=webp

# Start at the third frame.
/loader.gif?page=3&f=webp

# Just one still frame.
/loader.gif?anim=off&f=png

For an animated source, page / pages picks the starting frame; only its first value matters, and frame counting starts from there. APNG is the odd one out: the PNG loader only reads its first frame.

Crop, sizing, filters and the watermark are applied to every frame that’s kept. Smart gravity on the top-level crop falls back to center, while crop=g:attention or g:entropy picks a region separately on each frame.

The anim parameter

Use anim or animate, with case-sensitive key:value pairs joined by |:

/loader.gif?anim=frames:24|stride:2|fps:15|loop:0&f=webp
frames

Keeps at most this many frames from the starting frame. Anything below 1 also means every frame.

timing

Sets the delay between every frame. Can't be combined with fps.

fps

Same thing as a frame rate. Can't be combined with timing.

loop

How many times to repeat; 0 loops forever.

stride

Keeps every Nth source frame.

anim=off, anim=false, anim=no and anim=0 all flatten the result to one frame. An unknown key, a missing colon, stride:0, or using both timing and fps gets the request rejected. GIF stores delays in hundredths of a second, so timings that aren’t a multiple of 10 ms get rounded; WebP keeps them exact.

output.max_animation_frames caps how many frames an animated image can have. It’s 300 by default, and 0 removes the cap. Frames past the cap are never loaded, but every frame that is kept goes through the full pipeline, so both frame count and size affect how long a request takes.

Video frames & clips

Video needs FFmpeg. These extensions are recognised:

mp4 · webm · mkv · avi · av1 · 3gp · m4v · flv · mov · mpeg · mts · hevc

Extract one frame

Use t / time with seconds or an FFmpeg-style timecode. picturium seeks before decoding, so a timestamp near the end doesn’t mean decoding the whole video first.

/movie.mp4?t=5&f=jpeg
/movie.mp4?t=5.25&w=1280&f=webp
/movie.mp4?t=00:01:30&crop=ar:video|g:center&w=960&f=avif

Without t, picturium uses video.default_time, which is one second in. That skips most black or fading-in opening frames. If the video is shorter than that default, picturium tries again from the start. A t you set yourself isn’t retried: if it’s past the end, the request fails. page has no effect on video.

Extract an animated clip

Give anim at least one real setting and ask for WebP or GIF. t then becomes the start of the clip, frames the number of frames you get back, and timing or fps how often a frame is sampled.

# 48 frames at the default 12 fps, starting at 10 seconds.
/movie.mp4?t=10&anim=loop:0&f=webp

# 30 frames at 10 fps: a three-second clip.
/movie.mp4?t=10&anim=frames:30|fps:10|loop:0&f=webp

# Still 30 frames, but sampled five times less often: fifteen seconds of footage.
/movie.mp4?t=10&anim=frames:30|fps:10|stride:5&f=gif

On video, stride slows down the sampling instead of dropping frames afterwards. You get the same number of frames, spread over more footage. A bare anim= has no settings, so you still get one frame. A still-only format also gives you one frame, whatever anim says.

video.default_time

Where to take the frame from when t isn't set.

video.extraction_timeout

Time limit for grabbing one frame.

video.animation_timeout

Time limit for extracting a clip.

video.animation_frames

Clip length when anim doesn't set frames.

video.animation_fps

Sampling rate when anim sets neither timing nor fps.

video.max_animation_frames

Upper limit on frames in a video clip.

The clip is first extracted to a temporary lossless animated WebP, then goes through the same crop, sizing, filter, watermark, quality and encoding steps as any animated image. Long clips with frames close together mean decoding a lot of video and can be slow; samples far apart are fetched with separate seeks instead. The [video] config reference lists the defaults and timeouts, and Output format & quality covers the WebP and GIF encoder settings.