Skip to content

Instantly share code, notes, and snippets.

@bsidhom
Created December 27, 2017 19:59
Show Gist options
  • Save bsidhom/80e600fcf918db931db84b87a0f57398 to your computer and use it in GitHub Desktop.
Save bsidhom/80e600fcf918db931db84b87a0f57398 to your computer and use it in GitHub Desktop.
Rip all chapters from a DVD to separate files
#!/usr/bin/env python3
import argparse
import datetime
import os
import os.path
import subprocess
import time
def log_message(message):
print("{}: {}".format(datetime.datetime.now().isoformat(), message))
def get_chapter_lengths(device_file):
result = subprocess.run(["lsdvd", "-c", "-Oy", device_file], stdout=subprocess.PIPE, encoding="utf-8")
result.check_returncode()
locs = {}
# lsdvd = {...}
exec(result.stdout, {}, locs)
return [(title['ix'], chapter['ix'], chapter['length']) for title in
locs['lsdvd']['track'] for chapter in title['chapter']]
def build_handbrake_args(input_device, title, chapter, output_path):
return [
"HandBrakeCLI",
"-v",
"-i", str(input_device),
"-t", str(title),
"-c", str(chapter),
"-o", str(output_path),
"-f", "av_mp4",
"-e", "x264",
"-E", "av_aac",
"--no-markers",
"--optimize",
"--no-ipod-atom",
"--encoder-profile", "main",
"--encoder-preset", "slow",
"-q", "16.0",
"--no-two-pass",
]
def rip_chapter(title, chapter, output_dir, device_file, log_file):
fname = "{:02d}_{:02d}.mp4".format(title, chapter)
output_path = os.path.join(output_dir, fname)
log_message("ripping {}/{} to {}".format(title, chapter, output_path))
args = build_handbrake_args(device_file, title, chapter, output_path)
result = subprocess.run(args, stdout=log_file, stderr=log_file)
log_file.flush()
result.check_returncode()
log_message("finished {}/{}".format(title, chapter))
def main():
parser = argparse.ArgumentParser(description="Rip all titles and chapters from a DVD.")
parser.add_argument("--output_dir", type=str, required=True, help="Output directory")
parser.add_argument("--log_file", type=argparse.FileType("a",
encoding="UTF-8"), default=open(os.devnull, "w"), help="Log file")
parser.add_argument("--device_file", type=str, default="/dev/dvd",
help="DVD device file to read from")
args = parser.parse_args()
if not os.path.isdir(args.output_dir):
raise Exception("No such directory: {}".format(args.output_dir))
if not os.path.exists(args.device_file):
raise Exception("No such DVD device file: {}".format(args.device_file))
metadata = get_chapter_lengths(args.device_file)
total_length = sum(x[2] for x in metadata)
progress = 0.0
start_time = time.time()
for title, chapter, length in metadata:
rip_chapter(title, chapter, args.output_dir, args.device_file, args.log_file)
progress += length
progress_fraction = progress / total_length
remaining_fraction = (total_length - progress) / total_length
elapsed_sec = time.time() - start_time
remaining_sec = elapsed_sec / progress_fraction * remaining_fraction
log_message("Progress: {:03.3f}% Elapsed: {:02.2f} min Remaining: {:02.2f} min".format(
progress_fraction * 100.0,
elapsed_sec / 60.0,
remaining_sec / 60.0))
args.log_file.close()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment