ffmpeg filter API: Sume's video filter allowlist and checks
Run allowlisted ffmpeg filters on a Sume-hosted clip with POST /v1/video-filter: the allowed names, filtergraph rules, the free check, and the encode settings.

Sume's ffmpeg filter API is POST /v1/video-filter: send one Sume-hosted clip and a filters-only filtergraph string, and the server checks every filter name against an allowlist, wraps the graph with its own input and output, and encodes a new MP4. You never send argv, codecs, or file paths, and POST /v1/video-filter/check validates the same body for free.
The facts below come from the Video filter docs and the Sume API reference, read on 2026-09-26. The docs name Sume's filter compiler as the home of the allowlist; the filter names and encoder settings here are read from it and describe how it works today.
Which ffmpeg filters are allowed?
The allowlist has 66 names in five groups. Each takes only inline options, with no file, font, model, command, or socket option, so nothing on it can read a path or reach a network.
Not on the list: trim and setpts (cut ranges with video trim), drawtext, subtitles, movie, lut3d, and anything that reads a file or a socket. An unknown name fails with invalid_filtergraph (unknown_filter), and the message names the token and lists the allowlist.
| Group | Allowed filters |
|---|---|
| Tone and color | eq, lutyuv, lutrgb, lut, hue, colorbalance, colorchannelmixer, colorlevels, colortemperature, colorcontrast, colorcorrect, colorize, colorhold, colorkey, chromakey, chromahold, negate, monochrome, exposure, normalize, histeq, vibrance, swapuv, shuffleplanes, despill, vignette |
| Blur, sharpen, noise | unsharp, boxblur, gblur, avgblur, smartblur, median, noise, deband, deflicker, dilation, erosion, sobel, edgedetect, cas |
| Geometry | crop, scale, pad, hflip, vflip, transpose, rotate, setsar, setdar, zoompan, lenscorrection, perspective |
| Time | fps, tpad, fade, framerate, tblend, tmix |
| Compositing (internal labels only) | split, overlay, hstack, vstack, blend, drawbox, drawgrid, format |
What does a valid filtergraph look like?
A filtergraph here is filters only. The server supplies the input from video_url as [0:v] and maps the last filter to the encoder, so the graph follows these rules:
- Start and end with a filter, not a label. Internal labels such as
split[a][b]are fine; a stream specifier such as[0:v]is refused. - At most 2,048 characters and 32 named filters. The graph runs after any
ops[](up to 8dimorcropops). - No whitespace inside a filter: write options as
name=key=value:key=value. - None of
://, a backslash, a backtick,$, a double quote,&, a tab, or a line break. - No ffmpeg argv fields in the body: keys such as
vf,filter,ffmpeg,cmd,codec,crf, or-ireturn400 ffmpeg_fields_rejected.
How do I check a filtergraph before I pay?
Send the same body to POST /v1/video-filter/check, or call video_filter with check_only: true on the hosted MCP server. It runs the encode's schema, allowlist, and source checks without creating a job or reserving credits; Trim, filter, or detach audio covers the rest of its contract. The response has these fields:
object: video_filter_check,valid, andencode: "not_run".diagnostics[]: each withseverity(error),code, andmessage, plus optionalfield,next_action, anddetails.program: the normalizedvideo_url,ops,filtergraph,filter_count, andfilters(compiled names only, no argv), ornullwhen the body itself was rejected.estimatewhen valid (currency,usd_micros,usd_cents,label), andnext_action:submit_video_filterorfix_program_and_recheck.
curl -X POST https://api.sume.com/v1/video-filter/check \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://media.sume.com/artifacts/artf_demo/talk.mp4",
"filtergraph": "eq=contrast=1.2:saturation=0.8,gblur=sigma=2"
}'How does Sume encode the filtered video?
Submit the checked body to POST /v1/video-filter with an Idempotency-Key, then poll the job envelope as for any media tool. The result (kind: video_filter) carries the new video_url and the compiled filters[], and the output keeps the source's geometry, frame rate, and audio unless the program changes them.
The encoder is not configurable. Today it runs with these settings:
- Video:
libx264, presetveryfast, CRF 20,yuv420p, with the keyframe interval set to one second of the source's frame rate when that rate is known. - Audio: re-encoded as AAC at 192 kbps, outside the filtergraph, which only sees the video stream. A source with no audio track is still accepted, with a
filter_source_has_no_audiowarning. - Container: MP4 with
+faststart. - HDR sources (PQ or HLG) are refused with
hdr_source_unsupported, and a pixel format outside the YUV family withunsupported_pixel_format.
What are the limits and costs?
Each encode is priced per job, at the rate GET /v1/catalog lists, and the check is free. There is no provider inference, only worker ffmpeg.
- One Sume-hosted clip per job, at most 300 seconds long. A longer source fails with
output_duration_exceeded, and one past the timeline download budget withsource_too_large. - For a 9:16 reframe built from
cropandscale, see Convert a landscape video to vertical. For size and frame-rate changes, see Change a video's frame rate or resolution.
Sources
Related posts
Written by Sume