Search code examples
ffmpegoverlaycrop

Efficient command line to crop a video, overlay another crop from it and scale the result with ffmpeg


I need to convert many videos in such a way that I take 2 different crops from each frame of a single video, stack them one over the other and scale down the result, creating a new smaller video. I want to convert this fullHD frame (two crop areas are marked red) to this small stacked frame.

Right now I use the following code:

ffmpeg  -i "video.mkv" -filter:v "crop=560:416:0:0" out1.mp4
ffmpeg  -i "video.mkv" -filter:v "crop=560:384:1060:128" out2.mp4
ffmpeg  -i out1.mp4 -vf "movie=out2.mp4[inner]; [in][inner] overlay=0:32,scale=280:208[out]"  -c:v libx264 -preset veryfast -crf 30 result.mp4

It works but it is very inefficient and requires temporary files (out1 and out2). And the problem is I have over 100.000 of such videos (they are big and stored on a NAS and not directly on my computer's HDD). Converting all of them with a Windows batch script (for loop) will take...48 days. Can you help me to optimize the script?


Solution

  • Use the crop, vstack, scale, and format filters:

    ffmpeg -i input.mkv -filter_complex "[0:v]crop=560:24:0:0[top];[0:v]crop=560:384:1076:128[bottom];[top][bottom]vstack,scale=280:-2[out]" -map "[out]" -c:v libx264 -preset veryfast -crf 30 -movflags +faststart result.mp4
    

    If you want to complicate it somewhat for faster filtering (maybe) then you can try scaling first:

    ffmpeg -i input.mkv -filter_complex "[0:v]scale=iw/2:-1,split[v0][v1];[v0]crop=560/2:24/2:0:0[top];[v1]crop=560/2:384/2:1076/2:128/2[bottom];[top][bottom]vstack[out]" -map "[out]" -c:v libx264 -preset veryfast -crf 30 -movflags +faststart result.mp4
    

    You'll have to experiment to see which is fastest for you.