Jump to content



Photo

Batch file to run command on joining video files?


  • Please log in to reply
24 replies to this topic

#16 hshah

hshah

    Neowinian

  • Joined: 12-January 13

Posted 13 January 2013 - 00:12

I got it working by using a specified file list, and I think I know what was wrong. My films are named "Film CD 1.avi" etc and not "Film - CD1.avi".

What would I need to change these two lines to work with that format:
$name = (split (/[ ]*-[ ]*CD[ ]*1/i, $in_avi))[0];

if ($in_avi_2 =~ /^$MOVIE_IN_PATH\\$name[ ]*-[ ]*CD[ ]*2\.avi$/i)



#17 +Karl L.

Karl L.

    xorangekiller

  • Tech Issues Solved: 15
  • Joined: 24-January 09
  • Location: Virginia, USA
  • OS: Debian Testing

Posted 13 January 2013 - 01:14

I got it working by using a specified file list, and I think I know what was wrong. My films are named "Film CD 1.avi" etc and not "Film - CD1.avi".

What would I need to change these two lines to work with that format:

$name = (split (/[ ]*-[ ]*CD[ ]*1/i, $in_avi))[0];

if ($in_avi_2 =~ /^$MOVIE_IN_PATH\\$name[ ]*-[ ]*CD[ ]*2\.avi$/i)


You are correct in suspecting the regular expressions as the reason the script is not working for you. I wrote it to expect the OP's naming scheme. Since your naming scheme is a little bit different, my script was not detecting anything to convert. The version below is modified to work under the your conditions; note the differences on lines 66, 70, and 75 in particular.

#!/usr/bin/perl

use strict;

########################################################################
#						 Configuration Details						#
########################################################################

# Array of movies to convert
my @MOVIES_TO_CONVERT; # = ('The Figher', 'The Fifth Element');

# Directory where the split AVI files are stored
my $MOVIE_IN_PATH = 'T:\Video\Movies';

# Directory where the combined AVI files will be stored
my $MOVIE_OUT_PATH = 'C:\_COMBINED_AVI';

# Full path to the avidemux executable
my $AVIDEMUX = 'C:\Programs\avidemux\avidemux.exe';

########################################################################
#							   Functions							  #
########################################################################

# Return an array of all the AVI files in the specified directory.
sub get_avis_in_directory
{
	my $dh; # Directory handle
	my $dir; # Current directory
	my @avis; # Array of file names to return

	opendir ($dh, $dir = shift) or die "Failed to open directory $dir: $!\n";
	while (readdir $dh)
	{
		next if (/^\.{1,2}/);
		$_ = $dir . "\\" . $_;
		push (@avis, $_) if (-f $_ and /.*\.avi$/i);
	}
	closedir $dh;

	return (@avis);
}

########################################################################
#							  Entry Point							 #
########################################################################

die "Input directory $MOVIE_IN_PATH does not exist!\n" unless (-d $MOVIE_IN_PATH);
die "Output directory $MOVIE_OUT_PATH does not exist!\n" unless (-d $MOVIE_OUT_PATH);

# This variable represents the actual names and paths of movies to be converted.
# It will either be built from the files specified in @MOVIES_TO_CONVERT manually, or
# built dynamically based on the files in the source and destination paths.
my @movies_formatted; # Array of hashes of movies to convert

if ($#MOVIES_TO_CONVERT == -1)
{
	my @in_avis; # Array of AVI files in the input directory
	my @out_avis; # Array of AVI files in the ouput directory

	@in_avis = get_avis_in_directory ($MOVIE_IN_PATH);
	@out_avis = get_avis_in_directory ($MOVIE_OUT_PATH);

	for my $in_avi (@in_avis)
	{
		if ($in_avi =~ /.*[ ]*CD[ ]*1\.avi$/i)
		{
			my $rec; # Temporary hash variable
			my $name; # Name of the move we are processing
			$name = (split (/[ ]*CD[ ]*1/i, $in_avi))[0];
			$name = (split (/$MOVIE_IN_PATH[\\\/]{1}/i, $name))[1];

			for my $in_avi_2 (@in_avis)
			{
				if ($in_avi_2 =~ /^$MOVIE_IN_PATH\\$name[ ]*CD[ ]*2\.avi$/i)
				{
					$rec->{'part2'} = $in_avi_2;
					last;
				}
			}

			if (defined $rec->{'part2'})
			{
				for my $out_avi (@out_avis)
				{
					if ($out_avi =~ /$name\.avi$/i)
					{
						$rec->{'output'} = $out_avi;
						last;
					}
				}

				unless (defined $rec->{'output'})
				{
					$rec->{'part1'} = $in_avi;
					$rec->{'output'} = "$MOVIE_OUT_PATH\\$name.avi";
					push (@movies_formatted, $rec);
				}
			}
		}
	}
}
else
{
	my $rec; # Temporary hash variable

	for my $name (@MOVIES_TO_CONVERT)
	{
		$rec = {};
		$rec->{'part1'} = "$MOVIE_IN_PATH\\$name CD 1.avi";
		$rec->{'part2'} = "$MOVIE_IN_PATH\\$name CD 2.avi";
		$rec->{'output'} = "$MOVIE_OUT_PATH\\$name.avi";
		push (@movies_formatted, $rec);
	}
}

for my $movie (@movies_formatted)
{
	my $convert_cmd = "\"$AVIDEMUX\" --load \"" . $movie->{'part1'} . "\" --append \"" . $movie->{'part2'} . "\" --force-smart --save \"" . $movie->{'output'} . "\" --quit";
	print "$convert_cmd\n";
	die "Unable to convert $movie->{'output'}!\n" if (system "$convert_cmd");
}

Edit: Here is the diff between the OP's version of the script and yours. It should make the changes a little more obvious. (The spaces may be a little munged, kinda like the script above. I hate Neowin's code formatting.)

--- avijoin.pl  2013-01-12 20:15:57.468098458 -0500
+++ avijoin-nodash.pl   2013-01-12 20:31:27.336122407 -0500
@@ -63,16 +64,16 @@

	 for my $in_avi (@in_avis)
	 {
-		if ($in_avi =~ /.*-[ ]*CD[ ]*1\.avi$/i)
+		if ($in_avi =~ /.*[ ]*CD[ ]*1\.avi$/i)
		 {
			 my $rec; # Temporary hash variable
			 my $name; # Name of the move we are processing
-			$name = (split (/[ ]*-[ ]*CD[ ]*1/i, $in_avi))[0];
+			$name = (split (/[ ]*CD[ ]*1/i, $in_avi))[0];
			 $name = (split (/$MOVIE_IN_PATH[\\\/]{1}/i, $name))[1];

			 for my $in_avi_2 (@in_avis)
			 {
-				if ($in_avi_2 =~ /^$MOVIE_IN_PATH\\$name[ ]*-[ ]*CD[ ]*2\.avi$/i)
+				if ($in_avi_2 =~ /^$MOVIE_IN_PATH\\$name[ ]*CD[ ]*2\.avi$/i)
				 {
					 $rec->{'part2'} = $in_avi_2;
					 last;
@@ -107,8 +108,8 @@
	 for my $name (@MOVIES_TO_CONVERT)
	 {
		 $rec = {};
-		$rec->{'part1'} = "$MOVIE_IN_PATH\\$name - CD1.avi";
-		$rec->{'part2'} = "$MOVIE_IN_PATH\\$name - CD2.avi";
+		$rec->{'part1'} = "$MOVIE_IN_PATH\\$name CD 1.avi";
+		$rec->{'part2'} = "$MOVIE_IN_PATH\\$name CD 2.avi";
		 $rec->{'output'} = "$MOVIE_OUT_PATH\\$name.avi";
		 push (@movies_formatted, $rec);
	 }


#18 hshah

hshah

    Neowinian

  • Joined: 12-January 13

Posted 13 January 2013 - 15:46

Brilliant. You are a star :)

#19 hshah

hshah

    Neowinian

  • Joined: 12-January 13

Posted 13 January 2013 - 17:06

Unfortunately the new script doesn't work. It gives the same result as before and my files are named in the format "Film CD 1.avi" etc.

The only difference this time is that there are some .mkv files in the same folder but if I am reading this script correctly, they would just be ignored?

/Edit: I added "use warnings;" to the top and it shows this error many times:
Use of uninitialized value $name in regexp compilation at films.pl line 76


#20 +Karl L.

Karl L.

    xorangekiller

  • Tech Issues Solved: 15
  • Joined: 24-January 09
  • Location: Virginia, USA
  • OS: Debian Testing

Posted 13 January 2013 - 18:52

Unfortunately the new script doesn't work. It gives the same result as before and my files are named in the format "Film CD 1.avi" etc.

The only difference this time is that there are some .mkv files in the same folder but if I am reading this script correctly, they would just be ignored?

/Edit: I added "use warnings;" to the top and it shows this error many times:

Use of uninitialized value $name in regexp compilation at films.pl line 76


The MKV files should not interfere with the script. It is supposed to filter out everything but AVIs.

The warning you are getting about an uninitialized variable does suggest a cause. The split statement on line 72 is failing. The split statement on line 71, which is supposed to remove the "CD 1" text from the end of the video's name, could be failing as well, but since the $name variable is assigned from the first element of the resulting array, $name will always have a value, even if its wrong. Since the split statement on line 72, which is supposed to remove the leading path from the video's name, is using the second element of the resulting array, $name is not guaranteed to have a value, although a value is assumed by the script. You are getting a warning on line 76 because that is the first place the uninitialized variable is used. Theoretically the way the script is building the array of AVIs and parsing out the name should have made this situation impossible - at least that was my thinking - but apparently not. Your environment must have some condition that my tests did not cover.

If you have more specific questions, feel free to ask. If you discover a solution, post it. Hopefully that gives you enough information to debug your issue. Good luck.

#21 hshah

hshah

    Neowinian

  • Joined: 12-January 13

Posted 13 January 2013 - 19:44

I posted the question here:
http://stackoverflow...me-not-matching

See the answer by Borodin, and the following comments. You might be able to help with that :)

#22 hshah

hshah

    Neowinian

  • Joined: 12-January 13

Posted 13 January 2013 - 20:02

Argh! After all that it looks like my installation of Avidemux was ****ed. I reinstalled it and it runs fine now with the changes Borodin suggested.

#23 +Karl L.

Karl L.

    xorangekiller

  • Tech Issues Solved: 15
  • Joined: 24-January 09
  • Location: Virginia, USA
  • OS: Debian Testing

Posted 13 January 2013 - 20:55

I posted the question here:
http://stackoverflow...me-not-matching

See the answer by Borodin, and the following comments. You might be able to help with that :)


Thanks! His answer was very helpful, and he is correct: I'm not a pro Perl programmer. I learned Perl about 4 months ago. I originally wrote this script in Perl because it was certainly easier than Batch, and the best way to learn a language is to practice it.

By the way, after all that: hshah, welcome to Neowin!

#24 hshah

hshah

    Neowinian

  • Joined: 12-January 13

Posted 13 January 2013 - 21:37

Thanks! His answer was very helpful, and he is correct: I'm not a pro Perl programmer. I learned Perl about 4 months ago. I originally wrote this script in Perl because it was certainly easier than Batch, and the best way to learn a language is to practice it.

By the way, after all that: hshah, welcome to Neowin!


Thanks for the welcome.

I hadn't noticed his edit (that code wasn't there before) and to be honest I'm not fussed whether your code is the best or not... it works and it has saved me hours of manual work. So the thanks still goes to you :)

#25 spline

spline

    Resident One Post Wonder

  • Joined: 12-December 13

Posted 12 December 2013 - 09:21

Hi,

 

wow, this is great.

 

Thanks a lot for your work, xorangekiller.

 

The only think, if i have one wish for free, is, to make it more flexible and simple.

 

For example, the script could parse through all files of a directory (i move all split avis in a separate directory) and whenever it finds two matching files it will join them.

So there is no need to fill the array @MOVIES_TO_CONVERT

 

A second wish is, that the naming convention is mor flexible.

Sometimes the naming of the file is *-cd1.avi / *-cd2.avi, sometimes it's *cd1 or cda or just a and b.

 

 

But anyhow, this is great

 

 

spline