Using `ffmpeg` on Video Files
Posted: 2024-08-14
Tags: ffmpeg
- Detecting Interlace vs Progressive
- Preserving Interlace with H264
- De-interlacing
- Re-Interlacing
- Scale
- Crop
- Storage vs Display Aspect Ration
- Gaussian Blur
- Unsharp Mask
- Adjust Audio / Subtitle Timing
- Extracting Closed Captions
Detecting Interlace vs Progressive1
ffmpeg -vf idet -frames:v 360 -an -f rawvideo -y /dev/null -i input.mp4
Look for the number of TFF
and BFF
(Top/Bottom First Field) detected. If they are non-zero, then the video is interlaced.
Explanation: Runs the idet
filter on 360 frames of video, ignoring audio, forcing rawvideo, and redirecting output to /dev/null
.
Preserving Interlace with H264
Because ffmpeg
and libx264
default to progressive (non-interlaced) video, in order to preserve interlace when dealing with an already interlaced video do the following:
ffmpeg -i input.mp4 -c:v libx264 -flags +ildct+ilme -x264opts "tff=1" -c:a copy output.mp4
The -flags +ildct+ilme
flags enable interlaced DCT (Discrete Cosine Transform) and interlaced motion estimation.
Optionally, specifying -x264opts "tff=1"
sets the video as top-field-first interlaced. If it is bottom-field-first, then use tff=0
.
Note: Re-scaling interlaced video is very finnicky. Do careful quality control checks on interlaced video that is resized or otherwise filtered before deleting source files.
De-interlacing
ffmpeg -i input.mp4 -vf "yadif=1:-1:1" -c:v libx264 -c:a copy output.mp4
The yadif
filter2 set to output one frame per field (doubling the frame rate), auto-detect TFF or BFF, and only deinterlace frames marked as interlaced.
Include fps=fps=30
(or whatever the original frame rate was) in the filter chain to preserve original frame rate.
Alternately, use yadif=0:-1:1
to maintain current framerate without needing the fps
filter.
Re-Interlacing
Sometimes an interlaced video is converted to progressive without any de-interlace filter being used. It can be reconfigured as an interlaced video with the tinterlace
filter.
Top Field First (TFF)
ffmpeg -i input.mp4 -vf "tinterlace=interleave_top" -c:v libx264 -x264opts "tff=1" -flags +ildct+ilme -c:a copy output_interlaced.mp4
Bottom Field First (BFF)
ffmpeg -i input.mp4 -vf "tinterlace=interleave_bottom" -c:v libx264 -x264opts "tff=0" -flags +ildct+ilme -c:a copy output_interlaced_bff.mp4
Note: If you pick the wrong one it will be obvious when watching fast motions in hte resulting video.
Scale3
Crop4
In the form crop=w:h:x:y
, where x
is zero indexed and starts at the left edge and y is zero indexed from the upper edge.
To trim one pixel from the left, three from the right, two from the top, and one from the bottom on a 640x480 video:
ffmpeg -i input.mp4 -vf "crop=636:477:1:2" output.mp4
In the form crop=w:h
, the cropped size is taken out of the middle since x
and y
default to (in_w-out_w)/2
and (in_h-out_h)/2
.
Storage vs Display Aspect Ration
Gaussian Blur5
Unsharp Mask6
Adjust Audio / Subtitle Timing
Extracting Closed Captions7
Closed Captions are different than other subtitle formats. They are encoded as part of the video stream itself.
Extract CC to SRT file
ffmpeg -f lavfi -i "movie=input.mp4[out0+subcc]" -map s "output.srt"
Note: The CC data is still in the video stream after this command.
Remove CC data from video stream
For AVC encoded video:
ffmpeg -i "INPUT.mp4" -c copy -map 0 -bsf:v filter_units=remove_types=6 "OUTPUT.mp4"
For HEVC encoded videos:*
ffmpeg -i "INPUT.mp4" -c copy -map 0 -bsf:v filter_units=remove_types=39 "OUTPUT.mp4"
PAL to NTSC
Historically many NTSC 23.976 fps films have been run at the PAL speed of 25fps because it is close enough that people cannot tell the difference.
This ends up making the films have a slightly shorter run time, and slowly desynchronizes NTSC subtitles the further into the film you get.
ffmpeg -i input.mp4 -vf "setpts=25025/24000*PTS" -af "atempo=0.959040959040959" -r 24000/1001 -c:v libx264 -c:a aac output.mp4
Note: Both audio and video must be re-encoded to fix this. Update the -c:v
and -c:a
segments as needed.