How do you rip a DVD to a bunch of MP4 files?

published May 29, 2022

It's very easy to split your DVDs title by title (e.g. one video file per episode) on Linux.

How do you rip a DVD to a bunch of MP4 files?

Here's some code I have used to rip DVDs I own.  This has made my life enormously easier, by letting me back up discs before they rot.  Now you can do the same too.

What does this do?

The program is fairly simple:

  1. It reads the DVD for title information.
  2. It then rips each title to a separate MP4 file, with a filename pattern of your choice.

No attempt is made to preserve chapter information per title.  Subtitles are also not preserved (DVD subtitles are images, not text).  If, however, the title has multiple audio tracks, those should be preserved correctly.  Another upside of this program is, the extraction process does not reencode the audio/video stream, which means you get to preserve the exact original quality of the disc you started with, and the extraction goes much faster than other programs like HandBrake.

What do I need?

The code requires mplayer and ffmpeg, both of which are available in nearly every Linux distribution on the face of the Earth, so you don't need to compile anything or do anything arcane.  It also requires Python 3.8 or later, which should be already installed on your Linux setup.

Fedora users are advised to install the RPM Fusion repositories to obtain DVD-codec-enabled ffmpeg and mplayer.

How do I use it?

To use:

  • Install mplayer and ffmpeg.
  • Store the program in some folder of your choosing, naming it e.g rip
  • Make it executable:
    chmod +x rip
  • Run the program:
    path/to/rip /dev/dvd0 title%s
    Note that you can also specify an ISO image file instead of a device path.

The program will then spit out a series of files title1.mp4, title2.mp4, and so on — the number of title files being equal to the number of titles stored in the DVD.

Program listing

Here is the program listing — read the code for more instructions:

#!/usr/bin/python

from subprocess import check_output, check_call
import os
import sys


def usage(msg=None):
    if msg:
        print(msg)
        print()
      
    print(f"""Quality-preserving DVD ripper to MP4.

This program will rip DVDs title by title ("episode by episode") to your
computer.  While it will preserve the quality of your DVDs as-is, without
reencoding, subtitles will be lost.

This program requires mplayer and ffmpeg installed on your PATH.
        
usage:

{os.path.basename(sys.argv[0])} <DVD image or device> <output file pattern for titles>

Example: if the output file pattern is title%s, then the output file in
the end will be title1.mp4, title2.mp4 and so on.""")
    sys.exit(os.EX_USAGE)


try:
    ifile = sys.argv[1]
    ofilepattern = sys.argv[2]
except IndexError:
    usage("error: either input file or output pattern are missing on the command line")

try:
    _ = ofilepattern % 64
except Exception:
    usage("error: the output file pattern must contain a Python string interpolation %s expression")


out = check_output(["mplayer", "dvd://", "-identify", "-frames", "0", "-dvd-device", ifile], text=True)
outl = [x for x in out.splitlines() if x.startswith("ID_DVD_TITLES=")]
numtitles = int(outl[0][len("ID_DVD_TITLES="):])

print("Will rip %s titles" % numtitles)
for x in range(1,numtitles+1):
    ofile = ofilepattern%x + ".vob"
    print("Ripping title %s to file %s" % (x, ofile))
    cmd = ["mplayer", "-dumpstream", "-dumpfile", ofile, "dvd://%s"%x, "-dvd-device", ifile, "-msglevel", "all=2"]
    check_call(cmd)
    oldofile = ofile
    ofile = ofilepattern%x + ".mp4"
    print("Encoding title %s to file %s" % (x, ofile))
    cmd = ["ffmpeg", "-i", oldofile, "-acodec", "copy", "-vcodec", "copy", "-y", "-loglevel", "warning", ofile]
    check_call(cmd)
    os.unlink(oldofile)