Zach Isbach 3 年 前
親
コミット
d6efd2de18
4 ファイル変更、104 行追加、74 行削除
  1. 73 25
      encode.pl
  2. 25 47
      findRecode.sh
  3. 2 1
      folderToMKV.sh
  4. 4 1
      movInfo.pl

+ 73 - 25
encode.pl

@@ -9,12 +9,13 @@ use File::Basename;
 
 # Default configuration
 my $FORMAT        = 'av_mkv';
-my $AUDIO_BITRATE = 192;
 my $QUALITY       = 20;
 my $HD_QUALITY    = 22;
+my $NO_MIXDOWN    = 1;
 my $AUDIO_COPY    = 0;
 my $STEREO_ONLY   = 0;
 my $VIDEO_ONLY    = 0;
+my $AUDIO_BITRATE = undef();
 my $HEIGHT        = undef();
 my $WIDTH         = undef();
 my $AUDIO_EXCLUDE_REGEX =
@@ -26,8 +27,7 @@ my $SUB_INCLUDE_REGEX = '\b(?:English|Unknown|Closed\s+Captions)\b';
 my $FORCE_MP4         = 0;
 my $OUT_DIR           = undef();
 my $MIXDOWN_CODEC     = 'AAC';
-my $MIXDOWN_CHANNELS  = 2.0;
-my $AAC_ENCODER       = 'ffaac';
+my $MIXDOWN_CHANNELS  = 5.1;
 my $VIDEO_ENCODER     = 'x265';
 my %ENCODER_OPTS      = (
 	'x264' => [ '--encopts',        'b-adapt=2:rc-lookahead=50' ],
@@ -41,20 +41,15 @@ my $MIN_VIDEO_WIDTH = 100;
 my $MAX_CROP_DIFF   = .1;
 my $MAX_DURA_DIFF   = 5;
 my $NO_CROP         = 0;
-my @CODEC_ORDER     = ('DTS-HD', 'FLAC', 'TRUEHD', 'PCM', 'DTS', 'E-AC3', 'AC3', 'VORBIS', $MIXDOWN_CODEC, 'OTHER');
+my @CODEC_ORDER     = ('DTS-HD', 'FLAC', 'TRUEHD', 'AAC', 'PCM', 'DTS', 'E-AC3', 'AC3', 'VORBIS', 'OTHER');
 my $HB_EXEC         = $ENV{'HOME'} . '/bin/video/HandBrakeCLI';
 my $DEBUG           = 0;
 
 # General parameters for HandBrake
 # Someday we will also --use-opencl, but not today
 my @video_params = ('--markers', '--optimize', '--detelecine', '--decomb', '--auto-anamorphic');
-my @audio_params = ('--audio-copy-mask', 'dtshd,dts,truehd,eac3,ac3,aac', '--audio-fallback', 'eac3');
-
-# Use CoreAudio where available
-my ($OS) = POSIX::uname();
-if ($OS eq 'Darwin') {
-	$AAC_ENCODER = 'ca_aac';
-}
+# HD Audio: 'dtshd,dts,truehd,eac3,ac3,aac'
+my @audio_params = ('--audio-copy-mask', 'aac,dts,eac3,ac3', '--audio-fallback', 'aac');
 
 # Runtime debug mode
 if (defined($ENV{'DEBUG'}) && $ENV{'DEBUG'}) {
@@ -97,6 +92,7 @@ if ($ENV{'AUDIO_COPY'}) {
 # Allow AAC-only audio transfers (for use in mobile encoding)
 if ($ENV{'STEREO_ONLY'}) {
 	$STEREO_ONLY = 1;
+	$MIXDOWN_CHANNELS = 2.0;
 }
 
 # Allow MP4-only output format (for use in mobile encoding)
@@ -104,6 +100,11 @@ if ($ENV{'FORCE_MP4'}) {
 	$FORCE_MP4 = 1;
 }
 
+# Allow mixdown if requested
+if ($STEREO_ONLY || (defined($ENV{'NO_MIXDOWN'}) && !$ENV{'NO_MIXDOWN'})) {
+	$NO_MIXDOWN = 0;
+}
+
 # Allow overrides for video quality
 if ($ENV{'QUALITY'}) {
 	if (!($ENV{'QUALITY'} =~ /^\d+$/)) {
@@ -294,9 +295,6 @@ foreach my $title (keys(%titles)) {
 			print STDERR basename($0) . ': No audio detected in: ' . $in_file . ':' . $title . ". Skipping title...\n";
 			next;
 		}
-
-		# Set the bitrate for transcoded audio tracks
-		push(@audio, '--ab', $AUDIO_BITRATE);
 	}
 
 	# Set the video quality, using $HD_QUALITY for images larger than $HD_WIDTH (to allow lower quality on HD streams)
@@ -613,8 +611,8 @@ sub audioOptions($) {
 		return;
 	}
 
-	# Clear the mixdown selection if we're copying audio
-	if ($AUDIO_COPY) {
+	# Clear the mixdown track if not required
+	if ($AUDIO_COPY || $NO_MIXDOWN) {
 		$mixdown = undef();
 	}
 
@@ -622,21 +620,20 @@ sub audioOptions($) {
 	my @audio_tracks = ();
 	if (defined($mixdown) && $mixdown > 0) {
 		if ($DEBUG) {
-			print STDERR 'Using track ' . $mixdown . " as default AAC audio\n";
-			if ($tracks{$mixdown}->{'channels'} > 2) {
-				push(@retval, '--mixdown', 'dpl2');
-				print STDERR "\tMixing down with Dolby Pro Logic II encoding\n";
-			}
+			print STDERR 'Using track ' . $mixdown . " as mixdown audio (" . $MIXDOWN_CODEC . ")\n";
 		}
-		my %track = ('index' => $mixdown, 'encoder' => $AAC_ENCODER);
+		my %track = ('index' => $mixdown, 'encoder' => codecToEncoder($MIXDOWN_CODEC));
 		push(@audio_tracks, \%track);
+
+		# Include mixdown params for this track
+		push(@retval, mixdownParams($tracks{$mixdown}->{'channels'}));
 	}
 
 	# Keep all other audio tracks, unless STEREO_ONLY is set
 	if (!$STEREO_ONLY) {
 
-		# Passthru DTS-MA, DTS, AC3, and AAC
-		# Keep other audio tracks, but recode to AAC (using Handbrake's audio-copy-mask/audio-fallback feature)
+		# Passthru DTS, AC3, and AAC
+		# Keep other audio tracks, but recode to the mixdown codec (using Handbrake's audio-copy-mask/audio-fallback feature)
 		foreach my $index (keys(%tracks)) {
 			if (defined($mixdown) && $mixdown == $index && $tracks{$index}->{'channels'} <= $MIXDOWN_CHANNELS) {
 				if ($DEBUG) {
@@ -692,7 +689,7 @@ sub audioOptions($) {
 	# Consolidate from the hashes
 	my @output_tracks   = ();
 	my @output_encoders = ();
-	foreach my $track (@audio_tracks) {
+	foreach my $track (sort(@audio_tracks)) {
 		push(@output_tracks,   $track->{'index'});
 		push(@output_encoders, $track->{'encoder'});
 	}
@@ -884,6 +881,57 @@ sub findBestAudioTrack($$) {
 	return $best;
 }
 
+sub codecToEncoder($) {
+	my ($codec) = @_;
+	my $encoder = undef();
+
+	if ($codec eq 'AAC') {
+		# Use CoreAudio where available
+		my ($OS) = POSIX::uname();
+		$encoder = ($OS eq 'Darwin') ? 'ca_aac' : 'ffaac';
+	} else {
+		my $t = lc($codec);
+		$t =~ s/[\w]//g;
+		$encoder = $t;
+	}
+
+	return $encoder;
+}
+
+sub mixdownParams() {
+	my ($channels) = @_;
+	my $mixdown = '7point1';
+	my $bitrate = 512;
+
+	# Don't encode more than we need
+	if ($MIXDOWN_CHANNELS < $channels) {
+		$channels = $MIXDOWN_CHANNELS;
+	}
+
+	# Pick mixdown models and appropriate bitrates (for AAC)
+	if ($channels <= 2.0) {
+		$mixdown = 'dpl12';
+		$bitrate = 128;
+	} elsif ($channels <= 5.1) {
+		$mixdown = '5point1';
+		$bitrate = 384;
+	} elsif ($channels <= 6.1) {
+		$mixdown = '6point1';
+		$bitrate = 448;
+	}
+
+	# Allow user override of the bitrate
+	if ($AUDIO_BITRATE) {
+		$bitrate = $AUDIO_BITRATE;
+	}
+
+	if ($DEBUG) {
+		print STDERR "\tMixdown to " . $MIXDOWN_CHANNELS . " channels at " . $bitrate .
+			" kbps with " . $mixdown . " encoding\n";
+	}
+	return ('--mixdown', $mixdown, '--ab', $bitrate);
+}
+
 sub isValidSubLanguage($) {
 	my ($lang, $iso) = @_;
 

+ 25 - 47
findRecode.sh

@@ -3,13 +3,10 @@
 # Parameters
 FOLDER="`~/bin/video/mediaPath`"
 if [ -z "${MIN_RATE}" ]; then
-	MIN_RATE=275000
+	MIN_RATE=20000
 fi
 if [ -z "${MIN_SIZE}" ]; then
-	MIN_SIZE="425M"
-fi
-if [ -z "${MIN_HEIGHT}" ]; then
-	MIN_HEIGHT=500
+	MIN_SIZE="100M"
 fi
 if [ -z "${NAME_REGEX}" ]; then
 	NAME_REGEX="\.(mov|avi|mkv|mp4|ts|mpg|mpeg|m4v)$"
@@ -18,18 +15,18 @@ if [ -z "${CODEC_REGEX}" ]; then
 	CODEC_REGEX='^(x264|Nx265)'
 fi
 if [ -z "${CODEC_BUILD_REGEX}" ]; then
-	CODEC_BUILD_REGEX='^(x264 - core (79|112|120|125|129|130|142|148)|Nx265 \(build 95\))'
+	CODEC_BUILD_REGEX='^(x264 - core (79|112|120|125|129|130|142|148)|Nx265 \(build (95|206)\))'
 fi
 SCAN_DEPTH_FAST=10
 SCAN_DEPTH_SLOW=100
+STRINGS_MINLEN=100
 
 # Standard overrides for the current official archive format
 if [ -n "${FULL_ARCHIVE}" ]; then
 	MIN_SIZE=50M
 	MIN_RATE=100
-	MIN_HEIGHT=100
-	CODEC_BUILD_REGEX='Nx265 \(build 95\)'
-	# Don't set the codec regex so we get faster scans against
+	CODEC_BUILD_REGEX='Nx265 \(build (95|206)\)'
+	# Don't limit the codec regex so we get faster scans against
 	# things that we did encode but aren't in the archive format
 	#CODEC_REGEX='^Nx265' 
 fi
@@ -38,22 +35,6 @@ fi
 if [ -n "${1}" ]; then
 	FOLDER="${1}"
 fi
-if [ -n "${2}" ]; then
-	MIN_SIZE="${2}"
-	echo "Deprecated: MIN_SIZE" 1>&2
-fi
-if [ -n "${3}" ]; then
-	MIN_RATE="${3}"
-	echo "Deprecated: MIN_RATE" 1>&2
-fi
-if [ -n "${4}" ]; then
-	MIN_HEIGHT="${4}"
-	echo "Deprecated: MIN_HEIGHT" 1>&2
-fi
-if [ -n "${5}" ]; then
-	NAME_REGEX="${5}"
-	echo "Deprecated: NAME_REGEX" 1>&2
-fi
 
 # Name-based paramters
 ZERO=0
@@ -84,6 +65,9 @@ if [ -n "${LAST_RECODE_FILE}" ]; then
 	LAST_RECODE_TMP="`mktemp "${LAST_RECODE_FILE}.XXXXXX" 2>/dev/null`"
 fi
 
+# We need a strings scratch file, apparently, since strings doesn't handle STDIN correctly
+STRINGS_TMP="`mktemp -t findRecode`"
+
 # Loop with newline-as-IFS
 OLDIFS="${IFS}"
 IFS=$'\n'
@@ -100,18 +84,23 @@ for i in ${FILES}; do
 	fi
 
 	# Find the x264/Nx265 header, if present. Scan deeper if the fast scan fails.
-	STRINGS="`head -c $(( $SCAN_DEPTH_FAST * 1024 * 1024 )) "${i}" | strings -n 100`"
-	if ! echo "${STRINGS}" | grep -Eq "${CODEC_REGEX}"; then
-		STRINGS="`head -c $(( $SCAN_DEPTH_SLOW * 1024 * 1024 )) "${i}" | strings -n 100`"
+	head -c $(( $SCAN_DEPTH_FAST * 1024 * 1024 )) "${i}" | strings -n "${STRINGS_MINLEN}" > "${STRINGS_TMP}"
+	if ! strings -n 1 "${STRINGS_TMP}" | grep -Eq "${CODEC_REGEX}"; then
+		head -c $(( $SCAN_DEPTH_SLOW * 1024 * 1024 )) "${i}" | strings -n "${STRINGS_MINLEN}" > "${STRINGS_TMP}"
+	fi
+
+	# Check for binary junk that makes grep angry
+	if ! head -c 1 "${STRINGS_TMP}" | grep -q '\w'; then
+		STR_CLEAN="`mktemp -t findRecode.clean`"
+		cat "${STRINGS_TMP}" | cut -b 3- > "${STR_CLEAN}"
+		mv "${STR_CLEAN}" "${STRINGS_TMP}"
 	fi
 
 	# Check for our particular HandBrake parameters
 	HANDBRAKE=0
-	if echo "${STRINGS}" | grep -Eq 'crf=2[0-5]\.[0-9]'; then
-		if echo "${STRINGS}" | grep -Eq "${CODEC_BUILD_REGEX}"; then
-			HANDBRAKE=1
-		fi
-	elif echo "${STRINGS}" | grep -q HandBrake; then
+	if strings -n 1 "${STRINGS_TMP}" | grep -Eq "${CODEC_BUILD_REGEX}"; then
+		HANDBRAKE=1
+	elif strings -n 1 "${STRINGS_TMP}" | grep -q HandBrake; then
 		echo "Matched literal 'HandBrake': ${i}" 1>&2
 		HANDBRAKE=1
 	fi
@@ -121,20 +110,6 @@ for i in ${FILES}; do
 		continue
 	fi
 
-	# We only care about "big" videos
-	# Movies with no known height should be left alone
-	# Movies with a "0" height can be assumed to be tall enough
-	HEIGHT="`~/bin/video/movInfo.pl "${i}" VIDEO_HEIGHT 2>/dev/null`"
-	if [ -z "${HEIGHT}" ]; then
-		HEIGHT=1
-	fi
-	if [ $HEIGHT -eq 0 ]; then
-		HEIGHT=$MIN_HEIGHT
-	fi
-	if [ $HEIGHT -lt $MIN_HEIGHT ]; then
-		continue
-	fi
-
 	# Skip files with low bitrates
 	SIZE="`stat -f %z "${i}" 2>/dev/null`"
 	if [ -z "${SIZE}" ]; then
@@ -159,6 +134,9 @@ for i in ${FILES}; do
 done
 IFS="${OLDIFS}"
 
+# Remove the strings temp file
+rm -f "${STRINGS_TMP}"
+
 # Move the temporary timestamp file into place
 if [ -n "${LAST_RECODE_TMP}" ]; then
 	mv "${LAST_RECODE_TMP}" "${LAST_RECODE_FILE}"

+ 2 - 1
folderToMKV.sh

@@ -22,7 +22,8 @@ fi
 if ~/bin/video/canRecode.sh; then
 
 	# Prefer recoding to rewrapping if the file is overrate
-	~/bin/video/findRecode0 "${inFolder}" | xargs -0 -n1 ~/bin/video/recode
+	NO_LAST_RECODE_FILE=1 ~/bin/video/findRecode0 "${inFolder}" | \
+		xargs -0 -n1 ~/bin/video/recode
 
 	# MPEGs must be recoded, not just re-wrapped
 	for i in "${inFolder}/"*.[mM][pP][gG] "${inFolder}/"*.[mM][pP][eE][gG]; do

+ 4 - 1
movInfo.pl

@@ -27,7 +27,7 @@ my $data = run_mplayer(@args);
 
 # Sanity check
 if (!defined($data->{'VIDEO_FORMAT'}) || length($data->{'VIDEO_FORMAT'}) < 1) {
-	die(basename($0) . ': Unable to find any video streams in: ' . $infile . "\n");
+	die(basename($0) . ': Unable to find video streams in: ' . $infile . "\n");
 }
 
 # Duplicate the audio data for track 0 with the appropriate index
@@ -101,5 +101,8 @@ sub run_mplayer(@) {
 		close($child_out);
 		alarm(0);
 	};
+	if ($@ ne "") {
+		print(STDERR $@);
+	}
 	return \%data;
 }