Home > Software engineering >  Trying to batch process videos in multi-depth subdirectories with ffmpeg, find with -exec
Trying to batch process videos in multi-depth subdirectories with ffmpeg, find with -exec

Time:11-24

The sub-directories have different depth and have videos scattered. I am using find command to locate videos of multiple extensions like mp4, mkv, m4v, webm, ts, mov, etc. and then trying to process them with ffmpeg.

So far, I have come up with this command:

find . -type f \( -name "*.mp4" -o -name "*.mkv" -o -name "*.m4v" -o -name "*.webm" -o -name "*.ts" -o -name "*.mov" \) -execdir ffmpeg -i {} -vcodec libx264 -crf 32 -vf scale=1280:720 -r 16 -map_metadata -1 {}.mp4 \;

If I try adding a prefix to ffmpeg output as ... out{}.mp4 \;, it is not possible. It says:

out./<FILE_NAME>.mp4: No such file or directory

I want the final output to have "out${original_name}".mp4 as the name. Is there anyway to add prefix to output?

CodePudding user response:

Is there anyway to add prefix to output?

Yes, use a shell script like this:

find . ... -exec sh -c '
for src; do
  name=${src##*/}
  dest=${src%"$name"}out${name%.*}.mp4
  ffmpeg -i "$src" ... "$dest"
done' sh {}  

CodePudding user response:

$1 is the first argument to your currently running shell, and probably empty.

You are probably looking for something like

find . -type f \(
   -name "*.mp4" -o -name "*.mkv" -o -name "*.m4v" \
   -o -name "*.webm" -o -name "*.ts" -o -name "*.mov" \) \
   -exec sh -c 'for f; do
      ffmpeg -i "$f" -vcodec libx264 -crf 32 -vf scale=1280:720 \
         -r 16 -map_metadata -1 "${f%.*}".mp4;
    done' _ {}  

The use of -exec sh -c '...' allows you to refer to the argument repeatedly and apply the shell's parameter expansion facilities etc, and the for loop and the instead of \; is just an efficiency hack to allow you to -exec fewer times.

  • Related