Although there are many transcoding DVD rippers available and a few non-transcoding ones such as
dvdbackup
, there seems a somewhat surprising lack of simple tools to just copy a DVD unaltered from its source to an ISO image directly. DVD burner applications such as Brasero can do this but are somewhat overblown. The below tiny Python script
dvdcopy
aims to be useful in that sense. It copies the DVD with plain old dd
after getting name and size information from isoinfo
. Both those as well as the for most commercial movie DVD's necessary libdvdcss2 package are installed by default on both Mint 18.3 and Mint 19; isoinfo is from the genisoimage package if you do not yet have it.I can not speak to usefulness of this script for Blu-ray; I have discs nor hardware. CSS on DVD is partly drive-based and if this is also the case for the newer systems on Blu-ray then usefulness will depend on libdvdcss2. That is, for all I know Blu-ray may or may not be supported --- although I would assume not.
Save the below as say
~/bin/dvdcopy
, make it executable as chmod +x ~/bin/dvdcopy
and use dvdcopy -h
for a small usage screen. Simply dvdcopy
will have it copy /dev/dvd to an after the volume id named iso in the current directory, dvdcopy -i
will only show disc information.Reports of success, failure and/or perceived usefulness welcome...
Code: Select all
#!/usr/bin/env python3
#
# dvdcopy (public domain, 2018)
import argparse
import ctypes
import locale
import subprocess
IBS = 128 * 1024
OBS = 4 * 1024 ** 2
def isoinfo(device):
def val(tag, line):
i = line.find(':')
return '' if i < 0 or line[:i].strip() != tag else line[i + 1:].strip()
id, bs, vs = '', '', ''
p = subprocess.run(['isoinfo', '-d', '-i', device], stdout=subprocess.PIPE, universal_newlines=True, check=True)
for line in p.stdout.splitlines():
if vs and bs and id:
break
if not id:
id = val('Volume id', line)
if id:
continue
if not bs:
bs = val('Logical block size is', line)
if bs:
continue
if not vs:
vs = val('Volume size is', line)
try:
bs = int(bs)
vs = int(vs)
except ValueError:
bs = 0
vs = 0
return id, bs, vs
locale.setlocale(locale.LC_ALL, '')
parser = argparse.ArgumentParser(description='Backup DVD to ISO.')
group = parser.add_mutually_exclusive_group()
group.add_argument('-c', action='store_true', dest='copy', default=True, help='backup device to iso (default)')
group.add_argument('-i', action='store_false', dest='copy', help='show iso information')
parser.add_argument('-d', dest='device', default='/dev/dvd', help='device (default: /dev/dvd)')
args = parser.parse_args()
id, bs, vs = isoinfo(args.device)
if id and bs and vs:
size = vs * bs
i = 0 if size < 1024 ** 2 else 1 if size < 1024 ** 3 else 2
unit = 'KMG'[i]
print(locale.format_string('Volume %s, %d bytes (%.1f %cB, %.1f %ciB)',
(id, size, size / 1000 ** (i + 1), unit, size / 1024 ** (i + 1), unit)))
if args.copy:
libdvdcss = ctypes.CDLL('libdvdcss.so.2')
libdvdcss.dvdcss_close(libdvdcss.dvdcss_open(args.device.encode()))
i = IBS // bs
while vs % i:
i -= 1
ibs = bs * i
obs = OBS // ibs * ibs
subprocess.run(['dd', 'if=%s' % args.device,
'iflag=direct',
'ibs=%d' % ibs,
'of=%s.iso' % id.lower(),
'obs=%d' % obs,
'count=%d' % (vs // i),
'status=progress'], check = True)