Choggbuster/dvd_ripper.py

100 lines
3.2 KiB
Python
Raw Permalink Normal View History

import itertools as ITT
import json
import os
import subprocess as SP
import sys
import time
from glob import glob
import cffi
from datetime import timedelta
from dvdnav import DVDError, DVDNav
from dvdread import DVDRead
from ff_d2v import make_d2v, make_meta
from vob_demux import demux
def close_file_del_if_empty(fh):
if not fh:
return False
if fh.tell() == 0:
fh.close()
os.unlink(fh.name)
return False
else:
fh.close()
return True
dur_thr = 60.0
def process_m2v_files(path):
for file in glob(os.path.join(path,"**", "*.m2v")):
make_meta(file)
make_d2v(file)
for dvd_path in ITT.chain.from_iterable(map(glob, sys.argv[1:])):
r = DVDRead(dvd_path)
# r.grab_ifos()
# r.grab_vobs()
# exit()
if os.path.isfile(dvd_path):
basename = os.path.splitext(os.path.basename(dvd_path))[0]
else:
basename = r.iso_disc_name or r.udf_disc_name
base_dir = os.path.join("out", "_".join([basename, r.disc_id]).replace(" ", "_"))
if os.path.isdir(base_dir):
print(f"Output foldrer {base_dir} exists, remove to re-rip DVD")
process_m2v_files(base_dir)
continue
os.makedirs(base_dir, exist_ok=True)
d = DVDNav(dvd_path)
to_demux = []
for k, v in d.titles.items():
out_folder=os.path.join(base_dir,f"t{k:03}")
v["duration"] = v["duration"].total_seconds()
if v["chapters"]:
v["chapters"] = [0.0]+[c.total_seconds() for c in v["chapters"]]
avg_chapter_len = v["duration"] / len(v["chapters"])
# if avg_chapter_len<10:
# continue
d.titles[k] = v
# if not v.get('audio'):
# print(f"[{k}|0] Skipping title {k} because it has no audio tracks")
# continue
# if not v.get('vts'):
# print(f"[{k}|0] Skipping title {k} because it has no title sets")
# continue
if v["duration"] < dur_thr:
print(
f"[{k}|0] Skipping title {k} because it is shorter than {dur_thr} seconds ({v['duration']} seconds)"
)
continue
os.makedirs(out_folder, exist_ok=True)
with open(os.path.join(out_folder, f"title.json"), "w") as fh:
json.dump(d.titles[k], fh, indent=4)
with open(os.path.join(out_folder, f"chapters.txt"), "w") as fh:
if set(v["chapters"])==set([0.0]):
continue
for n,t in enumerate(v["chapters"],1):
if abs(t-v["duration"])<1.0:
continue
print(f"CHAPTER{n:02}={timedelta(seconds=t)}",file=fh)
print(f"CHAPTER{n:02}NAME=Chapter {n}",file=fh)
for a in range(0, 99):
outfile = os.path.join(out_folder, f"{a:03}.vob")
to_demux.append(outfile)
fh = open(outfile, "wb")
try:
for block in d.get_blocks(k, a):
fh.write(block)
except DVDError as e:
if str(e) != "Invalid angle specified!":
raise
close_file_del_if_empty(fh)
to_demux = list(filter(os.path.isfile, to_demux))
for file in to_demux:
demux(file)
os.unlink(file)
process_m2v_files(base_dir)