0

I am trying to get a bare-bones (just running a few commands) script which should read a folder with sub-folders for video files, select the ones which are not HEVC encoded and pass them to ffmpeg, and after - compare the size of the input and output files and if the output is larger in size - move on to the next one, or if the size is smaller - replace the original file.

My logic goes like so:

  1. Prepare plain txt list:

    find /folder -type f \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" \) > log.txt
    
  2. Pass the txt to ffprobe

    ffprobe "log.txt" -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1
    

This is where ffprobe should receive line 1,2,3, etc from log.txt, however I do not know how to do this, because ffprobe only accepts single input.

  1. ffprobe should run the list and output the non-HEVC results in log1.txt

  2. This is where log1.txt should be passed to ffmpeg for transcoding, using the system /tmp folder. I have a working ffmpeg command, the syntax here is not a problem for a single file.

  3. Compare the input and output - if the input is larger than the output - replace it. If the output is larger than the input - discard it and move on to the next one.

The problems I have are mostly linked to passing variables (see 2.) and definetly (5.). I need some pointers as to how to approach the issues stated above, rather than a solution.

Thank you for reading.

1 Answers1

0

You should not be using find for creating a list of files. Parsing find's output it is dangerous and should be avoided – especially if file names with spaces are involved. It is way better to prepare a script that will to the bulk of the work and have it executed via find's exec parameter (the protected semicolon is necessary, I also used single quotes to stop wildcards to be expanded by bash rather than find):

find /folder -type f \( -iname '*.mkv' -o -iname '*.mp4' -o -iname '*.avi' \) -exec transcode.sh {} \;

You can call ffprobe directly on the file and pipe the output to grep to check for the codec name (please note that I do not know the actual name of the codec you want, please adapt):

if ffprobe "$1" -hide_banner -loglevel panic -select_streams v:0 -show_entries stream=codec_name | grep -q 'hvec'
then
  # TODO: do transcoding
fi

After transcoding, you can compare file sizes and act accordingly (note that I deliberately leave file stubs in place so you don't waste time and energy transcoding the file again next time you execute the script):

if [[ $(stat -c%s "$f") -gt $(stat -c%s "$fhvec") ]]
then
  mv "$fhvec" "$f"
else
  truncate -s 0 "$fhvec"
fi

And a more general warning: Do this only on data which is not important (previews, thumbnails, proxies). HVEC is a powerful encoder, but you may end up with videos containing compression artifacts from two distinct encoders. They might be small, but ugly to the eye, too.

Hermann
  • 6,148