How to reduce the size of every video in a directory

If you have a ton of videos and you are running out of room on your hard drive. You can use this script to reduce the file size of every video file in a directory.

Required

 * mencoder, part of mplayer
 * http://www.mplayerhq.hu/
 * XVID library
 * http://www.xvid.org
 * mp3lame library
 * http://lame.sourceforge.net/

Description
This script uses mencoder to re-encode each file using the XVID video codec, and the mp3lame audio codec. The default settings are video quality #5 and 96kbs audio bitrate. 96kbs audio bitrate is fine for most things. Video quality #5 is fine for most low-action videos, like Law and Order type, or if you don't mind it getting chunky during explosions.


 * Features
 * Ignores non-video files
 * Copies instead of encodes files smaller than 100MB, so it won't compress already small files (size can be changed)
 * Moves new files to a directory
 * default small
 * Creates a log: /tmp/video_dir_smallify.log
 * Can set process priority
 * Displays estimate of time left based on last encoding time.
 * Displays final summary


 * Statistic
 * Average file size: 140MB for a 45min video
 * Compression time: 20m to compress a 45m show, based on a 3 GHz computer

Example of output
Detected 3 video files. Roughly est. 1.5 h to completion, based on encoding time 30min/file. Creating 'small' directory To Exit before completion hit Ctrl-C twice.

Smallifying: American.Dad.S05E01.In.Country.Club.PDTV.XviD-FQM.avi (1 of 3 files) Encoding video...     Encoding finished. Original file size: 175MB Final file size: 84 MB   Encoding took 0.2 h Smallifying: American.Dad.S05E02.Moon.Over.Isla.Island.PDTV.XviD-FQM.avi (2 of 3 files) Updated est. time left 0.4 h, based on last encoding Encoding video...     Encoding finished. Original file size: 175MB Final file size: 69 MB   Encoding took 0.2 h Smallifying: American.Dad.S05E03.PDTV.XviD-2HD.avi (3 of 3 files) Updated est. time left 0.2 h, based on last encoding Encoding video...     Encoding finished. Original file size: 175MB Final file size: 65 MB   Encoding took 0.2 h

=
============================= Summary of encoding -- American.Dad.S05E01.In.Country.Club.PDTV.XviD-FQM.avi Original Size: 175 MB Final: 84 MB American.Dad.S05E02.Moon.Over.Isla.Island.PDTV.XviD-FQM.avi Original Size: 175 MB Final: 69 MB American.Dad.S05E03.PDTV.XviD-2HD.avi Original Size: 175 MB Final: 65 MB

--- Original dir: shrink/ Final dir: shrink//small Log file: /tmp/video_dir_smallify.log Total encoding time: 0.5 h

All done. Before deleting old files: Check a few files Check log for errors Look at the file sizes for inconsistency

Script
use Time::HiRes qw ( time );
 * 1) !/usr/bin/perl
 * 1) Name: Video directory Smallifier
 * 2) Version: 0.2
 * 3) Creator: Jeff Israel
 * 4) Date: Oct 21, 2009
 * 5) License: GPL 3.0
 * 6) Description: This script reduces the file size of every video file
 * 7)  in a directory
 * 8) Requirements: mencoder (part of mplayer), XVID library, mp3lame
 * 9) Usage: video_dir_smallify.pl [video directory]
 * 10) Example: video_dir_smallify.pl /pub/video/tv/castle/
 * 1) Example: video_dir_smallify.pl /pub/video/tv/castle/


 * 1) Configure
 * 1) Configure

$video_quality=5; # 5 is good for most low action $audio_bitrate=96;
 * 1) $video_bitrate=500; # not used, adjust $video_quality

$video_codec='xvid'; # currently only supports _xvid_ $audio_codec='libmp3lame'; # currently only supports _libmp3lame_

$video_output_dir = 'small'; # where the new videos go, relative dir, example input='videos/' output='videos/small/' $min_file_size =100; # skips encoding video if small than x in MB, recomended 150MB for 1h videos, 100MB for 30m videos

$niceness = '19'; # 19 is lowest priority, 0 is highest $log_file = '/tmp/video_dir_smallify.log';

@video_file_extentions = ("avi","rm","mpg","mpeg","asf","ram","wmv","mp4","ogg",'ogm',"m4v","mkv",'rmvb','mov','divx'); #will only encode files with these extensions

$directory_name = $ARGV[0];
 * 1) Code
 * 1) Code

# $audio_var = "-oac lavc -lavcopts acodec=vorbis:abitrate=$audio_bitrate"} # $video_var = "-ovc lavc -lavcopts vcodec=mpeg4:vbitrate=$video_bitrate:vhq -ffourcc XVID";
 * 1) commands
 * 2) if ( $audio_codec eq 'vorbis' ) {
 * 1) if ( $video_codec eq 'xvid') {
 * }

$encode_command = "nice -n $niceness mencoder -oac mp3lame -lameopts abr:br=$audio_bitrate -ovc xvid -xvidencopts fixed_quant=$video_quality ";
 * 1) Some input error checking
 * 1) Some input error checking

if($directory_name eq ""){ print "Error: no directory entered.\n the first arg is the directory\n"; exit; }

if ( !( -d $directory_name) ){ #check if directory exists print "Error: $directory_name is not a directory\n"; exit; } if ( !( -w $directory_name) ){ #check if directory exists print "Error: $directory_name is not writeable\n"; exit; }

opendir(DIR, "$directory_name"); #precheck if video files in dir $video_cnt=0; while (defined($dir = readdir(DIR))) { if ( isVideo($dir) ) { 	$video_cnt++; } } closedir(DIR); if ( $video_cnt == 0 ) { print "Error: not video files in $directory_name\n"; exit; }

sub isVideo { # doo my $filename = $_[0]; foreach $ext (@video_file_extentions) { if ($filename =~ /$ext$/i) { return 1; } else { }	}	0; }
 * 1) 			print "$ext: $filename: match\n";
 * 1) 			print "$ext: $filename: no match\n";

$est_time = 0.5 * $video_cnt; print "Detected $video_cnt video files. \nRoughly est. $est_time h to completion, based on encoding time 30min/file.\n";

if ( -d "$directory_name/$video_output_dir" ) { #checks to see if new dir exists print "Warning: directory, $video_output_dir, exists. This is OK, but files within $video_output_dir may be overwritten\n"; } else { mkdir("$directory_name/$video_output_dir"); print "Creating \'$video_output_dir\' directory\n"; }

if ( -e $log_file ) { my $log_file_old = $log_file. '.old'; system("mv $log_file $log_file_old"); }

print "To Exit before completion hit Ctrl-C twice.\n\n"; $cnt=0; $summary="\n\n==========================================\nSummary of encoding\n--\n"; $total_start_time=time; opendir(DIR, "$directory_name"); $first=1; while (defined($dir = readdir(DIR))) { if ( ($dir ne '.') && ($dir ne '..') && !( -d "$directory_name/$dir" ) ) { if ( isVideo($dir) ) { $cnt++; $file_size = (-s "$directory_name/$dir")/1024/1024; $file_size =~ s/\..*//; if ( $file_size < $min_file_size ) { print "Copying instead of re-encoding: $dir < $min_file_size\MB\n"; system("cp \"$directory_name/$dir\" \"$directory_name/$video_output_dir/$dir\""); sleep(1);

} else { system("rm -f divx2pass.log frameno.avi"); # deleting temp files the might be left over $file_name_full = "$directory_name/$dir"; $new_file_name = "$directory_name/$video_output_dir/$dir.avi"; print "Smallifying: $dir ($cnt of $video_cnt files)\n"; if ( $first == 0 ) { $time_elapst = sprintf("%.1f",($stop_time - $start_time) / 3600 ); # rounding time to one decimal print "   Updated est. time left ". ( 1 + $video_cnt - $cnt)*$time_elapst. " h, based on last encoding \n"; }				$first=0; $start_time = time; # print " Encoding audio...\n"; # print "$audio_enc_command \"$file_name_full\""; # system; # print " Encoding video...\n"; # print "$video_enc_command \"$file_name_full\" -o \"$new_file_name\""; # system; print "   Encoding video...  \n"; system("echo \"\n\n\n============================================================\" >> $log_file"); system("echo \"Encoding $dir\" >> $log_file"); system("echo \"============================================================\" >> $log_file"); system("$encode_command \"$file_name_full\" -o \"$new_file_name\" &>> $log_file "); # system("echo \"$mencoder_out\" >> $log_file"); sleep(1); print "   Encoding finished.\n"; print "   Original file size: $file_size\MB\n"; $org_file_size = $file_size; $file_size = (-s "$new_file_name")/1024/1024; $file_size =~ s/\..*//; print "   Final file size: $file_size MB\n"; $summary .= "$dir\n  Original Size: $org_file_size MB Final: $file_size MB\n"; $stop_time = time; $time_elapst1 = ($stop_time - $start_time) / 3600 ; $time_elapst = sprintf("%.1f", ($stop_time - $start_time) / 3600 ); # rounding time to one decimal # print " start=$start_time, $stop_time, $time_elapst, $time_elapst1\n"; print "   Encoding took $time_elapst h\n"; }		} else { print "Skipping: $dir is not a recognised video file\n"; }		} } closedir(DIR); $total_stop_time=time; $total_time= sprintf("%.1f",($total_stop_time - $total_start_time) / 3600); $summary .= "\n---\nOriginal dir: $directory_name\nFinal dir: $directory_name/$video_output_dir\nLog file: $log_file\nTotal encoding time: $total_time h\n\n";

print $summary; system ("echo \"$summary\" >> $log_file");

$out_text = ''; open FILE, "<", "$log_file"; while () { my $line = $_; if ( $line !~ /^Pos/ && $line !~ /^Skipping frame!/ && $line !~ /^. duplicate frame\(s\)!/ ) { $out_text .= $line; } } close FILE; open FILE, ">$log_file" ; print FILE $out_text; close FILE;
 * 1) Post processing log file
 * 2) system("cat $log_file |grep -v '^Pos' |grep -v '^1 duplicate frame(s)!'|grep -v '^Skipping frame!' ");

print "All done.\n"; print "Before deleting old files:\n"; print " Check a few files\n"; print " Check log for errors\n"; print " Look at the file sizes for inconsistency\n"; print "\n";