bashbatch-fileffmpegre-encoding

ffmpeg batch reencode with subfolders


I am trying to reencode a few hundred videos to X265 but there are many directories that have spaces in the filenames as do some of the files. I have looked at a bunch of scripts and am struggling to find one that works with the spaces and the different directory levels.

This one works, as long as there is no sub directories:

#!/bin/bash
for i in *.avi;
do 
    ffmpeg -i "$i" -c:v libx265 -c:a copy X265_"$i"
done

I have been trying to work with this bash script, but it fails with the whitespaces I am guessing.

#!/bin/bash
inputdir=$PWD
outputdir=$PWD
while IFS= read -r file ; do
  video=`basename "$file"`
  dir=`dirname "$file"`
 ffmpeg -fflags +genpts -i "$file" -c:v libx265 -c:a copy "$dir"/X265_"$video"
done < <(find "$inputdir" -name "*.avi" | head -100)

On this thread it looks like a good solution for windows users, but not linux. FFMPEG - Batch convert subfolders

FOR /r %%i in (*.mp4) DO ffmpeg32 -i "%%~fi" -map 0:0 -map 0:1 -map 0:1 -c:v copy -c:a:0 aac -b:a 128k -ac 2 -strict -2 -cutoff 15000 -c:a:1 copy "%%~dpni(2)%%~xi"

If you can point me to the right solution that is appropriate for bash, I would appreciate it.


Solution

  • This is a typical scenario for find and xargs

    find /path/to/basedir -name '*.avi' -print0 | xargs -0 convert.sh
    

    where -print0 and -0 ensure the proper handling of names with spaces.

    And in convert.sh, you have your for loop, almost the same as in your first script

    #!/bin/bash
    
    for i; do
        d=$(dirname "$i")
        b=$(basename "$i")
        ffmpeg -i "$i" -c:v libx265 -c:a copy "$d/X265_$b"
    done
    

    for i without anything means the same as "for all arguments given", which are the files passed by xargs.

    To prepend the filename with a string, you must split the name into the directory and base part, and then put it together again.