# mkvtoolnix - http://www.bunkus.org/videotools/mkvtoolnix/
# ffmpeg
-###########################
+####################################################################################################
# Includes
use File::Copy;
use File::Basename;
use DateTime::Duration;
use DateTime::Format::Duration;
-###########################
-# Configuration parameters
+####################################################################################################
+# Configuration parameters - CHANGE THESE TO SUITE YOUR NEEDS
my $mkvmerge=`which mkvmerge`; chomp($mkvmerge);
my $ffmpeg=`which ffmpeg`; chomp($ffmpeg);
my $tmpfile = `tempfile`; chomp($tmpfile);
my $chapter_file = $tmpfile;
my $input_file_options = "-S";
my $output_file_options = "--chapters $chapter_file";
+####################################################################################################
-###########################
-# Options
+
+####################################################################################################
+# Command Line Options
getopts("st:o:i:h");
if(! -x $mkvmerge) { die "-E- Unable to find required program: mkvmerge\n"; }
return 1;
}
-###########################
+####################################################################################################
# Helper Subroutines
sub epoch_to_date {
my ($epoch) = @_;
return sprintf("%4d",$mtime->year)."-".sprintf("%02d",$mtime->month)."-".sprintf("%02d",$mtime->day)." ".$mtime->hms;
}
-###########################
+####################################################################################################
# MAIN
# Turn the list of input videos into a hash with a value equal to the modification time in epoch seconds
if($errno > 1) { die "-E- mkvmerge encountered some errors with exit code $errno\n"; }
}
-# Remove the temporary file
+# Remove the temporary file used for the chapter generation
if(-e "$tmpfile") { unlink "$tmpfile"; }
-###########################
+####################################################################################################
#!/usr/bin/perl
+# Author: Alan J. Pippin
+# Description: For the given srcpath, merge all the videos that were taken on the same day into a single mkv file
use File::Copy;
use File::Basename;
use File::stat;
use Time::localtime;
+####################################################################################################
+# Configuration parameters - CHANGE THESE TO SUITE YOUR NEEDS
+my $compute_host = "pippin.pippins.net"; # I need this since this script is run from a virtual machine
+my $use_compute_host = 1; # Set to 1 to use a remote compute host to run the mkvmerge command. Set to 0 to use the local host to run it.
+my $make_mkv = "/naspool/videos/bin/make_mkv"; # Update this to be the path to the make_mkv script
+my $minage = "+10"; # Files must be older than X minutes to move
+my $owner = "ajp"; # The owner of the files after they are moved
+my $group = "pip"; # The group of the files after they are moved
+my $mode = "664"; # The mode to set on each file after they are moved
+my $video_suffix = "000"; # What number to start with when adding an incrementing suffix to the end of the video clip to avoid name collisons
+my $video_title_prefix = "HomeVideos:"; # What text to put on the front of the title for the merged video being created
+my $find_cmd = "find \"$srcpathname/\" -cmin $minage -iregex \".*\.mov\" -o -iregex \".*\.3gp\" -o -iregex \".*\.mp4\" -o -iregex \".*\.mts\"";
+####################################################################################################
+
# Command line options
-getopts("h:tvs:");
+getopts("rh:tvs:");
sub usage {
- print "usage: $0 [-t] -s <srcpath>\n";
+ print "usage: $0 [-tvrh] -s <srcpath>\n";
print " -s <srcpath> specify the path to search for videos to merge under\n";
print " -h <compute host> specify the remote compute host to submit the mkvmerge job to\n";
print " -v verbose mode; print extra information about what is being found/merged\n";
print " -t test mode; print what will happen, but don't do anything\n";
+ print " -r remove merged video clips; after a merge, remove the individual video files that were merged\n";
return 1;
}
-if(defined $opt_h) { usage(); exit 1; }
-
-# Configuration parameters
-my $compute_host = "pippin.pippins.net";
my $srcpathname = $opt_s;
-my $minage = "+10"; # Files must be older than X minutes to move
-my $owner = "ajp"; # The owner of the files after they are moved
-my $group = "pip"; # The group of the files after they are moved
-my $mode = "664"; # The mode to set on each file after they are moved
-my $make_mkv = "/naspool/videos/bin/make_mkv"; chomp($make_mkv);
-my $find_cmd = "find \"$srcpathname/\" -cmin $minage -iregex \".*\.mov\" -o -iregex \".*\.3gp\" -o -iregex \".*\.mp4\" -o -iregex \".*\.mts\"";
+if(defined $opt_h) { usage(); exit 1; }
-# Sanity check
+# Sanity checks
if(! -x $make_mkv) { die "-E- Unable to find required script: make_mkv\n"; }
if(! -d $srcpathname) { &usage; print "-E- Can't find srcpath: $srcpathname\n"; exit 1; }
if(defined $opt_h) { $compute_host = $opt_h; }
$dstfile = $dstdir . "/" . $year . "-" . $monthnum . "-" . $day;
# Check for duplicate filenames at the destination
- $newfile = $dstfile . "." . "000";
+ $newfile = $dstfile . "." . $video_suffix;
if(-e "$newfile.$ext") {
- foreach $i ('001' .. '999') {
+ foreach $i ($video_suffix+1 .. '999') {
$newfile = $dstfile . "." . $i;
if(! -e "$newfile.$ext") { last; }
}
}
my $pwd = `pwd`; chomp($pwd);
- my $cmd = "ssh $compute_host 'cd \"$pwd\"; $make_mkv -t \"HomeVideos: $year-$month-$day\" -o \"$video\" -i $videos'\n";
+ my $cmd = "";
+ if($use_compute_host) { $cmd .= "ssh $compute_host 'cd \"$pwd\";"; }
+ $cmd .= "$make_mkv -t \"$video_title_prefix $year-$month-$day\" -o \"$video\" -i $videos";
+ if($use_compute_host) { $cmd .= "'"; }
if(defined $opt_t) {
print "\n-> Creating \"$video\"\n";
print "$cmd\n";
- foreach $video (@{$videos{$video}}) {
- print("rm -f $video\n");
+ if(defined $opt_r) {
+ foreach $video (@{$videos{$video}}) {
+ print("rm -f $video\n");
+ }
}
} else {
# Create the merged video
system("chgrp $group \"$video\"");
system("chmod $mode \"$video\"");
# Remove the individual video files
- foreach $video (@{$videos{$video}}) {
- system("rm -f $video");
+ if(defined $opt_r) {
+ foreach $video (@{$videos{$video}}) {
+ system("rm -f $video");
+ }
}
}
}
#!/usr/bin/perl
+# Author: Alan J. Pippin
+# Description: Find videos from a temporary dropbox location and merge and move them into their final destination.
use File::Copy;
use File::Basename;
use Getopt::Std;
use File::stat;
use Time::localtime;
+use File::Pid;
-# Configuration parameters
-my $srcpathname = "/naspool/pictures/New Photos"; # Path to look for photos to move from
-my $dstpathname = "/naspool/videos/HomeVideos"; # Path to move the photos to
+####################################################################################################
+# Configuration parameters - CHANGE THESE TO SUITE YOUR NEEDS
+my $srcpathname = "/naspool/pictures/New Photos"; # Path to look for videos to move from
+my $dstpathname = "/naspool/videos/HomeVideos"; # Path to move the videos to
my $merge_videos_by_day = "/naspool/videos/bin/merge_videos_by_day";
-my $minage = "+10"; # Files must be older than X minutes to move
+my $minage = "+10"; # File creation dates must be older than X minutes to move
my $owner = "ajp"; # The owner of the files after they are moved
my $group = "pip"; # The group of the files after they are moved
my $mode = "664"; # The mode to set on each file after they are moved
+my $playlist_extension = "pls"; # The extension to use when creating playlist files
+my $video_suffix = "000"; # What number to start with when adding an incrementing suffix to the end of the final video clip to avoid name collisions
my $find_cmd = "find \"$srcpathname/\" -cmin $minage -a \\( -iregex \".*\.mov\" -o -iregex \".*\.3gp\" -o -iregex \".*\.mp4\" -o -iregex \".*\.mts\" -o -iregex \".*\.mkv\" \\)";
+####################################################################################################
# Sanity check
if(! -d $srcpathname) { print "-E- Can't find srcpath: $srcpathname\n"; exit 1; }
"12" => "Dec"
);
-getopts("htv");
+getopts("htvrpd:");
sub usage {
- print "usage: $0 [-v] [-t]\n";
- print " -v = verbose; print file being moved (to)\n";
+ print "usage: $0 [-v] [-t] [-r] [-p] [-d <dir>]\n";
+ print " -v = verbose; print file being moved (to).\n";
print " -t = test; print what will happen, but don't do anything\n";
+ print " -r = remove merged video clips; after a merge, remove the individual video files that were merged\n";
+ print " -p = Only recreate video playlists. Do this for each year & month of video clips in the directory specified by -d <dir>.\n";
+ print " -d <dir> = Directory to recreate the playlists in. Only needed if -p option is given\n";
return 1;
}
return scalar(grep { $_ ne "." && $_ ne ".." } readdir($dh)) == 0;
}
+sub create_playlists {
+ my ($dstdirs) = @_;
+
+ foreach $dstdir (@{$dstdirs}) {
+ print "-> Recreating playlists in: $dstdir\n";
+ print "-> Creating playlists for each month & year of clips from this directory: $video_directory\n";
+ opendir(VIDEODIR, "$dstdir") or die "-E- could not open: $dstdir\n";
+ chdir "$dstdir" || die "-E- Unable to change directory to the dstdir: $dstdir\n";
+
+ my @all_files = readdir VIDEODIR;
+ closedir(VIDEODIR);
+ @all_files = sort @all_files;
+
+ print " Removing all existing playlists from the directory\n";
+ if(! defined $opt_t) { system("rm *.$playlist_extension > /dev/null 2>&1"); }
+
+ foreach $file (@all_files) {
+ next if -d $file;
+ next if ($file !~ /\.avi$/i && $file !~ /\.mpg$/i && $file !~ /\.mkv$/i && $file !~ /\.3gp$/i && $file !~ /\.mov$/i && $file !~ /\.mts$/i);
+ if($file =~ /(\d\d\d\d)-(\d\d)-(\d\d)/) {
+ $year = $1; $month = $2;
+ print " Adding $file to $year.$playlist_extension & $year-$month.$playlist_extension\n";
+ if(! defined $opt_t) { system("echo \"$file\" >> $year.$playlist_extension"); }
+ if(! defined $opt_t) { system("echo \"$file\" >> $year-$month.$playlist_extension"); }
+ } else {
+ print " Skipping $file since we can't extract the year and month from it\n";
+ }
+ }
+ }
+}
+
+# Sanity checks / Option processing
if(defined $opt_h) { usage(); exit 1; }
+if(defined $opt_p) {
+ if(defined $opt_d) {
+ my @dstdirs = ("$opt_d");
+ create_playlists(\@dstdirs);
+ } else {
+ die "-E- You must specify the -d <dir> option when using the -p option\n";
+ }
+ exit 0;
+}
# Only proceed if there are video files to organize
$video_files_found=`$find_cmd`;
if(!$video_files_found) { exit 0; }
# Only one instance of this script running at a time
-use File::Pid;
my $pidfile = File::Pid->new({file => "/tmp/organize_videos.pid"});
exit if $pidfile->running();
$pidfile->write();
# Merge videos prior to copying them over to the destination path
my $errno = 0;
-if(defined $opt_t) {
- $errno=system("$merge_videos_by_day -s \"$srcpathname\" -t");
-} else {
- $errno=system("$merge_videos_by_day -s \"$srcpathname\"");
-}
+my $merge_opts = "";
+if(defined $opt_t) { $merge_opts .= "-t "; }
+if(defined $opt_r) { $merge_opts .= "-r "; }
+$errno=system("$merge_videos_by_day -s \"$srcpathname\" $merge_opts");
if($errno > 0) { $errno = $errno - 255; }
if($errno) { die "-E- $merge_videos_by_day encountered some errors with exit code $errno\n"; }
# Copy the videos over to the destination path
+my @dstdirs;
chdir "$srcpathname";
print "$find_cmd\n" if($opt_v);
foreach $file (`$find_cmd`) {
# Throw out files not in the current srcpath
if((! -f "$srcfile") && (! -f "$srcdir/$srcfile")) { next; }
-
- # Change all spaces to underscores in the filename
- #$srcfile =~ s/ /_/g;
# Make a note of the month, year, and day this video was taken (from the modification time of the file)
$date_taken = ctime(stat("$srcdir/$srcfile")->mtime);
# We are ready to pick a destination folder to put the picture in
$dstdir = $dstpathname . "/" . $year;
+ push(@dstdirs,$dstdir);
$dstfile = $dstdir . "/" . $year . "-" . $monthnum . "-" . $day;
# Check for duplicate filenames at the destination
- $newfile = $dstfile . "." . "000";
+ $newfile = $dstfile . "." . $video_suffix;
if(-e "$newfile.$ext") {
- foreach $i ('001' .. '999') {
+ foreach $i ($video_suffix+1 .. '999') {
$newfile = $dstfile . "." . $i;
if(! -e "$newfile.$ext") { last; }
}
$errno=system("mkdir -p \"$dstdir\"");
if($errno) { print "-E- Error creating dstdir: $dstdir\n"; next; }
# Perform the move operation from $srcdir/$srcfile -> $dstfile
- if($opt_v) { print "-> Moving \"$srcdir/$srcfile\" to \"$dstfile\"\n"; }
+ print "-> Moving \"$srcdir/$srcfile\" to \"$dstfile\"\n";
# Make sure the dstfile doesn't exist, if it does, don't do the move
if(! -f "$dstfile") {
$errno=system("mv \"$srcdir/$srcfile\" \"$dstfile\" 2>/dev/null");
if($errno) { print "-E- Error moving srcfile to dstfile: $srcdir/$srcfile -> $dstfile\n"; next; }
} else {
- if($opt_v) { print "-> Skipping \"$srcdir/$srcfile\". Destfile \"$dstfile\" already exists.\n"; }
+ print "-> Skipping \"$srcdir/$srcfile\". Destfile \"$dstfile\" already exists.\n";
}
# Fix the permissions
system("chown $owner \"$dstfile\"");
}
}
+# For each destination dir we copied new content into, recreate the playlists
+create_playlists(\@dstdirs);
+
$pidfile->remove();
print "\n\n";