Two problems come from the same place: video formats designed for broadcast television, arriving on servers that expect something else.
Interlacing, and how to recognise it
Interlaced video stores two half-pictures (fields) captured a fraction of a second apart, woven into one frame. A television drew them alternately. A computer displays the woven frame whole, so you see both moments at once.
The symptom is unmistakable once you know it: horizontal comb lines that appear only during motion and vanish when the picture is still.
Confirm rather than guess:
ffprobe -v error -select_streams v:0 -show_entries stream=field_order -of csv input.mp4
Anything other than progressive means interlaced. tt and bb indicate which field comes first, which the filters detect on their own.
Deinterlacing
ffmpeg -i input.mp4 -vf bwdif -c:v libx264 -crf 20 -c:a copy out.mp4
bwdif is generally better than the older yadif and is used the same way. Both output one frame per input frame by default, keeping the frame rate as it was.
To instead produce a frame from each field, doubling the frame rate and giving genuinely smoother motion, since each field was a distinct moment:
ffmpeg -i input.mp4 -vf bwdif=mode=1 -c:v libx264 -crf 20 -c:a copy out.mp4
That turns 25 interlaced frames per second into 50 progressive ones. It looks better and produces a larger file, which is a fair description of the whole trade.
Do not deinterlace progressive video. It softens the picture and fixes nothing. This is why the ffprobe check comes first.
The order that cannot be undone
Deinterlace before scaling. Always.
Scaling an interlaced picture mixes the two fields into shared pixels. After that the combing is baked into the image and no filter can separate what were originally two moments in time.
Correct:
-vf "bwdif,scale=1280:-2"
Backwards, and permanently damaged:
-vf "scale=1280:-2,bwdif"
The filter chain runs left to right, which is why this is worth stating explicitly. For the syntax in general, see understanding FFmpeg filters.
Changing frame rate
ffmpeg -i input.mp4 -vf fps=30 -c:v libx264 -crf 23 -c:a copy out.mp4
The fps filter duplicates or drops frames to reach the target. When the conversion is not a clean multiple, 25 to 30, say. The result is uneven motion, because some frames are shown twice and others once.
There is no way around that with duplication. Interpolation can be smoother:
-vf "minterpolate=fps=60"
It invents intermediate frames by estimating motion. It is slow, and it produces visible distortion around fast movement and edges. Worth trying on specific material, not worth applying as a habit.
Leave the frame rate alone when you can
The most common reason people convert frame rate is a belief that a standard value is required. Browsers play whatever they are given, and 24, 25, 30 and 60 are all fine.
Converting costs quality and gains nothing unless something downstream genuinely demands a fixed rate: adaptive streaming being the usual case, where all renditions must share one rate so a player can switch between them. Setting up HLS streaming goes into that constraint.
Telecined film
Film shot at 24 frames and converted for 30-frame broadcast has a repeating pattern of duplicated fields. Ordinary deinterlacing works on it but throws away the original frames.
ffmpeg -i input.mp4 -vf "fieldmatch,decimate" -c:v libx264 -crf 20 -c:a copy out.mp4
That reverses the process and recovers the original 24-frame progressive film. Where it applies it is clearly better; where it does not, it produces stuttering, so check the result rather than assuming.
Using ffprobe to inspect media files deals with reading the properties that tell you which case you have.
Confirm the source before choosing a filter
The field order tells you which filter to use and whether to use one at all, and it is one command.
ffprobe -v error -select_streams v:0 \ -show_entries stream=field_order,avg_frame_rate,r_frame_rate,codec_name \ -of default=noprint_wrappers=1 input.mp4
Two values are worth reading together. field_order reports interlacing; avg_frame_rate differing from r_frame_rate suggests a variable frame rate, which is a separate problem that deinterlacing will not fix.
Where the metadata says progressive and the picture combs during motion, the file is mis-tagged, which happens with footage that was deinterlaced badly once already. In that case the tag is wrong and your eyes are right.
Variable frame rate is the other cause of judder
Screen recordings and phone footage frequently have a frame rate that varies, and converting them without addressing it produces audio that drifts out of sync.
ffmpeg -i in.mp4 -vsync cfr -r 30 -c:v libx264 -crf 20 -c:a copy out.mp4
That forces a constant rate by duplicating or dropping frames as needed. It is not the same operation as changing the frame rate deliberately, and applying it to genuinely constant-rate footage achieves nothing.
The signature is distinctive: audio and video aligned at the start and progressively further apart by the end, which is also what a bad remux produces, so check which you have before treating it. Remuxing and stream copy sets out the other case.
Deinterlacing costs more than it looks
Both filters run on every frame and are not free, and the doubling mode is roughly twice the work of the standard one because it produces twice the frames.
On a queue, that difference is the one that matters. Measure a representative file both ways before deciding which mode the pipeline uses:
time ffmpeg -nostdin -i in.mp4 -vf bwdif -f null - time ffmpeg -nostdin -i in.mp4 -vf bwdif=mode=1 -f null -
The output goes nowhere, so the figures compare the filter alone instead of the encode. There is more on what the total then means for throughput in running FFmpeg jobs in parallel.
Check the result at full size
Deinterlacing is judged on motion, and motion is invisible in a still frame or a small preview.
Extract a few seconds from a moving section and watch it at full resolution:
ffmpeg -ss 60 -t 5 -i out.mp4 -c copy sample.mp4
What to look for: residual combing on fast movement means the filter did not catch it; a soft, smeared picture on static shots means it was applied to progressive footage. The second is the more common mistake and the more damaging, because it costs detail permanently.