findRecode.sh 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #!/bin/bash
  2. # Parameters
  3. FOLDER="`~/bin/video/mediaPath`"
  4. if [ -z "${MIN_RATE}" ]; then
  5. MIN_RATE=200000
  6. fi
  7. if [ -z "${MIN_SIZE}" ]; then
  8. MIN_SIZE="250M"
  9. fi
  10. if [ -z "${MIN_HEIGHT}" ]; then
  11. MIN_HEIGHT=500
  12. fi
  13. if [ -z "${NAME_REGEX}" ]; then
  14. NAME_REGEX="\.(mov|avi|mkv|mp4|ts|mpg|mpeg|m4v)$"
  15. fi
  16. if [ -z "${CODEC_REGEX}" ]; then
  17. CODEC_REGEX='^(x264|Nx265)'
  18. fi
  19. if [ -z "${CODEC_BUILD_REGEX}" ]; then
  20. CODEC_BUILD_REGEX='^(x264 - core (79|112|120|125|129|130|142|148)|Nx265 \(build 95\))'
  21. fi
  22. SCAN_DEPTH_FAST=10
  23. SCAN_DEPTH_SLOW=100
  24. STRINGS_MINLEN=100
  25. # Standard overrides for the current official archive format
  26. if [ -n "${FULL_ARCHIVE}" ]; then
  27. MIN_SIZE=50M
  28. MIN_RATE=100
  29. MIN_HEIGHT=100
  30. CODEC_BUILD_REGEX='Nx265 \(build 95\)'
  31. # Don't limit the codec regex so we get faster scans against
  32. # things that we did encode but aren't in the archive format
  33. #CODEC_REGEX='^Nx265'
  34. fi
  35. # Command-line overrides
  36. if [ -n "${1}" ]; then
  37. FOLDER="${1}"
  38. fi
  39. if [ -n "${2}" ]; then
  40. MIN_SIZE="${2}"
  41. echo "Deprecated: MIN_SIZE" 1>&2
  42. fi
  43. if [ -n "${3}" ]; then
  44. MIN_RATE="${3}"
  45. echo "Deprecated: MIN_RATE" 1>&2
  46. fi
  47. if [ -n "${4}" ]; then
  48. MIN_HEIGHT="${4}"
  49. echo "Deprecated: MIN_HEIGHT" 1>&2
  50. fi
  51. if [ -n "${5}" ]; then
  52. NAME_REGEX="${5}"
  53. echo "Deprecated: NAME_REGEX" 1>&2
  54. fi
  55. # Name-based paramters
  56. ZERO=0
  57. if basename "${0}" | grep -q '0'; then
  58. ZERO=1
  59. fi
  60. # Sanity check
  61. if [ ! -d "${FOLDER}" ]; then
  62. echo "Usage: `basename "${0}"` [folder]" 1>&2
  63. exit 1
  64. fi
  65. # Derived parameters
  66. LAST_RECODE_FILE="`(cd "${FOLDER}" && pwd)`/.lastFindRecode"
  67. # Environmental parameters
  68. if [ -n "${NO_LAST_RECODE_FILE}" ]; then
  69. LAST_RECODE_FILE=""
  70. fi
  71. # Find large video files that match the regex filter
  72. FILES="`find "${FOLDER}" -maxdepth 1 -type f -size "+${MIN_SIZE}" | grep -iE "${NAME_REGEX}"`"
  73. # Record the last scan start time, in a temp file
  74. LAST_RECODE_TMP=""
  75. if [ -n "${LAST_RECODE_FILE}" ]; then
  76. LAST_RECODE_TMP="`mktemp "${LAST_RECODE_FILE}.XXXXXX" 2>/dev/null`"
  77. fi
  78. # We need a strings scratch file, apparently, since strings doesn't handle STDIN correctly
  79. STRINGS_TMP="`mktemp -t findRecode`"
  80. # Loop with newline-as-IFS
  81. OLDIFS="${IFS}"
  82. IFS=$'\n'
  83. for i in ${FILES}; do
  84. # Skip invalid files
  85. if [ -z "${i}" ] || [ ! -r "${i}" ] || basename "${i}" | grep -q '^\._'; then
  86. continue
  87. fi
  88. # Skip files older than the LAST_RECODE_FILE mtime
  89. if [ -n "${LAST_RECODE_FILE}" ] && [ -f "${LAST_RECODE_FILE}" ] && [ "${i}" -ot "${LAST_RECODE_FILE}" ]; then
  90. continue
  91. fi
  92. # Find the x264/Nx265 header, if present. Scan deeper if the fast scan fails.
  93. head -c $(( $SCAN_DEPTH_FAST * 1024 * 1024 )) "${i}" | strings -n "${STRINGS_MINLEN}" > "${STRINGS_TMP}"
  94. if ! strings -n 1 "${STRINGS_TMP}" | grep -Eq "${CODEC_REGEX}"; then
  95. head -c $(( $SCAN_DEPTH_SLOW * 1024 * 1024 )) "${i}" | strings -n "${STRINGS_MINLEN}" > "${STRINGS_TMP}"
  96. fi
  97. # Check for our particular HandBrake parameters
  98. HANDBRAKE=0
  99. if strings -n 1 "${STRINGS_TMP}" | grep -Eq 'crf=2[0-5]\.[0-9]'; then
  100. if strings -n 1 "${STRINGS_TMP}" | grep -Eq "${CODEC_BUILD_REGEX}"; then
  101. HANDBRAKE=1
  102. fi
  103. elif strings -n 1 "${STRINGS_TMP}" | grep -q HandBrake; then
  104. echo "Matched literal 'HandBrake': ${i}" 1>&2
  105. HANDBRAKE=1
  106. fi
  107. # We do not want to recode videos that we already encoded
  108. if [ $HANDBRAKE -eq 1 ]; then
  109. continue
  110. fi
  111. # We only care about "big" videos
  112. # Movies with no known height should be left alone
  113. # Movies with a "0" height can be assumed to be tall enough
  114. HEIGHT="`~/bin/video/movInfo.pl "${i}" VIDEO_HEIGHT 2>/dev/null`"
  115. if [ -z "${HEIGHT}" ]; then
  116. HEIGHT=1
  117. fi
  118. if [ $HEIGHT -eq 0 ]; then
  119. HEIGHT=$MIN_HEIGHT
  120. fi
  121. if [ $HEIGHT -lt $MIN_HEIGHT ]; then
  122. continue
  123. fi
  124. # Skip files with low bitrates
  125. SIZE="`stat -f %z "${i}" 2>/dev/null`"
  126. if [ -z "${SIZE}" ]; then
  127. SIZE=1
  128. fi
  129. LENGTH="`~/bin/video/movInfo.pl "${i}" LENGTH 2>/dev/null | sed 's%\..*$%%'`"
  130. if [ -z "${LENGTH}" ] || [ $LENGTH -eq 0 ]; then
  131. LENGTH=1
  132. fi
  133. RATE=$(( $SIZE / $LENGTH ))
  134. if [ $RATE -le $MIN_RATE ]; then
  135. continue
  136. fi
  137. # If we're still around, the file matched all criteria
  138. if [ $ZERO -gt 0 ]; then
  139. echo -en "${i}\0"
  140. else
  141. echo "${i}"
  142. fi
  143. done
  144. IFS="${OLDIFS}"
  145. # Remove the strings temp file
  146. rm -f "${STRINGS_TMP}"
  147. # Move the temporary timestamp file into place
  148. if [ -n "${LAST_RECODE_TMP}" ]; then
  149. mv "${LAST_RECODE_TMP}" "${LAST_RECODE_FILE}"
  150. fi