I have a video file and I want to crop some portion of the video, apply to a pad, and scale it to a particular dimension. I can do this using three FFmpeg commands each time using a specific filter but I want to do it in a single FFmpeg command, is there any way?
John,
Combining multiple filters into a single FFmpeg command is very simple, you must be using the -vf
option provided by FFmpeg for your individual filters, but to combine them into a single command you have to create a filter chain and use it with the -filter_complex
option provided by FFmpeg.
For example,
ffmpeg -i input.mp4 -filter_complex "[0:v]filter1=option1:option2[outv];[0:a]filter2=option3:option4[outa]" -map "[outv]" -map "[outa]" output.mp4
-
-i input.mp4
indicates the input file, in this case,input.mp4
. -
-filter_complex
is used to target the complex filter graph. -
[0:v]
refers to the video stream from the first input (index 0). -
filter1=option1:option2
shows the first filter you wish to apply to the video stream. -
[outv]
is the name given to the output video stream from the filter. -
[0:a]
refers to the audio stream from the first input (index 0). -
filter2=option3:option4
shows the second filter you want to apply to the audio stream. -
[outa]
is the name given to the output audio stream from the filter. -
-map "[outv]" and -map "[outa]"
specify which output streams to include in the final output file. -
output.mp4
is the name of the output file.
And you can also use the filters twice in different commands and complex filters in ffmpeg.
I hope this may help you! Ask if you need further guidance.
Thanks
Can you tell me how can I use this option mentioned above? I tried this on my system but it did not work properly maybe I am missing something!
Sure!
FFmpeg filter chain works in a very simple way just like a normal programming language, you get a hold particular stream (video/audio/subtitle), apply some operation (filter) on it, and store the output stream in a variable that can be referenced later in filter chain anywhere or can be passed to video codec for transcoding purpose.
Usually, these filter chains follow syntax like the given below.
[index_of_stream:type_of_stream]filter_1_name=param1=value1:param2=value2[output_of_filter_1];[output_of_filter_1]filter_2_name[final_output]
For your use case, the filter chain would look like the following.
[0:v]crop=x=0:y=0:w=500:h=500[cropped_stream];[cropped_stream]pad=width=500:height=500:x=0:y=40:color=black[padded_stream];[padded_stream]scale=w=300:h=300[scaled_stream]
You can just put the filter chain constructed in the above example into the FFmpeg command like the following.
ffmpeg -i input.mp4 -filter_complex “[0:v]crop=x=0:y=0:w=500:h=500[cropped_stream];[cropped_stream]pad=width=500:height=500:x=0:y=40:color=black[padded_stream];[padded_stream]scale=w=300:h=300[scaled_stream]” -map “[scaled_stream]” -c:v libx264 -f mp4 output.mp4