Adjust video brightness, contrast, saturation by API: eq filter
Send eq=brightness=0.06:contrast=1.1:saturation=1.2 as the filtergraph of Sume video-filter. Ranges come from FFmpeg: brightness -1 to 1, saturation 0 to 3.

To change a clip's brightness, contrast or saturation by API, send an eq filter in the filtergraph field of Sume's video filter: eq=brightness=0.06:contrast=1.1:saturation=1.2. eq is on the filter allowlist, so the job returns a new MP4 and leaves the source alone. Check the string first with POST /v1/video-filter/check, which is free.
The option ranges below are from FFmpeg's eq entry, read 2026-10-02. The request shape and limits are from the video filter docs.
What are the eq options and their ranges?
FFmpeg's page gives: contrast -1000.0 to 1000.0, default 1; brightness -1.0 to 1.0, default 0; saturation 0.0 to 3.0, default 1; gamma 0.1 to 10, default 1. Small moves go a long way: start near brightness 0.05, contrast 1.1 and saturation 1.2, then compare stills.
How do I send it to Sume?
Required: video_url (a media.sume.com clip of 300 seconds or less) and a program: ops[], a filtergraph, or both. ops[] run first, then the graph. A filtergraph is filters only, up to 2,048 characters and 32 named filters, with no spaces inside a filter, no input or output labels, and no paths. Write options as name=key=value:key=value.
A filter name off the list fails as invalid_filtergraph with the allowed names in the message. Do not send vf or ffmpeg fields; those return ffmpeg_fields_rejected. The encode is $0.02 per job and the check is free.
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=brightness=0.06:contrast=1.1:saturation=1.2"
}'What can the check not tell me?
It validates schema, allowlist and the source, and returns next_action submit_video_filter or fix_program_and_recheck. A program that passes can still fail on the worker, for example on a bad expression, and that returns as a structured job error. The check cannot say if the look is right; pull a still with video frames after the encode.
| Item | Value | Source |
|---|---|---|
brightness | -1.0 to 1.0, default 0 | FFmpeg eq |
contrast | -1000.0 to 1000.0, default 1 | FFmpeg eq |
saturation | 0.0 to 3.0, default 1 | FFmpeg eq |
| Filtergraph length | 2,048 characters, 32 filters | Sume docs |
| Source length | 300 seconds | Sume docs |
Sources
Related posts
More in Media tools
- Fill a timeline gap with generated B-roll through an API
Premiere 26.5 can generate clips inside the timeline. Here is the API version: generate a 3 to 10 second clip, then place it in a Timeline 1.0 slot.
- Find the video frame where a phrase is spoken: hypit tile around
hypit tile with around {phrase} resolves a spoken phrase on the transcript and returns labeled frames around it. Parameters, limits and the error codes.
- Gemini video understanding: 100 vs 300 tokens a second vs Sume
Gemini reads video at about 100 tokens a second, or 300 at high resolution: 60,000 or 180,000 tokens for 10 minutes. How Sume's stills route compares.
- Hook, demo, CTA: assemble a product ad from 3 clips in one render
Build a 15-second holiday product ad from a hook clip, a demo clip and a call-to-action card with one Sume timeline render. Plan first, render second.
Written by Sume