One tool under most of the others
ffmpeg is the free software that decodes, encodes, filters and converts essentially every audio and video format. It is also what a great many commercial applications use internally, which means learning it is not learning an alternative to the professional tools: it is learning the layer most of them sit on.
The command line puts people off. It is worth twenty minutes, because a handful of commands cover most of what an editor is slow at.
The shape of a command
ffmpeg [input options] -i input [output options] outputOptions before -i apply to reading the input; options after apply to writing the output. Getting that the wrong way round is the most common beginner error, and -ss is where it shows: before -i it seeks quickly, after -i it decodes and discards.
Trim without re-encoding
ffmpeg -ss 00:01:30 -i in.mp4 -t 00:00:45 -c copy out.mp4No decode, no encode, no quality loss, done in under a second on a long file. The cut lands on the nearest keyframe, so the start may be up to a GOP early. For a precise cut you have to re-encode:
ffmpeg -ss 00:01:30 -i in.mp4 -t 00:00:45 -c:v libx264 -crf 18 -c:a aac out.mp4Scale, with the trap included
ffmpeg -i in.mp4 -vf "scale=1280:-2" -c:v libx264 -crf 21 -c:a copy out.mp4-2 means “work out the height to preserve the aspect ratio, and make it divisible by 2”. -1 preserves aspect but can produce an odd number, which H.264’s 4:2:0 chroma cannot represent: that is the source of the “width not divisible by 2” error everybody meets once.
For a high-quality downscale, add flags=lanczos. For upscaling, nothing in ffmpeg invents detail; a good scaler is just less soft than a bad one.
Join clips
Same codec and parameters, no re-encode:
printf "file 'a.mp4'\nfile 'b.mp4'\nfile 'c.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy joined.mp4Different sources have to be re-encoded, via the concat filter, and it is worth normalising them to the same resolution and frame rate first rather than letting the filter improvise.
Extract and rebuild frames
ffmpeg -i in.mp4 -vf fps=12 frames/f_%04d.png
ffmpeg -framerate 12 -i frames/f_%04d.png -c:v libx264 -crf 18 -pix_fmt yuv420p out.mp4-pix_fmt yuv420p on the way out is not optional if the file has to play in browsers and on televisions; without it, ffmpeg may write 4:4:4 from PNG input and many hardware decoders will refuse it.
Audio jobs
# extract audio untouched
ffmpeg -i in.mp4 -vn -c:a copy audio.m4a
# replace the audio track
ffmpeg -i video.mp4 -i new.wav -map 0:v -map 1:a -c:v copy -c:a aac -shortest out.mp4
# normalise loudness to -14 LUFS, two-pass
ffmpeg -i in.wav -af loudnorm=I=-14:TP=-1.5:LRA=11:print_format=summary -f null -
ffmpeg -i in.wav -af loudnorm=I=-14:TP=-1.5:LRA=11:measured_I=...:measured_TP=... out.wavloudnorm in a single pass does a dynamic normalisation that can pump. Two-pass (measure, then apply the measured values) does a linear gain change and is what you want. The mixing module covers what those numbers mean.
Inspecting a file
ffprobe -v error -show_streams -show_format in.mp4
ffprobe -v error -select_streams v:0 -show_entries \
stream=codec_name,width,height,r_frame_rate,pix_fmt,color_range,bit_rate \
-of default=nw=1 in.mp4Most delivery arguments end the moment somebody runs this. MediaInfo presents the same information in a graphical window and is also free.
Three flags worth memorising
-movflags +faststart: moves the MP4 index to the front so the file streams. Non-negotiable for web.-pix_fmt yuv420p: maximum compatibility.-c copy: no re-encode, no loss, near-instant. Try it first for anything that does not change the pictures.
Batching
A loop over a folder is where ffmpeg earns its keep against a graphical editor:
for f in *.mov; do
ffmpeg -i "$f" -vf "scale=-2:720" -c:v libx264 -crf 22 \
-c:a aac -b:a 128k -movflags +faststart "web/${f%.mov}.mp4"
doneForty files while you make tea. The same job in an editor is forty exports and forty chances to get one setting wrong.
The free path, and the front ends
ffmpeg itself is free under LGPL or GPL depending on build. HandBrake wraps the same encoders with a graphical interface and sensible presets. Shutter Encoder is a free front end aimed at editors with named jobs rather than flags. MediaInfo reads files. Losslesscut trims with -c copy behind a timeline interface. None of these is a lesser version of a paid tool; they are the tool.
The limitation
ffmpeg does exactly what you say, which includes silently doing something unhelpful. Omit -c:a and it re-encodes your audio; omit -pix_fmt and it may write something unplayable; get the order of -ss wrong and you wait ten minutes for a seek. It has no preview, no undo, and its error messages assume you know the vocabulary.
It also will not make creative decisions. It cannot tell you that the CRF is too high for this footage or that the crop lost somebody’s head. It is a precise instrument for jobs you can already specify, and the judgement stays with you.
Every lesson here is open. Your progress is recorded once you pass the Video with AI exam.
Check your understanding
A team reports that their web video does not begin playing until it is fully downloaded, although the server supports range requests and the file is encoded at a modest bitrate. What is the most likely cause?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Deepa, your AI tutor
