How to do 3 operations without rendering 3 times?

How to do 3 operations without rendering 3 times?

I want to do three filter operations in ffmpeg, but without encoding three times: Microsoft Windows [Version 10.0.18362.959]

  1. Video crop

  2. Add cropped video over image

  3. Add text to result video

The operations visualized:

i want...(image)

My current code (working but 3x render):

ffmpeg -i kare.mp4 -filter:v "crop=in_w:in_h-472" -c:a copy kirp.mp4 && ffmpeg -y -loop 1 -i 1.jpg -i kirp.mp4 -filter_complex "[0:v]setpts=PTS-STARTPTS[V1]; [1:v]setpts=PTS-STARTPTS, scale=1080:608[V2]; [V1][V2]overlay=shortest=1:x=0:y=600" sablon.mp4  && ffmpeg -i sablon.mp4 -vf "drawtext=fontfile=Be.ttf:text='123asd':fontcolor=white:fontsize=105:x=(w-text_w)/2:y=(h-text_h)/3.8" -codec:a copy output.mp4 && del "kirp.mp4" del "sablon.mp4"

Solution 1:

Have you tried just chaining the filters together? Something like this should work:

ffmpeg -loop 1 -i 1.jpg -i kare.mp4 -filter_complex \
"[0]setpts=PTS-STARTPTS[s0];[1:v]crop=in_w:in_h-472, \
setpts=PTS-STARTPTS,scale=1080:608[s3]; \
[s0][s3]overlay=eof_action=repeat:shortest=1:x=0:y=600, \
drawtext=fontcolor=white:fontfile=Be.ttf:fontsize=105: \
text='(MyText)':x=(w-text_w)/2:y=(h-text_h)/3.8[s5]" \
-map "[s5]" -map 1:a -c:a copy output.mp4

Edit: Since you're on Windows, try this (no modifications to it are needed):

ffmpeg -loop 1 -i 1.jpg -i kare.mp4 -filter_complex "[0]setpts=PTS-STARTPTS[s0];[1:v]crop=in_w:in_h-472,setpts=PTS-STARTPTS,scale=1080:608[s3];[s0][s3]overlay=eof_action=repeat:shortest=1:x=0:y=600,drawtext=fontcolor=white:fontfile=Be.ttf:fontsize=105:text='(MyText)':x=(w-text_w)/2:y=(h-text_h)/3.8[s5]" -map "[s5]" -map 1:a -c:a copy output.mp4

Tested on Ubuntu 20.04 and Windows 10 with the latest versions of FFmpeg respectively.

Solution 2:

It seems to me that in the second step you are taking the cropped video, scaling it, and then putting it on top of the image. I am not checking whether all the other values used by you fit your requirements. Anyhow, what will work in that case is:

ffmpeg -i kare.mp4 -loop 1 -i 1.jpg -filter_complex "[0:a]anull[audio]; \
[0:v]crop=in_w:in_h-472[cropped];[cropped]setpts=PTS-STARTPTS[V1]; \
[1:v]setpts=PTS-STARTPTS, scale=1080:608[V2]; \
[V1][V2]overlay=shortest=1:x=0:y=600[overlaid]; \
[overlaid]drawtext=fontfile=Be.ttf:text='(MyText)':fontcolor=white: \
fontsize=105:x=(w-text_w)/2:y=(h-text_h)/3.8[videout]" -map [videout] \
-map [audio] -c:a aac output.mp4 

Here the first chain in the filtergraph just passes the audio without tampering. The second part does the cropping of the video (first input stream 0). The third part sets PTS (presentation time stamp). The fourth part sets the PTS for the second input which is the image and scales it. (Is this what you want?)

The fifth part overlays the image on top of the cropped video. If you want the video on top of the image, you will have to reverse the order of [v1][v2] before overlay filter. In the overlay filter the second pad always goes on top.

The sixth part draws the text on top of this composite. On my system my font settings are different, but essentially this format will work.

Tested on bash 4.4 and ffmpeg 4.4.