FFmpeg has complex syntax because it’s dealing with the _complexity of video_. I agree with everyone about knowing (and helping create or contribute to) our tools.
Today I largely forget about the _legacy_ of video, the technical challenges, and how critical it was to get it right.
There are an incredible number of output formats and considerations for _current_ screens (desktop, tablet, mobile, tv, etc…). Then we have a whole other world on the creation side for capture, edit, live broadcast…
On legacy formats it used to be so complex with standards, requirements, and evolving formats. Today, we don’t even think about why we have 29.97fps around? Interlacing?
We have a mix of so many incredible (and sometimes frustrating) codecs, needs and final outputs, so it’s really amazing the power we have with a tool like FFmpeg… It’s daunting but really well thought out.
So just a big thanks to the FFmpeg team for all their incredible work over the years…
It's dealing with 3D data (more if you count audio or other tracks) and multi-dimensional transforms from a command line.
It's complexity paired with bad design, making the situation worse than it could be.
This hasn't solved the problem of sometimes needing to do new things, but it at least gives me a map to remind me of the parts of the rabbithole I've explored before.
`gst-launch-1.0 filesrc ! qt4demux ! matroskamux ! filesink...` people would be less frustrated maybe?
People would also learn a little more and be less frustrated when conversation about container/codec/colorspace etc... come up. Each have a dedicated element and you can better understand its I/O
Here making ffmpeg as "just another capability" allows it to be stitched together in workflows
The article states that whatever the article is trying to describe "Takes about ~20-30 mins. The cognitive load is high....". while their literal actual step of "Googling "ffmpeg combine static image and audio."" gives you the literal command you need to run from a known source (superuser.com sourced from ffmpeg wiki).
Anyone even slightly familiar with ffmpeg should be able to produce the same result in minutes. For someone who doesn't understand what ffmpeg is the article means absolutely nothing. How does a "no coder" understand what a "agent in a sandboxed container" is?
we have our designer/intern in our minds who creates shorts, adds subtiles, crops them,and merges the audio generated. He is aware of ffmpeg and prefers using a SaaS UI on top of it.
However, we see him hanging out on chatgpt, or gemini all the time. He is literally the no coder we have in mind.
We just combined his type what you want + ffmpeg workflows.
He does use davinci resolve but only for 2.
NLEs make ffmpeg a standalone yet easy to use tool.
Not denying that major heavy lifting is done by the NLE. We go a step ahead and make it embeddable in a larger workflow.
https://ffmpeg.org/ffmpeg-filters.html#toc-Filtergraph-synta...
"A special syntax implemented in the ffmpeg CLI tool allows loading option values from files. This is done be prepending a slash ’/’ to the option name, then the supplied value is interpreted as a path from which the actual value is loaded."
For how critical that was to getting over my ffmpeg hump, I wish it was not buried halfway through the documentation, but also, I don't know where else it would go.
And just because I am very proud of my accomplishment here is the ffmpeg side of my project, motion detection using mainly ffmpeg, there is some python glue logic to watch stdout for the events but all the tricky bits are internal to ffmpeg.
The filter(comments are added for audience understanding):
[0:v]
split #split the camera feed into two parts, passthrough and motion
[vis],
scale= #scale the motion feed way down, less cpu and it works better
w=iw/4:
h=-1,
format= #needed because blend did not work as expected with yuv
gbrp,
tmix= #temporial blur to reduce artifacts
frames=2,
[1:v] #the mask frame
blend= #mask the motion feed
all_mode=darken,
tblend= #motion detect actual, the difference from the last frame
all_mode=difference,
boxblur= #blur the hell out of it to increase the number of motion pixels
lr=20,
maskfun= #mask it to black and white
low=3:
high=3,
negate, #make the motion pixels black
blackframe= #puts events on stdout when too many black pixels are found
amount=1
[motion]; #motion output
[vis]
tpad= #delay pass through so you get the start of the event when notified
start=30
[original]; #passthrough output
and the ffmpeg evocation: ff_args = [
'ffmpeg',
'-nostats',
'-an',
'-i',
camera_loc, #a security camera
'-i',
'zone_all.png', # mask as to which parts are relavent for motion detection
'-/filter_complex',
'motion_display.filter', #the filter doing all the work
'-map', #sort out the outputs from the filter
'[original]',
'-f',
'mpegts', #I feel a little weied using mpegts but it was the best "streaming" of all the formats I tried
'udp://127.0.0.1:8888', #collect the full video from here
'-map',
'[motion]',
'-f',
'mpegts',
'udp:127.0.0.1:8889', #collect the motion output from here, mainly for debugging
]Like the Before vs after section doesn't even seem to create the same thing, the before has no speedup, the after does.
In the end it seems they basically created a few services ("recipes") that they can reuse to do simple stuff like speed-up 2x or combine audio / video or whatever
Or you could go one step further and create a special workflow which would allow you to define some inputs and iterate with an LLM until the user gets what he wants but for this you would need to generate outputs and have the user validate what the LLM has created before finally saving the recipe.
-filter_complex_script is a thing
- For one-offs, you would just use a GUI.
- For regular edits where you want creative control, you would use a NLE GUI.
- For regular edits where you want consistency, you would have a limited GUI without access to ffmpeg options.
CLI/prompt-based editing for a visual medium is how a programmer might approach editing but no creative…
I can ask it to orient people the right way, crop to the important parts, etc. and it will figure out what "the right way", "the important parts", etc. are. Sometimes I have to give it some light hints like "extract n frames from before y to figure out things", but most of the time it just does it.
Claude Code acts like a very general purpose agent for me. About the one thing that I have to manually do that I'm annoyed by is editing 360 videos into a flow. I'd like to be able to tell Claude Code to "follow my daughter as I dunk her in the pool" and stuff like that but I have to do that myself in the GoPro editor.
This is a nice resource: https://amiaopensource.github.io/ffmprovisr/
And also I've written this cheatsheet, which is designed to be used alongside an LLM: https://github.com/rendi-api/ffmpeg-cheatsheet
Let me know if you're interested in more resources
Can't promise it'll be soon but I may be able to expand on a couple of your repo's "possible future topics list" items.
I've been working on a personal project involving doing object detection on multiple camera feed inputs that all have different resolutions, frame rates, and encodings and sending a single consolidated and annotated feed to a remote streaming service.
That sent me down a really interesting rabbit hole and I've got tons of notes and links along with some Gemini chats that I'm gonna go through and see if there's anything there that might be worth including.
It works 99% of the time for my use case.