Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2019
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 5.89 KB | None | 0 0
  1. #!/bin/bash
  2. IFS=' '
  3.  
  4. root_directories='/mnt/hosts/nas/media/movies/ /mnt/hosts/nas/media/tv/ /mnt/hosts/nas/media/anime/'
  5. min_file_size=$((1024**2*400)) #400 MiB - smallest file size to consider for transcoding
  6. max_file_bit_rate=$((1024**3*10*8/90/60)) #5GiB * 8 bits per byte / 90 mins / 60 secs per min = 7767 Kibps
  7. max_video_bit_depth=8
  8. allowed_video_codecs='avc1 V_MPEG4/ISO/AVC V_VP8 XVID DIVX'
  9. ffmpeg_timeout_multiplier=5 #multiply by video duration to get ffmpeg timeout
  10. ffmpeg_timeout_minimum=$((60*1)) #1 minute - in case $min_file_size is very small
  11. ffmpeg_timeout_maximum=$((60*60*6)) #6 hours
  12. transcode_directory='/mnt/transcode/'
  13.  
  14. target_file_bitrate=$((1024**3*3*8/90/60)) #3GiB * 8 bits per byte / 90 mins / 60 secs per min = 4660 Kibps
  15.  
  16. kodi_url='http://127.0.0.1:8080/jsonrpc'
  17. kodi_json_scan='{"jsonrpc":"2.0","id":1,"method":"VideoLibrary.Scan"}'
  18.  
  19. log_file='/mnt/hosts/nas/files/scripts/media/media-transcode.log'
  20. history_file='/mnt/hosts/nas/files/scripts/media/media-transcode.history'
  21.  
  22. required_binaries='find mktemp mediainfo xpath awk timeout ffmpeg curl cat'
  23.  
  24. for required_binary in $required_binaries
  25. do
  26.     which "$required_binary" > /dev/null
  27.     if [ $? -ne 0 ]
  28.     then
  29.         echo "$required_binary was not found. Exiting"
  30.         exit 1
  31.     fi
  32. done
  33.  
  34. if [ ! -f "$log_file" ]
  35. then
  36.     echo "Result,Timestamp,Bitrate,Bitdepth,Codec,Duration,Filename" > "$log_file"
  37. fi
  38.  
  39. rm -rf "$transcode_directory*"
  40.  
  41. while [ true ]
  42. do
  43.     for root_directory in $root_directories
  44.     do
  45.         IFS='
  46.     '
  47.         for file in $(find "$root_directory" -type f -size +${min_file_size}c -exec ls -S1 {} +) #sort by size descending
  48.         do
  49.             IFS=' '
  50.             # don't start a new transcode between 22:00 and 07:00
  51.             # while [ $(date +%k) -ge 22 ] || [ $(date +%k) -lt 7 ]
  52.             # do
  53.             #   sleep 15m
  54.             # done
  55.             echo $file
  56.             mediainfo_file=$(mktemp)
  57.             # echo $mediainfo_file
  58.             mediainfo "$file" --Output=XML > "$mediainfo_file"
  59.             # ints as strings. convert further down
  60.             file_bit_rate=$(xpath -q -e 'MediaInfo/media/track[@type="General"]/OverallBitRate/text()' $mediainfo_file )
  61.             file_duration=$(xpath -q -e 'MediaInfo/media/track[@type="General"]/Duration/text()' $mediainfo_file )
  62.             file_frames=$(xpath -q -e 'MediaInfo/media/track[@type="General"]/FrameCount/text()' $mediainfo_file )
  63.             file_size=$(xpath -q -e 'MediaInfo/media/track[@type="General"]/FileSize/text()' $mediainfo_file )
  64.             video_bit_depth=$(xpath -q -e 'MediaInfo/media/track[@type="Video"]/BitDepth/text()' $mediainfo_file )
  65.            
  66.             file_frame_rate=$(xpath -q -e 'MediaInfo/media/track[@type="General"]/FrameRate/text()' $mediainfo_file ) #want to preserve decimals - keep as string
  67.             video_codec=$(xpath -q -e 'MediaInfo/media/track[@type="Video"]/CodecID/text()' $mediainfo_file )
  68.            
  69.             rm "$mediainfo_file"
  70.            
  71.             #convert to integers so that we can use them for maths
  72.             file_bit_rate=$(echo $file_bit_rate | awk '{print int($1+0.5)}')
  73.             file_duration=$(echo $file_duration | awk '{print int($1+0.5)}')
  74.             file_frames=$(echo $file_frames | awk '{print int($1+0.5)}')
  75.             file_size=$(echo $file_size | awk '{print int($1+0.5)}')
  76.             if [ "$video_bit_depth" = '' ] # not all formats (webm) expose the bit depth and mediainfo doesn't seem to return a useful exit code
  77.             then
  78.                 video_bit_depth=8
  79.             else
  80.                 video_bit_depth=$(echo $video_bit_depth | awk '{print int($1+0.5)}')
  81.             fi
  82.            
  83.             echo "Rate $((file_bit_rate/1024/1024))Mibps / $((file_bit_rate/1024))Kibps"
  84.             echo "Max  $(($max_file_bit_rate/1024/1024))Mibps / $(($max_file_bit_rate/1024))Kibps"
  85.             echo "$video_bit_depth bit $video_codec"
  86.             echo "$(($file_duration/60))m / ${file_duration}s"
  87.             echo "$file_frames frames @ ${file_frame_rate}fps"
  88.             echo "$((file_size/1024/1024/1024))GiB / $((file_size/1024/1024))MiB"
  89.            
  90.             echo " $allowed_video_codecs " | grep -q " $video_codec "
  91.             if [ $? -eq 0 ] #contains operator
  92.             then
  93.                 bad_codec=false
  94.             else
  95.                 bad_codec=true
  96.             fi
  97.            
  98.             if [ $file_bit_rate -gt $max_file_bit_rate ] || [ $video_bit_depth -gt $max_video_bit_depth ] || [ $bad_codec = true ]
  99.             then
  100.                
  101.                 previously_transcoded=false
  102.                 for history_item in $(cat "$history_file" 2> /dev/null)
  103.                 do
  104.                     if [ "$history_item" = "$file" ]
  105.                     then
  106.                         previously_transcoded=true
  107.                         break
  108.                     fi
  109.                 done
  110.                
  111.                 if [ $previously_transcoded = true ]
  112.                 then
  113.                     echo "Error: File has already been transcoded"
  114.                     echo "repeat,$(date +%Y-%m-%d-%H:%M:%S),$file_bit_rate,$video_bit_depth,$video_codec,$file_duration,$file" >> "$log_file"
  115.                 else
  116.                     echo "Transcoding"
  117.                     timeout=$(($file_duration*$ffmpeg_timeout_multiplier))
  118.                     if [ $timeout -le $ffmpeg_timeout_minimum ]
  119.                     then
  120.                         timeout=$ffmpeg_timeout_minimum
  121.                     elif [ $timeout -ge $ffmpeg_timeout_maximum ]
  122.                     then
  123.                         timeout=$ffmpeg_timeout_maximum
  124.                     fi
  125.                     filename=$(basename "$file")
  126.                     #ffmpeg's built-in -timeout is finicky
  127.                     timeout --foreground $timeout ffmpeg -loglevel warning -hide_banner -stats -y -i "$file" -bitrate $(($target_file_bitrate/1024)) -c:v libx264 -preset medium -tune film -c:a copy -threads 0 "$transcode_directory${filename%.*}.mkv"
  128.                     if [ $? -eq 0 ]
  129.                     then
  130.                         echo "Transcode sucessful"
  131.                         rm "$file"
  132.                         mv "$transcode_directory${filename%.*}.mkv" "${file%.*}.mkv"
  133.                         echo "transcoded,$(date +%Y-%m-%d-%H:%M:%S),$file_bit_rate,$video_bit_depth,$video_codec,$file_duration,$file" >> "$log_file"
  134.                         echo "$file" >> "$history_file"
  135.                         curl -X POST $kodi_url -d $kodi_json_scan
  136.                     else
  137.                         echo "Transcode failed"
  138.                         rm "$transcode_directory${filename%.*}.mkv"
  139.                         echo "failed,$(date +%Y-%m-%d-%H:%M:%S),$file_bit_rate,$video_bit_depth,$video_codec,$file_duration,$file" >> "$log_file"
  140.                     fi
  141.                 fi
  142.             else
  143.                 echo "No need to transcode"
  144.                 echo "skipped,$(date +%Y-%m-%d-%H:%M:%S),$file_bit_rate,$video_bit_depth,$video_codec,$file_duration,$file" >> "$log_file"
  145.             fi
  146.         done
  147.         IFS=' '
  148.     done
  149.     sleep 60m
  150. done
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement