decided to actually go through git as was doing too many scripts... uses ffmpeg to transcode a list of files into AV1 format.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
8.8 KiB

3 years ago
3 years ago
1 year ago
3 years ago
1 year ago
3 years ago
3 years ago
3 years ago
3 years ago
1 year ago
3 years ago
1 year ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. #!/bin/bash
  2. #Is a 'slave' script to run an ffmpeg (and ffprobe) command. Generally it will
  3. #take a file specified on the 'host' machine that has a list of files; copy a
  4. #version down locally, transcode it, then replace the original file on the
  5. #'host', and remove the temporary files.
  6. #
  7. #You will need to have both FFMPEG and FFPROBE installed (and will need
  8. #to pray to St. Isidore... good luck if you encounter issues.
  9. #Default operations, change if necessary
  10. FFBIN="/usr/bin/" #if unusual install or a specific version
  11. HostName="localhost" #if localhost then will do locally (removes ssh/scp cmds)
  12. hostFile="/tmp/transcode/list.txt"
  13. tmpDIR="$PWD/tmpTranscode"
  14. workDIR="$PWD/transcode"
  15. #DEFINE FUNCTIONS
  16. function encode {
  17. local tmpFL=$1
  18. local outFL=$2
  19. $FFBIN/ffmpeg -hide_banner -loglevel error -stats -re -i "$tmpFL" -map 0 \
  20. -map_metadata 0 -c copy \
  21. -c:v libsvtav1 -crf 28 -g 240 -preset 6 -svtav1-params \
  22. "enable-overlays=1:\
  23. tune=0" \
  24. -use_wallclock_as_timestamps 1 \
  25. -map_chapters 0 -max_muxing_queue_size 9999 -y "$outFL"
  26. }
  27. function burnSubs {
  28. local inFL=$1
  29. local tmpFL=$2
  30. local outFL=$3
  31. local track=$4
  32. #EVIDTNELY NECESSARY SO THAT FILES AREN'T 198+ HRS IN LEN. AT THE END
  33. local DURATION=$( $FFBIN/ffprobe -loglevel error -show_entries format=duration \
  34. -of default=noprint_wrappers=1:nokey=1 "$inFL" )
  35. $FFBIN/ffmpeg -hide_banner -loglevel error -stats -i "$inFL" \
  36. -filter_complex "[0:v][0:s:$track]overlay[v]" -map "[v]" \
  37. -filter_complex_threads 1 \
  38. -map 0:a -c:a copy -map 0:s -map -0:s:$track -c:s copy \
  39. -map_metadata 0 -map_chapters 0 -max_muxing_queue_size 4096 \
  40. -t $DURATION -threads 1 -y "$tmpFL"
  41. rm "$inFL" #SAVE SPACE
  42. encode "$tmpFL" "$outFL"
  43. }
  44. #MAIN FUNCTION BEGINS
  45. mkdir -p "$tmpDIR"
  46. mkdir -p "$workDIR"
  47. if [ -n "$1" ]
  48. then
  49. numIter=$1
  50. iterLim="true"
  51. else
  52. numIter=20
  53. iterLim="false"
  54. fi
  55. if ! command -v $FFBIN/ffprobe &> /dev/null
  56. then
  57. echo "Need to have ffprobe (and ffmpeg) installed"
  58. exit 1
  59. fi
  60. if ! command -v $FFBIN/ffmpeg &> /dev/null
  61. then
  62. echo "Need to have ffmpeg (and ffprobe) installed"
  63. exit 1
  64. fi
  65. if ! command -v bc &> /dev/null
  66. then
  67. echo "Need to have bc installed (foreign audio scan)"
  68. exit 1
  69. fi
  70. i=0 #Total number of loops
  71. j=0 #Failed to obtain job
  72. k=0 #ffmpeg failed
  73. declare -a langs #Subtitle Languages
  74. while [ $numIter -gt 0 ] && [ $j -lt 50 ] && [ $k -lt 60 ]
  75. do
  76. if [ $( echo "$HostName"|tr [a-z] [A-Z] ) != "LOCALHOST" ]
  77. then
  78. filePATH=$( ssh $HostName "head -n1 $hostFile;sed -i -e '1d' $hostFile" )
  79. else
  80. filePATH=$( head -n1 $hostFile;sed -i -e '1d' $hostFile )
  81. fi
  82. if [ -n "$filePATH" ]
  83. then
  84. j=0
  85. fileNAME=$( basename "$filePATH" )
  86. #PULL DOWN FILE
  87. if [ $( echo "$HostName"|tr [a-z] [A-Z] ) != "LOCALHOST" ]
  88. then
  89. scp $HostName:"$( echo $filePATH | sed "s/[][!@#$%^&*( ;)]/\\\&/g" )" "$tmpDIR"
  90. else
  91. rsync -a --progress "$filePATH" "$tmpDIR/"
  92. fi
  93. #RUN FFMPROBE/FFMPEG
  94. echo "DOING $fileNAME"
  95. unset langs
  96. #DETERMINE THE NUMBER OF ENGLISH SUBTITLES (BURNING BEHAVIOUR)
  97. for line in $( $FFBIN/ffprobe -loglevel error -select_streams s -show_entries\
  98. stream=index:stream_tags=language -of csv=p=0 \
  99. "$tmpDIR"/"$fileNAME" )
  100. do
  101. langs+=("$line")
  102. done
  103. unset line
  104. engCounter=0
  105. if [ ${#langs[@]} -gt 1 ]
  106. then
  107. #DETERMINE NUMBER OF ENGLISH-CONTAINING SUBTITLES
  108. unset streamNUMBERS
  109. declare -a streamNUMBERS
  110. for language in "${langs[@]}"
  111. do
  112. if grep -iq "eng" <<< $language
  113. then
  114. let ++engCounter
  115. delim=","
  116. unset addNumber
  117. addNumber=( "${language%%"$delim"*}" )
  118. streamNUMBERS+=($addNumber)
  119. fi
  120. done
  121. if [ $engCounter -lt 2 ]
  122. then
  123. #ONLY ONE ENG. SUB TRACK
  124. echo "ONE ENG. SUB TRACK"
  125. encode "$tmpDIR/$fileNAME" "$workDIR/$fileNAME"
  126. else
  127. #TEST SUBTITLE TYPE; IF NOT PGS SKIP IT; FEEL FREE TO FILL IN
  128. if grep -qi "pgs" <<< $( $FFBIN/ffprobe -loglevel error -select_streams s \
  129. -show_entries stream=codec_name \
  130. -of csv=p=0 "$tmpDIR"/"$fileNAME" )
  131. then
  132. # MORE THAN ONE SUB TRACK; HAVE TO FIGURE OUT WHICH TO BURN
  133. unset streamFRAMES
  134. declare -a streamFRAMES
  135. #Presuming the one to burn-in is the one with less frames
  136. unset minFrames
  137. unset maxFrames
  138. unset indexITER
  139. unset minINDEX
  140. minFrames=0
  141. maxFrames=0
  142. indexITER=0
  143. minINDEX=0
  144. for index in ${streamNUMBERS[@]}
  145. do
  146. SUBINDEX=$(expr $index - ${streamNUMBERS[0]})
  147. currFrames=$( $FFBIN/ffprobe -loglevel error -select_streams s:$SUBINDEX \
  148. -show_entries stream_tags=NUMBER_OF_FRAMES-eng -of csv=p=0 \
  149. "$tmpDIR/$fileNAME")
  150. if [ $indexITER -lt 1 ]
  151. then
  152. minFrames=$currFrames
  153. maxFrames=$currFrames
  154. minINDEX=$index
  155. let ++indexITER
  156. elif [ $currFrames -lt $minFrames ]
  157. then
  158. minFrames=$currFrames
  159. minINDEX=$index
  160. let ++indexITER
  161. elif [ $currFrames -gt $maxFrames ]
  162. then
  163. maxFrames=$currFrames
  164. let ++indexITER
  165. fi
  166. done
  167. unset SUBTITLEINDEX
  168. SUBTITLEINDEX=$(expr $minINDEX - ${streamNUMBERS[0]})
  169. #TEST FRAMES IN SUB TRACK, IF < 15% MAX MOST LIKELY ISN'T FOR. AUD.
  170. #15% as LOTR dir. comm included, blows up the max number for them...
  171. currFrames=$( $FFBIN/ffprobe -loglevel error -select_streams s:$SUBTITLEINDEX \
  172. -show_entries stream_tags=NUMBER_OF_FRAMES-eng -of csv=p=0 \
  173. "$tmpDIR/$fileNAME")
  174. if [ $( echo "($currFrames / $maxFrames) < 0.25"|bc -l ) -gt 0 ]
  175. then
  176. echo "BURNING STREAM $SUBTITLEINDEX (STREAM $minINDEX) from $fileNAME"
  177. burnSubs "$tmpDIR/$fileNAME" "$tmpDIR/TMP$fileNAME" "$workDIR/$fileNAME" $SUBTITLEINDEX
  178. else
  179. echo "MIN. SUB TRACK ($SUBTITLEINDEX [$minINDEX])) DUR. > 25% FILM, NOT BURNING"
  180. encode "$tmpDIR/$fileNAME" "$workDIR/$fileNAME"
  181. fi
  182. else
  183. #TODO expand foreign scan for more than pgs subtitles Need ass and
  184. #subtitles filters; don't know how to differentiate at present time.
  185. #I'm actually kinda missing a good example; I'm sure they're in there
  186. #but I don't know which ones they are lol; lmk if you know one.
  187. echo "NOT A PGS SUBTITLE TYPE; PASSING ALL THROUGH, FUTURE DEV."
  188. encode "$tmpDIR/$fileNAME" "$workDIR/$fileNAME"
  189. fi
  190. fi
  191. else
  192. #ONE OR FEWER SUB TRACKS
  193. encode "$tmpDIR/$fileNAME" "$workDIR/$fileNAME"
  194. fi
  195. if [ $? != 0 ] || [ $( stat -c%s "$workDIR/$fileNAME" ) -eq 0 ]
  196. then
  197. #RUN FAILED (EITHER NONZERO EXIT OR THE FILE IS 0 BYTES LARGE)
  198. if [ $( echo "$HostName"|tr [a-z] [A-Z] ) != "LOCALHOST" ]
  199. then
  200. ssh $HostName <<< "echo $( echo $filePATH | sed "s/[!@#$%^&*( ;)-]/\\\&/g" )>>$hostFile"
  201. else
  202. echo "$filePATH">>$hostFile
  203. fi
  204. let ++k
  205. echo "RUN ($fileNAME) FAILED ($k/60)"
  206. if [ $( stat -c%s "$workDIR/$fileNAME" ) -eq 0 ]
  207. then
  208. rm "$workDIR"/"$fileNAME"
  209. fi
  210. else
  211. #UPLOAD AND REMOVE THE TRANSCODED FILE
  212. if [ $( echo "$HostName"|tr [a-z] [A-Z] ) != "LOCALHOST" ]
  213. then
  214. #scp "$workDIR/$fileNAME" $HostName:"$( echo $filePATH | sed "s/[][!@#$%^&*( ;)]/\\\&/g" )"
  215. scp "$workDIR/$fileNAME" $HostName:"$filePATH"
  216. else
  217. rsync -a --progress "$workDIR/$fileNAME" "$filePATH"
  218. fi
  219. if [ $? != 0 ]
  220. then
  221. echo "UPLOAD OF $filePATH FAILED; EXITING"
  222. if [ $( echo "$HostName"|tr [a-z] [A-Z] ) != "LOCALHOST" ]
  223. then
  224. ssh $HostName <<< "echo $( echo $filePATH | sed "s/[!@#$%^&*( ;)-]/\\\&/g" )>>$hostFile"
  225. else
  226. echo "$filePATH">>$hostFile
  227. fi
  228. exit 1
  229. else
  230. rm "$workDIR"/"$fileNAME"
  231. fi
  232. k=0
  233. fi
  234. #REMOVE THE TEMP FILE (if necessary)
  235. if ls "$workDIR"/"$fileNAME"
  236. then
  237. rm "$workDIR"/"$fileNAME"
  238. else
  239. echo "Workdir already cleaned"
  240. fi
  241. if ls "$tmpDIR"/"$fileNAME"
  242. then
  243. rm "$tmpDIR"/"$fileNAME"
  244. elif ls "$tmpDIR"/"TMP$fileNAME"
  245. then
  246. rm "$tmpDIR"/"TMP$fileNAME"
  247. else
  248. echo "Already removed $tmpDIR/$fileNAME?"
  249. fi
  250. else
  251. echo "OUT OF FILES!? (try number $j/50) ... sleeping 1 min"
  252. let ++j
  253. sleep 60
  254. fi
  255. #Increment if required
  256. if [ $iterLim == "true" ]
  257. then
  258. let --numIter
  259. fi
  260. let ++i
  261. echo "Done LOOP NUMBER $i!"
  262. done
  263. exit 0