Просмотр исходного кода

Merge branch 'master' of github.com:profplump/UberZach-Video

Zachary Kotlarek 13 лет назад
Родитель
Сommit
376cae7b1f
6 измененных файлов с 241 добавлено и 85 удалено
  1. 1 1
      checkLoad.sh
  2. 110 23
      encode.pl
  3. 7 7
      findTorrent.pl
  4. 23 4
      mountMedia
  5. 15 1
      sync.sh
  6. 85 49
      transmission.pl

+ 1 - 1
checkLoad.sh

@@ -8,7 +8,7 @@ if [ $LOAD -gt $(( 2 * $CPU_COUNT )) ]; then
 fi
 
 # Bail if WoW is running
-if ps auwx | grep -v grep | grep -q "World of Warcraft/World of Warcraft-64.app/Contents/MacOS/World of Warcraft-64"; then
+if ps auwx | grep -v grep | grep -q "World of Warcraft-64"; then
 	exit 1
 fi
 

+ 110 - 23
encode.pl

@@ -13,9 +13,10 @@ my $QUALITY             = 20;
 my $HD_QUALITY          = 22;
 my $AUDIO_COPY          = 0;
 my $STEREO_ONLY         = 0;
+my $VIDEO_ONLY          = 0;
 my $HEIGHT              = undef();
 my $WIDTH               = undef();
-my $AUDIO_EXCLUDE_REGEX = '\b(?:Chinese|Espanol|Francais|Japanese|Korean|Portugues|Thai)\b';
+my $AUDIO_EXCLUDE_REGEX = '\b(?:Chinese|Deutsch|Espanol|Francais|Japanese|Korean|Portugues|Thai)\b';
 my $SUB_INCLUDE_REGEX   = '\b(?:English|Unknown|Closed\s+Captions)\b';
 my $FORCE_MP4           = 0;
 my $OUT_DIR             = undef();
@@ -70,6 +71,11 @@ if ($ENV{'STEREO_ONLY'}) {
 	$STEREO_ONLY = 1;
 }
 
+# Allow video-only transfers
+if ($ENV{'VIDEO_ONLY'}) {
+	$VIDEO_ONLY = 1;
+}
+
 # Allow MP4-only output format (for use in mobile encoding)
 if ($ENV{'FORCE_MP4'}) {
 	$FORCE_MP4 = 1;
@@ -117,6 +123,9 @@ if (!defined($in_file) || length($in_file) < 1 || !-r $in_file) {
 if ($AUDIO_COPY && $STEREO_ONLY) {
 	die(basename($0) . ": AUDIO_COPY and STEREO_ONLY are mutually exclusive\n");
 }
+if ($VIDEO_ONLY && ($AUDIO_COPY || $STEREO_ONLY)) {
+	die(basename($0) . ": VIDEO_ONLY and AUDIO_COPY or STEREO_ONLY are mutually exclusive\n");
+}
 
 # Scan for title/track info
 my %titles = &scan($in_file);
@@ -202,10 +211,8 @@ foreach my $title (keys(%titles)) {
 	# Reset
 	$FORMAT = $format_default;
 
-	# Parse the title's audio and subtitle tracks
-	my $scan  = $titles{$title};
-	my @audio = &audioOptions($scan);
-	my @subs  = &subOptions($scan);
+	# Select a title
+	my $scan = $titles{$title};
 
 	# Skip tracks that have no video
 	if (scalar(@{ $scan->{'size'} }) < 2 || $scan->{'size'}[0] < $MIN_VIDEO_WIDTH) {
@@ -213,14 +220,23 @@ foreach my $title (keys(%titles)) {
 		next;
 	}
 
-	# Skip tracks that have no audio
-	if (scalar(@{ $scan->{'audio'} }) < 1 || scalar(@audio) < 1) {
-		print STDERR basename($0) . ': No audio detected in: ' . $in_file . ':' . $title . ". Skipping title...\n";
-		next;
-	}
+	# Parse subtitle tracks
+	my @subs = &subOptions($scan);
+
+	# Parse audio tracks, unless we're in VIDEO_ONLY mode
+	my @audio = ();
+	if (!$VIDEO_ONLY) {
+		@audio = &audioOptions($scan);
 
-	# Set the audio quality for re-encoded tracks
-	push(@audio, '--ab', $AUDIO_BITRATE);
+		# Skip tracks that have no audio
+		if (scalar(@{ $scan->{'audio'} }) < 1 || scalar(@audio) < 1) {
+			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)
 	my $title_quality = $QUALITY;
@@ -282,10 +298,14 @@ foreach my $title (keys(%titles)) {
 	push(@args, '--quality', $title_quality);
 	push(@args, '--crop',    join(':', @{ $scan->{'crop'} }));
 	push(@args, @video_params);
-	push(@args, @audio_params);
-	push(@args, @audio);
 	push(@args, @subs);
 
+	# Include audio unless specifically excluded
+	if (!$VIDEO_ONLY) {
+		push(@args, @audio_params);
+		push(@args, @audio);
+	}
+
 	if ($DEBUG) {
 		print STDERR "\n" . join(' ', @args) . "\n\n";
 	}
@@ -396,7 +416,7 @@ sub audioOptions($) {
 	# Type the audio tracks
 	my %tracks = ();
 	foreach my $track (@{ $scan->{'audio'} }) {
-		my ($language, $codec, $note, $channels, $iso) = $track->{'description'} =~ /^([^\(]+)\s+\(([^\)]+)\)\s+(?:\(([^\)]*Commentary[^\)]*)\)\s+)?\((\d+\.\d+\s+ch|Dolby\s+Surround)\)(?:\s+\(iso(\d+\-\d+)\:\s+\w\w\w\))?/;
+		my ($language, $codec, $note, $channels, $iso, $specs) = $track->{'description'} =~ /^([^\(]+)\s+\(([^\)]+)\)\s+(?:\(([^\)]*Commentary[^\)]*)\)\s+)?\((\d+\.\d+\s+ch|Dolby\s+Surround)\)(?:\s+\(iso(\d+\-\d+)\:\s+\w\w\w\))?(?:,\s+(.*))?/;
 		if (!defined($channels)) {
 			print STDERR 'Could not parse audio description: ' . $track->{'description'} . "\n";
 			next;
@@ -428,8 +448,31 @@ sub audioOptions($) {
 			}
 		}
 
+		# Standardize the specs
+		my $bitrate    = 0;
+		my $samplerate = 0;
+		if (!$specs) {
+			$specs = '';
+		}
+		if ($specs =~ /(\d+)bps/) {
+			$bitrate = $1 / 1000;
+		} elsif ($specs =~ /(\d+)\s*kb\/s/) {
+			$bitrate = $1;
+		}
+		if ($specs =~ /(\d+)Hz/) {
+			$samplerate = $1;
+		}
+
 		# Push all parsed data into the array
-		my %data = ('language' => $language, 'codec' => $codec, 'channels' => $channels, 'iso' => $iso, 'note' => $note);
+		my %data = (
+			'language'   => $language,
+			'codec'      => $codec,
+			'channels'   => $channels,
+			'iso'        => $iso,
+			'note'       => $note,
+			'bitrate'    => $bitrate,
+			'samplerate' => $samplerate,
+		);
 		$tracks{ $track->{'index'} } = \%data;
 
 		# Print what we found
@@ -508,7 +551,7 @@ sub audioOptions($) {
 		foreach my $index (keys(%tracks)) {
 			if (defined($mixdown) && $mixdown == $index && $tracks{$index}->{'channels'} <= $MIXDOWN_CHANNELS) {
 				if ($DEBUG) {
-					print STDERR 'Skipping recode of track ' . $index . ' since it is already used as the default track and contains only ' . $tracks{$index}->{'channels'} . " channels\n";
+					print STDERR 'Skipping passthru of track ' . $index . ' since it is already used as the mixdown track and contains only ' . $tracks{$index}->{'channels'} . " channels\n";
 				}
 				next;
 			} elsif (!$tracks{$index}->{'codec'}) {
@@ -673,9 +716,10 @@ sub scan($) {
 
 sub findBestAudioTrack($$) {
 	my ($tracks, $codec) = @_;
-	my $best     = undef();
-	my $channels = 0;
+	my $best = undef();
+	my @available = ();
 
+	# Find available tracks
 	for my $index (keys(%{$tracks})) {
 		my $track = $tracks->{$index};
 
@@ -689,13 +733,56 @@ sub findBestAudioTrack($$) {
 			next;
 		}
 
-		# Find the track with the most channels (Ófirst wins)
-		if (!defined($best) || $track->{'channels'} > $channels) {
-			$best     = $index;
-			$channels = $track->{'channels'};
+		push(@available, $index);
+	}
+	if (scalar(@available) < 1) {
+		return $best;
+	}
+
+	# Find the tracks with the most channels
+	{
+		my @most     = ();
+		my $channels = 0;
+		foreach my $index (@available) {
+			my $track = $tracks->{$index};
+			if ($track->{'channels'} > $channels) {
+				@most     = ($index);
+				$channels = $track->{'channels'};
+			} elsif ($track->{'channels'} == $channels) {
+				push(@most, $index);
+			}
 		}
+		@available = @most;
+	}
+	if (scalar(@available) < 1) {
+		return $best;
 	}
 
+	# Find the tracks with the highest bitrate
+	{
+		my @highest = ();
+		my $bitrate = 0;
+		foreach my $index (@available) {
+			my $track = $tracks->{$index};
+			if ($track->{'bitrate'} > $bitrate) {
+				@highest = ($index);
+				$bitrate = $track->{'bitrate'};
+			} elsif ($track->{'bitrate'} == $bitrate) {
+				push(@highest, $index);
+			}
+		}
+		@available = @highest;
+	}
+	if (scalar(@available) < 1) {
+		return $best;
+	}
+
+	# Find the track if the lowest index
+	foreach my $index (@available) {
+		if (!defined($best) || $index < $best) {
+			$best = $index;
+		}
+	}
 	return $best;
 }
 

+ 7 - 7
findTorrent.pl

@@ -14,7 +14,7 @@ my $NEXT_EPISODES       = 3;
 my $TV_DIR = `~/bin/video/mediaPath` . '/TV';
 
 # Search parameters
-my $PROTOCOL = 'https';
+my $PROTOCOL = 'http';
 my %ENABLE_SOURCE = ('TPB' => 1, 'ISO' => 0);
 
 # Selection parameters
@@ -29,7 +29,7 @@ my $SEED_RATIO_COUNT = 10;
 # App config
 my $DELAY   = 4;
 my $TIMEOUT = 15;
-my $UA      = 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_5; en-us) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1';
+my $UA      = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71';
 
 # Includes
 use JSON;
@@ -57,13 +57,13 @@ if ($ENV{'NO_QUALITY_CHECKS'}) {
 if ($ENV{'MORE_NUMBER_FORMATS'}) {
 	$MORE_NUMBER_FORMATS = 1;
 }
-if ($ENV{'MIN_DAYS_BACK'}) {
+if (defined($ENV{'MIN_DAYS_BACK'})) {
 	$MIN_DAYS_BACK = $ENV{'MIN_DAYS_BACK'};
 }
-if ($ENV{'MAX_DAYS_BACK'}) {
+if (defined($ENV{'MAX_DAYS_BACK'})) {
 	$MAX_DAYS_BACK = $ENV{'MAX_DAYS_BACK'};
 }
-if ($ENV{'NEXT_EPISODES'}) {
+if (defined($ENV{'NEXT_EPISODES'})) {
 	$NEXT_EPISODES = $ENV{'NEXT_EPISODES'};
 }
 
@@ -82,7 +82,7 @@ my %SOURCES = ();
 if ($ENABLE_SOURCE{'TPB'}) {
 
 	# Available TPB proxies, in order of preference
-	my @TPBs = ('thepiratebay.sx/search/', 'tpb.jasohack.com/index.php?loadurl=/search/', 'tpb.allestec.com/index.php?loadurl=/search/');
+	my @TPBs = ('thepiratebay.se/search/', 'pirateproxy.se/search/', 'tpb.unblocked.co/search/');
 
 	# Automatically select a TPB proxy that returns a search page
 	my $search_url = '';
@@ -465,8 +465,8 @@ if (scalar(@urls) < 1) {
 						if ($source->{'search_suffix'}) {
 							$url .= $source->{'search_suffix'};
 						}
+						push(@urls, $url);
 					}
-					push(@urls, $url);
 
 					# SXX EYY
 					$url = $PROTOCOL . '://' . $source->{'search_url'} . $quote . $urlShow . $quote . '+s' . $season_long . '+e' . $episode_long;

+ 23 - 4
mountMedia

@@ -1,11 +1,30 @@
 #!/bin/bash
 
+# Ensure we have a valid TMPDIR
+if [ ! -d "${TMPDIR}" ]; then
+        TMPDIR="`getconf DARWIN_USER_TEMP_DIR 2>/dev/null`"
+        if [ ! -d "${TMPDIR}" ]; then
+                TMPDIR="/var/tmp"
+        fi
+        if [ ! -d "${TMPDIR}" ]; then
+                TMPDIR="/tmp"
+        fi
+fi
+
+# Config
 HOST="vera.uberzach.com"
+SHARE="media"
 LOCK="${TMPDIR}/mountMedia.mounting"
+REMOTE_USER="${USER}"
+
+# Hack for mismatched usernames
+if [ "${USER}" == "tv" ]; then
+	REMOTE_USER="atv"
+fi
 
 function findMedia {
 	MEDIA=""
-	for i in /Volumes/media*; do
+	for i in "/Volumes/${SHARE}"*; do
 		if [ -d "${i}" ] && [ -d "${i}/TV" ]; then
 			MEDIA="${i}"
 		fi
@@ -36,7 +55,7 @@ if [ -z "${MEDIA}" ]; then
 	fi
 	if [ $LOCKED -eq 0 ]; then
 		echo $$ > "${LOCK}"
-		osascript -e 'tell application "Finder" to mount volume "smb://atv@'"${HOST}"'/media"'
+		osascript -e 'tell application "Finder" to mount volume "smb://'"${REMOTE_USER}@${HOST}/${SHARE}"'"'
 		sleep 5
 		rm -f "${LOCK}"
 	fi
@@ -46,12 +65,12 @@ fi
 findMedia
 if [ -n "${MEDIA}" ]; then
 	if [ -d /mnt ]; then
-		if [ -h /mnt/media ]; then
+		if [ -e /mnt/media ] || [ -h /mnt/media ]; then
 			rm -f /mnt/media
 		fi
 		ln -s "${MEDIA}" /mnt/media
 	fi
-	if [ -e "${HOME}/media" ]; then
+	if [ -e "${HOME}/media" ] || [ -h "${HOME}/media" ]; then
 		rm -f "${HOME}/media"
 		ln -s "${MEDIA}" "${HOME}/media"
 	fi

+ 15 - 1
sync.sh

@@ -1,5 +1,11 @@
 #!/bin/bash
 
+# Ensure the media share is mounted
+if ! ~/bin/video/isMediaMounted; then
+	echo 'Media share not available' 1>&2
+	exit 1
+fi
+
 # Config
 BASE_LOCAL="`~/bin/video/mediaPath`"
 BASE_REMOTE="/Volumes/Bitcasa Infinite Drive"
@@ -23,6 +29,11 @@ if [ -z "${SUB_DIR}" ] || [ $NUM_FILES -lt 1 ] || [ $DELAY_DAYS -lt 1 ]; then
 	exit 1
 fi
 
+# Bail if the load is high
+if ! ~/bin/video/checkLoad.sh; then
+	exit 0
+fi
+
 # Allow usage with absolute local paths
 if [ "`echo "${SUB_DIR}" | head -c 1`" == '/' ]; then
 	BASE_LOCAL="`dirname "${SUB_DIR}"`"
@@ -99,7 +110,10 @@ for (( i=1; i<=${NUM_FILES}; i++ )); do
 
 	# Determine the action (i.e. copy to or delete from remote)
 	if [ "${ACTION}" == '+' ]; then
-		if [ -d "${PATH_REMOTE}" ]; then
+		if [ -n "${NO_DELETE}" ]; then
+			# Do nothing
+			true
+		elif [ -d "${PATH_REMOTE}" ]; then
 			echo "Removing directory: ${FILE}"
 			rmdir "${PATH_REMOTE}"
 		elif [ -f "${PATH_REMOTE}" ]; then

+ 85 - 49
transmission.pl

@@ -23,18 +23,20 @@ sub unrar($$);
 sub localSeriesCleanup($);
 sub seriesCleanup($);
 sub readDir($$);
+sub findMediaFiles($$);
 sub runAndCheck(@);
 
 # Parameters
-my $maxAge        = 2.5 * 86400;
-my $tvDir         = `~/bin/video/mediaPath` . '/TV';
-my $monitoredExec = '/Users/profplump/bin/video/torrentMonitored.pl';
-my $host          = 'http://localhost:9091';
-my $url           = $host . '/transmission/rpc';
-my $content       = '{"method":"torrent-get","arguments":{"fields":["hashString","id","addedDate","comment","creator","dateCreated","isPrivate","name","totalSize","pieceCount","pieceSize","downloadedEver","error","errorString","eta","haveUnchecked","haveValid","leftUntilDone","metadataPercentComplete","peersConnected","peersGettingFromUs","peersSendingToUs","rateDownload","rateUpload","recheckProgress","sizeWhenDone","status","trackerStats","uploadedEver","uploadRatio","seedRatioLimit","seedRatioMode","downloadDir","files","fileStats"]}}';
-my $delContent    = '{"method":"torrent-remove","arguments":{"ids":["#_ID_#"], "delete-local-data":"true"}';
-my $delSleep      = 10;
-my $RAR_MIN_FILES = 4;
+my $maxAge         = 2.5 * 86400;
+my $tvDir          = `~/bin/video/mediaPath` . '/TV';
+my $monitoredExec  = '/Users/profplump/bin/video/torrentMonitored.pl';
+my $host           = 'http://localhost:9091';
+my $url            = $host . '/transmission/rpc';
+my $content        = '{"method":"torrent-get","arguments":{"fields":["hashString","id","addedDate","comment","creator","dateCreated","isPrivate","name","totalSize","pieceCount","pieceSize","downloadedEver","error","errorString","eta","haveUnchecked","haveValid","leftUntilDone","metadataPercentComplete","peersConnected","peersGettingFromUs","peersSendingToUs","rateDownload","rateUpload","recheckProgress","sizeWhenDone","status","trackerStats","uploadedEver","uploadRatio","seedRatioLimit","seedRatioMode","downloadDir","files","fileStats"]}}';
+my $delContent     = '{"method":"torrent-remove","arguments":{"ids":["#_ID_#"], "delete-local-data":"true"}';
+my $delSleep       = 10;
+my $RAR_MIN_FILES  = 4;
+my $FIND_MAX_DEPTH = 5;
 
 # Debug
 my $DEBUG = 0;
@@ -43,7 +45,12 @@ if ($ENV{'DEBUG'}) {
 }
 
 # Command-line parameters
-my ($force, $maxDays) = @ARGV;
+my ($force, $maxDays, $hash) = @ARGV;
+
+# If a hash is provided, always process matching torrents
+if (defined($hash)) {
+	$force = 1;
+}
 
 # Init
 my $fetch = Fetch->new();
@@ -92,8 +99,18 @@ foreach my $tor (@{$torrents}) {
 		}
 		next;
 	}
+
+	# If a hash is provided, process only that file
+	if (defined($hash) && $tor->{'hashString'} ne $hash) {
+		if ($DEBUG) {
+			printf STDERR 'Skipping torrent with non-matching hash: ' . $tor->{'name'} . ' (' . $tor->{'hashString'} . ")\n";
+		}
+		next;
+	}
+
+	# We've decided to do something about this torrent
 	if ($DEBUG) {
-		print STDERR 'Processing finished torrent: ' . $tor->{'name'} . "\n";
+		print STDERR 'Processing completed torrent: ' . $tor->{'name'} . "\n";
 	}
 
 	# Handle individual files and directories
@@ -145,14 +162,8 @@ foreach my $tor (@{$torrents}) {
 			@newFiles = &unrar($IS_RAR, $path);
 		}
 
-		# Find all media files
-		my @tmpFiles = readDir($path, '/\.(?:avi|mkv|m4v|mov|mp4|ts|wmv)$/i');
-		foreach my $file (@tmpFiles) {
-			if ($file =~ /sample/i) {
-				next;
-			}
-			push(@files, $file);
-		}
+		# Find all media files, recursively
+		@files = findMediaFiles($path, 0);
 	}
 
 	# Bail if we found no files
@@ -231,9 +242,9 @@ sub getSSE($) {
 	my $season      = 0;
 	my $episode     = 0;
 	my $seasonBlock = '';
-	if ($name =~ /(?:\b|_)(S\d{1,2}[_\s\.]?E\d{1,2})(?:\b|_)/i) {
+	if ($name =~ /(?:\b|_)(S(?:eason)?[_\s\.\-]*\d{1,2}[_\s\.\-]*E(?:pisode)?[_\s\.]*\d{1,2})(?:\b|_)/i) {
 		$seasonBlock = $1;
-		($season, $episode) = $seasonBlock =~ /S(\d{1,2})[_\s\.]?E(\d{1,2})/i;
+		($season, $episode) = $seasonBlock =~ /S(?:eason)?[_\s\.\-]*(\d{1,2})[_\s\.\-]*E(?:pisode)?[_\s\.\-]*(\d{1,2})/i;
 		$season = int($season);
 		$episode = sprintf('%02d', int($episode));
 	} elsif ($name =~ /[\[\_\.](\d{1,2}x\d{2,3})[\]\_\.]/i) {
@@ -280,6 +291,9 @@ sub getDest($$$$) {
 		print STDERR 'Finding destintion for: ' . $series . ' S' . $season . 'E' . $episode . "\n";
 	}
 
+	# Input cleanup
+	$episode =~ s/^0+//;
+
 	# Find all our existing TV series
 	my @shows    = ();
 	my %showsCan = ();
@@ -382,12 +396,13 @@ sub getDest($$$$) {
 	}
 
 	# Bail if we already have this episode
-	my @episodes = readDir($seasonDir, '/^\s*[\d\-]+\s*\-\s*/');
+	my @episodes = readDir($seasonDir, 0);
 	foreach my $ep (@episodes) {
-		$ep = basename($ep);
 		my ($epNum) = $ep =~ /^\s*([\d\-]+)\s*\-\s*/;
-		$epNum   =~ s/^0+//;
-		$episode =~ s/^0+//;
+		if (!defined($epNum)) {
+			next;
+		}
+		$epNum =~ s/^0+//;
 		if ($epNum eq $episode) {
 			print STDERR 'Existing episode for: ' . $series . ' S' . $season . 'E' . $episode . "\n";
 			return;
@@ -561,7 +576,7 @@ sub unrar($$) {
 	}
 
 	# Keep a list of old files, so we can find/delete the output
-	my @beforeFiles = readDir($path, undef());
+	my @beforeFiles = readDir($path, 1);
 
 	# Run the unrar utility
 	my $pid = fork();
@@ -583,7 +598,7 @@ sub unrar($$) {
 
 	# Compare the old file list to the new one
 	my @newFiles = ();
-	my @afterFiles = readDir($path, undef());
+	my @afterFiles = readDir($path, 1);
 	foreach my $file (@afterFiles) {
 		my $found = 0;
 		foreach my $file2 (@beforeFiles) {
@@ -630,13 +645,7 @@ sub seriesCleanup($) {
 }
 
 sub readDir($$) {
-	my ($indir, $regex) = @_;
-
-	# Allow optional use of a matching regex
-	my $useRegex = 1;
-	if (!defined($regex) || length($regex) < 1) {
-		$useRegex = 0;
-	}
+	my ($indir, $long) = @_;
 
 	# Clean up the input directory
 	$indir =~ s/\/+$//;
@@ -649,23 +658,18 @@ sub readDir($$) {
 	foreach my $file (readdir(DIR)) {
 		my $keep = 0;
 
-		# Regex filter (if active)
-		if (!$useRegex) {
-			$keep = 1;
-		} elsif (eval('$file =~ m' . $regex)) {
-			$keep = 1;
-		}
-
-		# Construct a complete file path
-		$file = $indir . '/' . $file;
-
-		# Ignore directories
-		if (-d $file) {
-			$keep = 0;
+		# Skip junk
+		if (   $file eq '.'
+			|| $file eq '..'
+			|| $file =~ /\._/)
+		{
+			next;
 		}
 
-		# Save matching files
-		if ($keep) {
+		# Save the full path
+		if ($long) {
+			push(@files, $indir . '/' . $file);
+		} else {
 			push(@files, $file);
 		}
 	}
@@ -679,6 +683,38 @@ sub readDir($$) {
 	return (@orderedFiles);
 }
 
+sub findMediaFiles($$) {
+	my ($path, $depth) = @_;
+	my @files = ();
+
+	# Recursion limit
+	if ($depth > $FIND_MAX_DEPTH) {
+		return ();
+	}
+
+	my @tmpFiles = readDir($path, 1);
+	foreach my $file (@tmpFiles) {
+
+		# Skip sample files
+		if ($file =~ /sample/i) {
+			next;
+		}
+
+		# Recurse on directories
+		if (-d $file) {
+			push(@files, findMediaFiles($file, $depth + 1));
+			next;
+		}
+
+		# Save matching files
+		if ($file =~ /\.(?:avi|mkv|m4v|mov|mp4|ts|wmv)$/i) {
+			push(@files, $file);
+			next;
+		}
+	}
+	return @files;
+}
+
 sub runAndCheck(@) {
 	my (@args) = (@_);