ffmpeg
Conventions used below:
in.mp4= input fileout.mp4= output file- Times use
HH:MM:SSor seconds (e.g.5or00:00:05)
The whole guide in one sentence: "take THIS file, do THIS to it, save it as THIS." Every command follows ffmpeg -i [file you have] [what to do to it] [name of new file].
in.mp4= the file you're starting without.mp4= the new file it creates
1. Trimming / Cutting
| Task | Command |
|---|---|
| Remove first N seconds (re-encode) | ffmpeg -ss 5 -i in.mp4 -c:v libx264 -c:a aac out.mp4 |
| Remove first N seconds (no re-encode, fast, keyframe-snapped) | ffmpeg -ss 5 -i in.mp4 -c copy out.mp4 |
| Cut a middle segment (start to end) | ffmpeg -ss 00:01:00 -to 00:02:30 -i in.mp4 -c copy out.mp4 |
| Cut last N seconds off the end | ffmpeg -sseof -10 -i in.mp4 -c copy out.mp4 |
| Cut by duration instead of end time | ffmpeg -ss 10 -i in.mp4 -t 20 -c copy out.mp4 (start at 10s, keep 20s) |
Note: -ss before -i = fast seek (jumps to nearest keyframe, may be a few frames off). -ss after -i = accurate but slower (decodes from start). -c copy = no re-encoding (instant, lossless, but cut points snap to keyframes). Drop -c copy and add -c:v libx264 -c:a aac for frame-accurate cuts at the cost of re-encoding time.
In plain English: this is cutting a piece out of a video, like snipping a piece of tape. Cutting off the beginning = tell it how many seconds to skip. Cutting from the middle = give it a start time and an end time. Cutting off the end = chop a number of seconds from the back. There's a fast-but-slightly-sloppy way and a slow-but-exact way — fast is fine 95% of the time.
2. Format / Container Conversion
| Task | Command |
|---|---|
| Convert container only (no re-encode) | ffmpeg -i in.mkv -c copy out.mp4 |
| Convert with re-encode (e.g. old codec to H.264) | ffmpeg -i in.avi -c:v libx264 -c:a aac out.mp4 |
| Convert to GIF | ffmpeg -i in.mp4 -vf "fps=15,scale=480:-1" out.gif |
| Extract audio only | ffmpeg -i in.mp4 -vn -c:a copy out.aac |
| Extract audio, convert to mp3 | ffmpeg -i in.mp4 -vn -c:a libmp3lame -q:a 2 out.mp3 |
| Strip audio, keep video only | ffmpeg -i in.mp4 -an -c:v copy out.mp4 |
In plain English: changing the "wrapper" a video comes in (like .mkv vs .mp4), or pulling just the audio out of a video — like ripping the soundtrack out of a movie.
3. Resizing / Scaling
| Task | Command |
|---|---|
| Scale to specific width, keep aspect | ffmpeg -i in.mp4 -vf scale=1280:-1 out.mp4 |
| Scale to specific height, keep aspect | ffmpeg -i in.mp4 -vf scale=-1:720 out.mp4 |
| Force exact dimensions (may distort) | ffmpeg -i in.mp4 -vf scale=1280:720 out.mp4 |
| Scale down only if larger (never upscale) | ffmpeg -i in.mp4 -vf "scale='min(1280,iw)':-1" out.mp4 |
In plain English: making the video bigger or smaller, the same way you'd resize a photo. You tell it a width or a height and it keeps things from looking squished.
4. Joining / Concatenating
| Task | Command |
|---|---|
| Concat identical-codec files (fast, no re-encode) | See concat demuxer below |
| Concat with re-encode (mixed formats) | Use concat filter, not demuxer |
Concat demuxer (files must share codec/resolution):
# list.txt:
file 'clip1.mp4'
file 'clip2.mp4'
ffmpeg -f concat -safe 0 -i list.txt -c copy out.mp4
Concat filter (re-encodes, handles mismatched sources):
ffmpeg -i clip1.mp4 -i clip2.mp4 -filter_complex \
"[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" out.mp4
In plain English: gluing two or more clips together into one file, back to back.
5. Images ↔ Video
| Task | Command |
|---|---|
| Images to video (fixed duration each) | ffmpeg -framerate 1/5 -i %03d.png -c:v libx264 -pix_fmt yuv420p out.mp4 |
| Images to video, custom per-image duration | Use concat demuxer with duration lines (see your quote-slideshow project) |
| Video to image sequence | ffmpeg -i in.mp4 frame_%04d.png |
| Extract a single frame at a timestamp | ffmpeg -ss 00:00:10 -i in.mp4 -frames:v 1 frame.png |
| Add audio to a silent video | ffmpeg -i video.mp4 -i audio.mp3 -c:v copy -c:a aac -shortest out.mp4 |
In plain English: turning a folder of photos into a slideshow video — or going the other way and pulling still frames out of a video (like a screenshot, but from a video file instead of your screen).
6. Audio Adjustments
| Task | Command |
|---|---|
| Change volume | ffmpeg -i in.mp4 -filter:a "volume=1.5" out.mp4 (1.5 = 150%) |
| Normalize audio loudness | ffmpeg -i in.mp4 -filter:a loudnorm out.mp4 |
| Fade audio in/out | ffmpeg -i in.mp4 -af "afade=t=in:st=0:d=3,afade=t=out:st=57:d=3" out.mp4 |
| Merge/replace audio track | ffmpeg -i video.mp4 -i newaudio.mp3 -map 0:v -map 1:a -c:v copy -shortest out.mp4 |
In plain English: turning volume up/down, smoothing out loudness so it's not jarringly quiet-then-loud, fading sound in/out, or swapping one audio track for another.
7. Video Adjustments
| Task | Command |
|---|---|
| Change frame rate | ffmpeg -i in.mp4 -r 30 out.mp4 |
| Rotate 90° clockwise | ffmpeg -i in.mp4 -vf "transpose=1" out.mp4 |
| Crop | ffmpeg -i in.mp4 -vf "crop=w:h:x:y" out.mp4 |
| Add text overlay (burned-in) | ffmpeg -i in.mp4 -vf "drawtext=text='Hello':x=10:y=10:fontsize=24:fontcolor=white" out.mp4 |
| Fade video in/out | ffmpeg -i in.mp4 -vf "fade=t=in:st=0:d=2,fade=t=out:st=58:d=2" out.mp4 |
| Speed up / slow down | ffmpeg -i in.mp4 -vf "setpts=0.5*PTS" -af "atempo=2.0" out.mp4 (2x speed) |
In plain English: changing frame rate (smoothness), rotating it, cropping it, slapping text on it, fading the picture in/out, or speeding it up / slowing it down.
8. Inspecting Files
| Task | Command |
|---|---|
| Show all stream/codec info | ffprobe -hide_banner in.mp4 |
| Show duration only | ffprobe -v error -show_entries format=duration -of csv=p=0 in.mp4 |
| Show codec of video stream | ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of csv=p=0 in.mp4 |
In plain English: asking the file "what are you, exactly?" — length, format, what codec it's using. Good for troubleshooting before you do anything else.
9. Quality / Compression
| Task | Command |
|---|---|
| Compress with target quality (CRF, lower=better, 18-28 typical) | ffmpeg -i in.mp4 -c:v libx264 -crf 23 -c:a aac out.mp4 |
| Compress with target file size (2-pass) | Use -b:v with 2-pass encoding — ask if you need this, it's a multi-command process |
| Fast encode, larger file | ffmpeg -i in.mp4 -c:v libx264 -preset ultrafast out.mp4 |
| Slow encode, smaller file, same quality | ffmpeg -i in.mp4 -c:v libx264 -preset slow -crf 23 out.mp4 |
In plain English: shrinking file size. Lower "CRF" number = better quality / bigger file; higher number = smaller file / worse quality. It's a dial, not a switch.
Reading ffmpeg's flag order rule
Like ImageMagick, ffmpeg is order-sensitive but the rule is different: flags before -i apply to input handling (seeking, format forcing); flags after -i apply to output encoding/filtering. -ss is the classic example — its position changes both behavior and performance.
GUI Frontends (if you ever want to point-and-click instead)
These are wrappers around ffmpeg — the engine doesn't change, just the interface:
- LosslessCut — AppImage, great for the exact trim task you started with (frame-accurate cut/trim without re-encoding, visual timeline)
- Shutter Encoder — batch conversion, presets, GUI over most of ffmpeg's common operations
- Avidemux — cutting/filtering with a visual timeline, older but stable
- Curlew — simple GTK-based ffmpeg GUI, fits well with a lightweight WM setup
- HandBrake — encoding/compression focused, not trimming
None of these teach you ffmpeg commands directly, but LosslessCut is worth having installed alongside your terminal workflow — it's genuinely the fastest way to do the trim-first-5-seconds job when you don't want to think about keyframes.