bashffmpegplex

Plex DVR File Rename on FFMPEG Encoding


I'm currently using a bash shell script to encode all of my Plex DVR recordings to H.264 using FFMPEG. I'm using this little for loop I found online to encode all of the files in a single directory:

for i in *.ts;
    do echo "$i" && ffmpeg -i "$i" -vf yadif -c:v libx264 -preset veryslow -crf 22 -y "/mnt/d/Video/DVR Stash/Seinfeld/${i%.*}.mp4";
done

This has served its purposes well but in the process I would like to rename the file to my preferred naming convention so that the original filename Seinfeld (1989) - S01E01 - Pilot.ts is renamed to Seinfeld S01 E01 Pilot.mp4 in the encoded file. While I am already using a regular expression to change the .ts extension to .mp4, but I'm no expert with regex, especially in the bash shell so any help would be appreciated.

For anyone that's interested in my Plex setup, I'm using an old machine running Linux Mint as my dedicated DVR and actually accessing it over the network with my daily driver which is a gaming machine, so more processing power for video encodes. While that one is a Windows machine, I'm using the Ubuntu bash under WSL2 to run my script, as I prefer it over the Windows command prompt or Powershell (my day job is a web developer on a company issued Mac). So here's a sample of my code for anyone that might consider doing something similar.

if [[ -d "/mnt/sambashare/Seinfeld (1989)" ]]
then
    cd "/mnt/sambashare/Seinfeld (1989)"
    echo "Seinfeld"
    for dir in */; do
        echo "$dir/"
        cd "$dir"
        for i in *.ts;
            do echo "$i" && ffmpeg -i "$i" -vf yadif -c:v libx264 -preset veryslow -crf 22 -y "/mnt/d/Video/DVR Stash/Seinfeld/${i%.*}.mp4";
        done
        cd ..
    done
fi

While I've considered doing a for loop for all shows, for now I am doing each show like this individually as there are a few shows I have custom encoding settings for


Solution

  • A small revision from your code, something like this, with extglob

    #!/usr/bin/env bash
    
    if [[ -d "/mnt/sambashare/Seinfeld (1989)" ]]; then
      cd "/mnt/sambashare/Seinfeld (1989)" || exit
      echo "Seinfeld"
      for dir in */; do
        echo "$dir/"
        cd "$dir" || exit
        for i in *.ts; do
          shopt -s extglob
          new_file=${i//@( \(*\)|- )}
          new_file=${new_file/E/ E}
          new_file=${new_file%.*}
          echo "$i" &&
          ffmpeg -i "$i" -vf yadif -c:v libx264 -preset veryslow -crf 22 -y "/mnt/d/Video/DVR Stash/Seinfeld/${new_file}.mp4"
          shopt -u extglob
        done
        cd ..
      done
    fi
    

    The string/glob/pattern slicing might fail if there is/are E's in the file name somewhere besides the episode.


    With BASH_REMATCH using the =~ operator for Extended Regular Expression. This will work even if there are more E's in the filename.

    #!/usr/bin/env bash
    
    if [[ -d "/mnt/sambashare/Seinfeld (1989)" ]]; then
      cd "/mnt/sambashare/Seinfeld (1989)" || exit
      echo "Seinfeld"
      for dir in */; do
        echo "$dir/"
        cd "$dir" || exit
        for i in *.ts; do
           regex='^(.+) (\(.+\)) - (S[[:digit:]]+)(E[[:digit:]]+) - (.+)([.].+)$'
           [[ $i =~ $regex ]] &&
           new_file="${BASH_REMATCH[1]} ${BASH_REMATCH[3]} ${BASH_REMATCH[4]} ${BASH_REMATCH[5]}"
          echo "$i" &&
          ffmpeg -i "$i" -vf yadif -c:v libx264 -preset veryslow -crf 22 -y "/mnt/d/Video/DVR Stash/Seinfeld/${new_file}.mp4"
        done
        cd ..
      done
    fi