Script to reencode all files in a directory

Hello. I usually reencode many video files with this ffmpeg command or similar

ffmpeg -y -i -c:a copy -vf scale=720:-2 -c:v mpeg4 -vtag xvid -b:v 969k -r 25 -pass 1 -an -f avi /dev/null && ffmpeg -i  -c:a libmp3lame -b:a 48k -ac 1 -vf scale=720:-2,subtitles=1.srt:force_style='Fontsize=20' -c:v mpeg4 -vtag xvid -b:v 969k -r 25 -pass 2 /.avi

So I would like to insert the parameters of this ffmpeg command on a script that reencodes all the videos on a certain directory. I tried to adapt a script that I found for it

for f in $(find -type f -name *.mkv); do ffmpeg -n -y -i "$f.mkv" -vf scale=720:-2 -c:v mpeg4 -vtag xvid -b:v 969k -r 25 -pass 1 -an -f avi /dev/null && ffmpeg -n -i "$f" -c:a libmp3lame -b:a 48k -ac 1 -vf scale=720:-2,subtitles="$f.srt":force_style='Fontsize=20' -c:v mpeg4 -vtag xvid -b:v 969k -r 25 -pass 2  ".$f.avi" ; done 

However, when I try to run this script. it says that cannot find such file or directory. This happens because its treating every word separated by a blank space of the file's name as a file on its own.

So how can I solve this question. Also warns about any possible errors that might arise are welcome. Thank you

Try using shell continuation "markers " the backslash \ Also added { }

for f in $(find . -type f -name '*.mkv'); 
do 
   ffmpeg -n -y -i "${f}" -vf scale=720:-2 -c:v mpeg4 -vtag xvid -b:v 969k \
           -r 25 -pass 1 -an -f avi /dev/null && \
   ffmpeg -n -i "${f}" -c:a libmp3lame -b:a 48k \
           -ac 1 -vf scale=720:-2,subtitles="${f}.srt":force_style='Fontsize=20' \
           -c:v mpeg4 -vtag xvid -b:v 969k -r 25 -pass 2 ".${f}.avi" ; 
done

I cannot vouch for the correctness your ffmpeg commands at all. Try it.

Yes, quote *.mkv in the find argument, and do not add another .mkv to $f!

If space characters are your problem, use

IFS=

so the for list splits on newline only.

More robust (with special characters) is a while loop

find . -type f -name "*.mkv" | while IFS= read -r f; do ... ; done

Or

while IFS= read -r f; do ... ; done < <(find . -type f -name "*.mkv")

A last possibility is find -exec :

find . -type f -name "*.mkv" -exec /bin/sh 'f=$1; ... ' sh {} \;

(Note that one must provide $0, the script name, here: sh .)

1 Like

Hi MadeInGermany. I tried your script. I end receiving many messages like;

then:

and finally

It ends reencoding only the first video in the dir.

Try to redirect stdin:

  </dev/null ffmpeg ...

Why not:

myFFMPEG() { # SINGLE_FILE
   ffmpeg -n -y -i "${1}" -vf scale=720:-2 -c:v mpeg4 -vtag xvid -b:v 969k \
           -r 25 -pass 1 -an -f avi /dev/null && \
   ffmpeg -n -i "${1}" -c:a libmp3lame -b:a 48k \
           -ac 1 -vf scale=720:-2,subtitles="${f}.srt":force_style='Fontsize=20' \
           -c:v mpeg4 -vtag xvid -b:v 969k -r 25 -pass 2 ".${1}.avi" ; 
}

for f in *.mkv;do
    echo "Parsing: $f"
    [[ -f "$f" ]] && myFFMPEG "$f"
done

Other than that, I would happen to have that script....

Because I'm lazy :wink:

vhs -tQ fhd inputfile
## -- Vs. -- ##
ffmpeg -i "inputfile"  -strict -2  -map 0:0 -b:v 1664K -vf scale=1920x1080 -c:v libx264  -minrate 3328K -maxrate 3328K -bufsize 1664K  -b:a 256K -ac 2 -c:a ac3   -c:s ssa  -map 0:3  -map 0:1  "outputfile"