How to freeze frame a video: hold the last or any frame
Freeze a video's last frame with one tpad filter call, or hold any frame mid-clip as a still between two parts of the clip in a Timeline render.

To freeze frame a video, hold one frame on screen for a few seconds while the picture stops. For the last frame, FFmpeg's tpad filter does it: tpad=stop_mode=clone:stop_duration=3 adds three seconds of copies of the final frame. On a clip already hosted on Sume, that is one video filter call. For a freeze in the middle, pull that frame as a still with video frames and place it as its own slot between two parts of the clip in a Timeline 1.0 render.
The facts come from Sume's Video filter, Video frames, Audio detach, and Timeline 1.0 docs, the Sume API reference, and FFmpeg's ffmpeg tool, filters, and utilities documentation, read on 2026-09-27. Anything described as current behavior is read from Sume's code.
How do I freeze the last frame of a video?
Use FFmpeg's tpad filter. stop_mode=clone pads the end with clones of the last frame (the default, add, pads with solid-color frames), and stop_duration sets the length of the pad; a plain number is seconds. On your own computer, FFmpeg applies it with -vf while it re-encodes the file: ffmpeg -i clip.mp4 -vf tpad=stop_mode=clone:stop_duration=3 frozen.mp4.
On Sume, send the same filter as the filtergraph of POST /v1/video-filter; tpad is on Sume's filter allowlist today.
- The clip must already be your workspace's
media.sume.comartifact or asset, such as an earlier Sume job's output, and at most 300 seconds long. Sume has no public upload route for a file on your computer (which URLs each endpoint accepts).POST /v1/video-filter/checkvalidates the same body for free. - The server wraps your graph around the video stream, and the docs say the output inherits the source's audio. So the sound still ends where the clip's did, and the held seconds are silent.
start_mode=clonewithstart_durationholds the first frame instead. That delays the picture but not the audio, so keep it for clips whose sound you will replace.
curl -X POST https://api.sume.com/v1/video-filter \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: freeze-end-001" \
-d '{
"video_url": "https://media.sume.com/artifacts/artf_demo/clip.mp4",
"filtergraph": "tpad=stop_mode=clone:stop_duration=3"
}'How do I freeze a frame in the middle of a video?
Split the clip at the frame and hold a still of it between the two parts. That takes three calls:
POST /v1/video-frameswithat: [8]andformat: "png"returns a durable image of the instant at 8 seconds, at the source's size whenmax_edgeis omitted; read itsframes[].urlfromGET /v1/video-frames/:idonceresource_statusisready. It is unbilled, takes sources up to 300 seconds, and everyatvalue must be under the clip's duration.POST /v1/audio-detachreturns the clip's audio as a wav, the file a Timelineaudio.urlwants. In the current compiler a render's sound comes only from its spine and an optional soundtrack, never from the clips, so detaching is how the clip keeps its sound.POST /v1/timeline-1.0/rendertakes the wav as the spine and three slots: the clip up to the frame, the still (stills are static holds), and the clip again from a latersource_in. The default output is 1080×1920, so setoutputto the clip's size.
curl -X POST https://api.sume.com/v1/timeline-1.0/render \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: freeze-mid-001" \
-d '{
"audio": { "url": "https://media.sume.com/artifacts/artf_demo/clip.wav", "duration_seconds": 20 },
"output": { "width": 1920, "height": 1080 },
"video": [
{ "source_url": "https://media.sume.com/artifacts/artf_demo/clip.mp4", "start": 0, "duration": 8 },
{ "source_url": "https://media.sume.com/artifacts/artf_demo/frame-8s.png", "start": 8, "duration": 3 },
{ "source_url": "https://media.sume.com/artifacts/artf_demo/clip.mp4", "start": 11, "duration": 9, "source_in": 11 }
]
}'What happens to the sound during the freeze?
It keeps playing. The spine runs straight through, and even audio.parts[] slices join without silence at the seams, so the sound carries on under the still. That is why the last slot resumes at source_in: 11, not 8. The freeze covers three seconds of the clip, and picture and sound meet again in sync.
If the clip's sound doesn't matter, render with audio.mode: "silence" instead, which gives the output a silent track of duration_seconds. Then the freeze can add time: resume at source_in: 8 and set duration_seconds to 23. A soundtrack can lay music under the whole edit, as in add background music.
How do I hold the last frame inside a longer edit?
Make the clip's Timeline slot longer than the clip. Per the Sume API reference, render.pad_mode decides how a slot longer than its source is filled: freeze holds the last frame and loop replays the source. The default, auto, loops short sources instead of holding a long freeze, so send "render": { "pad_mode": "freeze" } when a slot should end on a held frame. The docs treat padded or looped short sources as soft warnings, not failures. Looping on purpose is covered in increase video length by looping.
What does each step cost, and what are the limits?
Video frames is unbilled. Every other step bills on its own, plus a 5.5% agent fee by default.
| Step | Call | Billing | Limits |
|---|---|---|---|
| Last-frame freeze | POST /v1/video-filter | Per encode job, rate in GET /v1/catalog; the check is free | Source ≤ 300 s |
| Frame still | POST /v1/video-frames | Unbilled | Source ≤ 300 s; each at in [0, duration) |
| Clip audio | POST /v1/audio-detach | Per job, rate in GET /v1/catalog | Source ≤ 1,800 s; output ≤ 900 s |
| Render | POST /v1/timeline-1.0/render | Reserves $0.10 per output minute and never charges more | Output 1–1,800 s; 1–200 slots, each ≥ 0.2 s |
Sources
Related posts
More in Media tools
- How to generate an SRT file from a video
To generate an SRT file from a video, transcribe it with timestamps and write each timed sentence as a numbered block. Sume's STT returns timed JSON.
- Hard subtitles vs soft subtitles: what's the difference?
Hard subtitles are burned into the picture and always show; soft subtitles are a separate track viewers can turn off. When to use each, and how.
- How to check a video's bitrate from its size and length
Check a video's average bitrate: size in bytes × 8 ÷ length in seconds. Sume's free probe returns both numbers, size_bytes and duration_seconds.
- Instagram story ad size: 9:16 specs, plus Facebook Stories
Meta recommends 9:16 at 1440×2560 for Instagram and Facebook Stories ads. Lengths that play in full, safe zones, and how to make one with Sume.
Written by Sume