From f4f394f21b6fc7b54a942cab41f06680eca45b5e Mon Sep 17 00:00:00 2001 From: Julian Mutter Date: Thu, 18 Aug 2022 17:15:40 +0200 Subject: [PATCH] Add transcoding script (no series support yet) --- ripper/transfer_ripped.py | 2 +- transcoder/transcode_dvd.py | 140 ++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 transcoder/transcode_dvd.py diff --git a/ripper/transfer_ripped.py b/ripper/transfer_ripped.py index 3441160..7ae5e29 100755 --- a/ripper/transfer_ripped.py +++ b/ripper/transfer_ripped.py @@ -3,7 +3,7 @@ import os import subprocess -DESTINATION_FOLDER = "transcode/raw" # pi@192.168.xxx:/home/pi/transcode/raw +DESTINATION_FOLDER = "transcoder/raw" # pi@192.168.xxx:/home/pi/transcoder/raw RIPPED_DIR = "ripped" diff --git a/transcoder/transcode_dvd.py b/transcoder/transcode_dvd.py new file mode 100644 index 0000000..c6b4dc5 --- /dev/null +++ b/transcoder/transcode_dvd.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import shutil +from datetime import datetime + +TMP_DIR = "tmp" +RAW_DIR = "raw" +TRANSCODED_DIR = "transcoded" +LOGFILE = "transcode.log" + +HANDBRAKE_PRESET = "General/HQ 1080p30 Surround" +HANDBRAKE_AUDIO_LANG_LIST = "de,en" +OUT_VIDEO_FORMAT = ".m4v" +MIN_EPISODES_DURATION_SECONDS = 10 * 60 + + +def main(): + chdir_to_script_dir() + mkdirs() + for dvd_type in ("movie", "series"): + for dvd in filter(is_dvd_files_not_locked, list_ripped_dvds(dvd_type)): + success = transcode_ripped_dvd(dvd, dvd_type) + dvd_title = "" # TODO + if success: + mv_video_from_tmp_to_transcoded_dir(dvd_title, dvd_type) + write_to_logfile(dvd_type, dvd_title, "Success") + delete_original_video_files(dvd) + delete_transcoding_logfile(dvd) + else: + write_to_logfile(dvd_type, dvd_title, "FAILURE") + + delete_tmp_dir() + + +def chdir_to_script_dir(): + os.chdir(os.path.dirname(__file__)) + + +def mkdirs(): + os.makedirs(TMP_DIR, exist_ok=True) + os.makedirs(TRANSCODED_DIR, exist_ok=True) + os.makedirs(RAW_DIR, exist_ok=True) + os.makedirs(os.path.join(RAW_DIR, "movie"), exist_ok=True) + os.makedirs(os.path.join(RAW_DIR, "series"), exist_ok=True) + + +def list_ripped_dvds(dvd_type): + path = os.path.join(RAW_DIR, dvd_type) + try: + dvd_titles = os.listdir(path) + dvd_titles = filter(lambda title: not title.endswith(".lock"), dvd_titles) + dvd_titles = filter(lambda title: not title.endswith(".err.log"), dvd_titles) + return map(lambda dvd_title: os.path.join(path, dvd_title), dvd_titles) + except FileNotFoundError: + print( + f"Directory {path} not found. Running the ripper script will generate it." + ) + exit(1) + + +def is_dvd_files_not_locked(dvd): + return not os.path.exists(dvd + ".lock") and not os.path.exists(dvd + ".err.log") + + +def transcode_ripped_dvd(ripped_dvd, dvd_type): + if dvd_type == "movie": + return transcode_movie(ripped_dvd) + else: + return transcode_series(ripped_dvd) + + +def transcode_movie(movie): + video_file_name = os.path.basename(movie) + OUT_VIDEO_FORMAT + output_file = os.path.join(TMP_DIR, video_file_name) + log_file_path = movie + ".err.log" + + with open(log_file_path, "w") as log_file: + + proc = subprocess.run( + [ + "HandBrakeCLI", + "--preset", + HANDBRAKE_PRESET, + "--main-feature", + "--first-audio", + "--audio-lang-list", + HANDBRAKE_AUDIO_LANG_LIST, + "--input", + movie, + "--output", + output_file, + ], + stderr=subprocess.STDOUT, + stdout=log_file, + ) + return proc.returncode == 0 + + +def transcode_series(series): + # --min-duration MIN_EPISODES_DURATION + # --title 1 + # --title 2 + # etc + pass + + +def mv_video_from_tmp_to_transcoded_dir(video_title, video_type): + src = os.path.join(TMP_DIR, video_title) + dst = os.path.join(TRANSCODED_DIR, video_type, video_title) + + shutil.move(src, dst) + + +def write_to_logfile(dvd_type, dvd_title, tag): + date = datetime.now().strftime("%d.%m.%Y %H:%M:%S") + log_line = f'{date} - {dvd_type} - "{dvd_title}" - {tag}' + + with open(LOGFILE, "a") as file: + file.write(log_line + "\n") + + +def delete_transcoding_logfile(dvd): + os.remove(dvd + "err.log") + + +def delete_original_video_files(folder): + os.rmdir(folder) + + +def delete_tmp_dir(): + try: + os.rmdir(os.path.join(TMP_DIR)) + except FileNotFoundError: + pass + + +if __name__ == "__main__": + main()