#!/usr/bin/ruby # Filename: vid2iphone # Author: David Ljung Madison # See License: http://MarginalHacks.com/License/ # Description: Converts videos into format suitable for iPhones # Requirements: ffmpeg WITH libfaac support # Ubuntu ships ffmpeg *w/out* libfaac support # You will need to recompile # Search google for instructions # mplayer required for DVDs, DVD images and DVD directories # linux or some such system also required # # Possible inputs: # + Video file [requires ffmpeg + proper codec] # + DVD [requires mplayer] # + dvd.iso image [requires mplayer] # + Directory DVD copy [requires mplayer] # # See also: http://thomer.com/howtos/mp4ize # # Notes: I think the iPhone video output can support 480i (640x480 interlaced) # It might make it worth having options for this encoding for videos # that are meant to go to an external display... ################################################## # Variables ################################################## # To dump from dvd: mplayer dvd://1 -dumpstream -dumpfile dump.vob # To dump from iso: mplayer -dvd-device some.iso dvd://1 -dumpstream -dumpfile dump.vob # Then: ffmpeg -i "$INFILE" -f mp4 -vcodec mpeg4 -maxrate 1000 -b 700 -qmin 3 -qmax 5 -bufsize 4096 -g 300 -acodec aac -strict experimental -ab 192k -s 480x320 -aspect 4:3 "$OUTFILE" # Some versions of ffmpeg warn that -b needs to specify kb/s, even though the usage claims otherwise. Ignore the warning. DUMP = ["mplayer"] DUMPARGS = %w(-dumpstream -dumpfile) # then a tmpfile DUMPIMAGE = %w(dvd://1 -dvd-device) # then the image CONVERT = ["ffmpeg"] # then "-i file" CONVERTARGS = %w(-f mp4 -vcodec mpeg4 -maxrate 1000 -b 700 -qmin 3 -qmax 5 -bufsize 4096 -g 300 -acodec aac -strict experimental -ab 192k -s 480x320 -aspect 4:3) # followed by output file $DEBUG = false ################################################## # Redefinitions ################################################## # Call system with an array and call exec, add debug support module Kernel def system(args) if ($DEBUG) then puts "\nDEBUG[sys]: #{args.join(' ')}\n\n" return 0 end exec(*args) unless pid=fork Process.wait pid $?.exitstatus end end # Fix the fact that we can't do: array + string class Array alias oldPlus + def +(other) if (other.kind_of? String or other.kind_of? Fixnum) then oldPlus([other]) else oldPlus(other) end end end ################################################## # Usage ################################################## def usage(msg=nil) $stderr.puts "ERROR: #{msg}\n\n" if msg $stderr.puts < | | ]" Converts videos/movies to iPhone video format After conversion, transfer with Amarok or equivalent Possible inputs: + Video file [requires ffmpeg + proper codec] + DVD [requires mplayer] + dvd.iso image [requires mplayer] + Directory DVD copy [requires mplayer] USAGE exit -1 end def clean(str) str.sub(/.+\/(.+)/,'\\1').sub(/\.[^\/]+$/,'').sub(/\/+$/,'') end def parseArgs from = "" out = "out.mp4" dumpDVD = false dumpImage = false ## Do we want the default to be the DVD? #ARGV.push("dvd://1") if ARGV.empty? usage if ARGV.empty? ARGV.each { |arg| if (arg == '-h' or arg == '-?') then usage end if (arg == '-d') then $DEBUG = true next end from = arg if (arg =~ /^dvd:/) then dumpDVD = true elsif (File.directory?(arg)) then out = clean(arg) + ".mp4" dumpImage = true elsif (!File.file?(arg)) then usage("File not found [#{arg}]") elsif (arg =~ /\.iso$/i) then out = clean(arg) + ".mp4" dumpImage = true else # Just a file out = clean(arg) + ".mp4" end } [from,out,dumpDVD,dumpImage] end ################################################## # Main ################################################## def dumpMovie(from,dumpDVD,dumpImage) dump = "tmp."+$$.to_s+".vob" puts "Dumping movie to [#{dump}]" cmd = DUMP cmd += DUMPIMAGE if dumpImage cmd += from cmd += DUMPARGS cmd += dump ret = system(cmd) raise "error dumping movie [#{dump}]" if ret!=0 dump end def convert(from,out) puts "Final out: [#{out}]" cmd = CONVERT cmd += ["-i",from] cmd += CONVERTARGS cmd += out ret = system(cmd) raise "error converting movie [#{out}]" if ret!=0 end def main (from,out,dumpDVD,dumpImage) = parseArgs from = dumpMovie(from,dumpDVD,dumpImage) if dumpDVD or dumpImage convert(from,out) File.delete(from) if (dumpDVD or dumpImage) and !$DEBUG end main