findRecode.sh 3.7 KB

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