Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 131 lines (105 sloc) 3.79 KB
#!/usr/bin/env ruby
#
# pbrisbin 2012
#
# WARNING:
#
# Something about the mencoder options causes the ISO to be unplayable
# on XBMC. I suspect it's refresh rate, but I'm not sure. They play
# fine via mplayer, and when burnt back to disc and played via a DVD
# player, they just skip when played directly on the HTPC. I'm
# unlikely to research this further as I no longer really have a need
# for ISOs and am simply going to rip to MP4 via handbrake from now
# on. Sorry...
#
###
require 'fileutils'
require 'optparse'
module Dvd2iso
class Info # {{{
attr_reader :title, :dvd_name, :file_name
attr_reader :length, :audio_br, :chapter_markers
def initialize(device)
title_info = `vobcopy -I '#{device}' 2>&1`.lines
@title = title_info.grep(/Most chapters/) { |x| x.split(' ')[5] }.first
@dvd_name = title_info.grep(/Name of the dvd/) { |x| x.split(' ')[5] }.first
@file_name = dvd_name.downcase.gsub(/\s+/, '_')
probe_info = `tcprobe -i '#{device}' -T #{title} -d 8 2>&1`.lines
@length = probe_info.grep(/^V:/) { |x| x.split(' ')[3].to_i }.first
@audio_br = probe_info.grep(/^A:/) { |x| x.split(' ')[4].to_i / 8 }.first
@chapter_markers = probe_info.grep(/\[Chapter \d+\] /) { |x| x.split(' ')[3] }
end
# given the length and audio bitrate we know, calculate a video
# bitrate that would encode to a file of the given size.
def video_br(size)
(((size - (audio_br * length)) / length) * 8)
end
end
# }}}
class Main
include FileUtils
SIZE = 4193404 # DVD5
WORK_DIR = './dvd2iso_tmp'
MPEG_FILE = "#{WORK_DIR}/movie.mpeg"
VIDEO_TS = "#{WORK_DIR}/MOVIE"
ISO_FILE = "#{WORK_DIR}/movie.iso"
LOG = "#{WORK_DIR}/output.log"
attr_reader :device, :output
def initialize
ENV['VIDEO_FORMAT'] = 'NTSC'
@device = '/dev/sr0'
@output = './%s.iso'
end
def run(argv)
OptionParser.new do |o|
o.banner = 'usage: dvd2iso [options]'
o.on('-i', '--input DEVICE') { |d| @device = d }
o.on('-o', '--output FILE') { |f| @output = f }
end.parse!(argv)
info = Info.new(device)
puts "#"
puts "# Ripping #{info.dvd_name}"
puts "# Title #{info.title}, #{info.chapter_markers.length} Chapters"
puts "#"
mkdir_p WORK_DIR, :verbose => true
mencoder info.title, info.video_br(SIZE), MPEG_FILE
dvdauthor MPEG_FILE, info.chapter_markers, VIDEO_TS
mkisofs VIDEO_TS, ISO_FILE
mv ISO_FILE, (output % info.file_name), :verbose => true
rm_r WORK_DIR, :verbose => true
puts "#"
puts "# Success!"
puts "#"
rescue => ex
die("#{ex}")
end
def mencoder(title, video_br, mpeg_file)
execute('mencoder', "dvd://#{title}", "-dvd-device '#{device}'",
'-mc 0', '-of mpeg', '-mpegopts format=dvd:tsaf', '-oac copy', '-ovc lavc', '-vf scale=720:480,pullup,softskip,harddup',
"-lavcopts vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=#{video_br}:keyint=18:vstrict=0:aspect=16/9:ilme:ildct",
'-ofps 24000/1001', "-o '#{mpeg_file}'"
)
end
def dvdauthor(mpeg_file, chapters, video_ts)
execute('dvdauthor', '-t', "-c #{chapters.join(",")}", "-o '#{video_ts}'", "'#{mpeg_file}'")
execute('dvdauthor', '-T', "-o '#{video_ts}'")
end
def mkisofs(video_ts, iso_file)
execute('mkisofs', '-dvd-video', "-o '#{iso_file}'", "'#{video_ts}'")
end
private
def execute(*args)
puts
puts args.join(" \\\n ")
cmd = args.join(' ')
cmd << " &>>'#{LOG}'"
system(cmd) or die("#{$?}")
end
def die(msg)
$stderr.puts "error: #{msg}."
$stderr.puts "see #{LOG} for more details."
exit 1
end
end
end
Dvd2iso::Main.new.run ARGV
You can’t perform that action at this time.