From 0116c278af0a87d4682f3005caae469b21af810d Mon Sep 17 00:00:00 2001 From: rlaphoenix Date: Fri, 12 Jan 2024 01:11:47 +0000 Subject: [PATCH] Absorb original file and path in Decrypt, Repack, & Range Operations To possibly support download resuming in the future, the file names for the decrypt, repack, and change range functions were simplified and once output has finished it then deletes the original input file and re-uses the original input file path. The file names were changed to just append `_repack`, `_decrypted`, `_full_range` etc. to the filename rather than using a duplex extension (`.repack.mp4`, `.decrypted.mp4`, `.range0.mp4`). This is all so that code to check if the file was already downloaded can be simpler. Instead of having to check if 4x different possible file names for a completed download existed, it checks one. --- devine/commands/dl.py | 7 ++----- devine/core/drm/widevine.py | 6 +++--- devine/core/tracks/track.py | 10 ++++++---- devine/core/tracks/video.py | 11 +++++++---- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/devine/commands/dl.py b/devine/commands/dl.py index c67b170..216bfd5 100644 --- a/devine/commands/dl.py +++ b/devine/commands/dl.py @@ -822,13 +822,10 @@ class dl: save_dir = save_path.parent def cleanup(): - # e.g., foo.mp4 + # track file (e.g., "foo.mp4") save_path.unlink(missing_ok=True) - # e.g., foo.mp4.aria2 + # aria2c control file (e.g., "foo.mp4.aria2") save_path.with_suffix(f"{save_path.suffix}.aria2").unlink(missing_ok=True) - for file in config.directories.temp.glob(f"{save_path.stem}.*{save_path.suffix}"): - # e.g., foo.decrypted.mp4, foo.repack.mp4, and such - file.unlink() if save_dir.exists() and save_dir.name.endswith("_segments"): shutil.rmtree(save_dir) diff --git a/devine/core/drm/widevine.py b/devine/core/drm/widevine.py index dff1139..90af853 100644 --- a/devine/core/drm/widevine.py +++ b/devine/core/drm/widevine.py @@ -230,12 +230,12 @@ class Widevine: if not path or not path.exists(): raise ValueError("Tried to decrypt a file that does not exist.") - decrypted_path = path.with_suffix(f".decrypted{path.suffix}") + output_path = path.with_stem(f"{path.stem}_decrypted") config.directories.temp.mkdir(parents=True, exist_ok=True) try: arguments = [ - f"input={path},stream=0,output={decrypted_path}", + f"input={path},stream=0,output={output_path}", "--enable_raw_key_decryption", "--keys", ",".join([ *[ @@ -294,7 +294,7 @@ class Widevine: path.unlink() if not stream_skipped: - shutil.move(decrypted_path, path) + shutil.move(output_path, path) except subprocess.CalledProcessError as e: if e.returncode == 0xC000013A: # STATUS_CONTROL_C_EXIT raise KeyboardInterrupt() diff --git a/devine/core/tracks/track.py b/devine/core/tracks/track.py index 8db2eef..f8a0503 100644 --- a/devine/core/tracks/track.py +++ b/devine/core/tracks/track.py @@ -229,20 +229,21 @@ class Track: if not executable: raise EnvironmentError("FFmpeg executable \"ffmpeg\" was not found but is required for this call.") - repacked_path = self.path.with_suffix(f".repack{self.path.suffix}") + original_path = self.path + output_path = original_path.with_stem(f"{original_path.stem}_repack") def _ffmpeg(extra_args: list[str] = None): subprocess.run( [ executable, "-hide_banner", "-loglevel", "error", - "-i", self.path, + "-i", original_path, *(extra_args or []), # Following are very important! "-map_metadata", "-1", # don't transfer metadata to output file "-fflags", "bitexact", # only have minimal tag data, reproducible mux "-codec", "copy", - str(repacked_path) + str(output_path) ], check=True, stdout=subprocess.PIPE, @@ -258,7 +259,8 @@ class Track: else: raise - self.swap(repacked_path) + self.swap(output_path) + self.move(original_path) def move(self, target: Union[str, Path]) -> bool: """ diff --git a/devine/core/tracks/video.py b/devine/core/tracks/video.py index 8dcdefb..c7cacc5 100644 --- a/devine/core/tracks/video.py +++ b/devine/core/tracks/video.py @@ -188,17 +188,20 @@ class Video(Track): Video.Codec.HEVC: "hevc_metadata" }[self.codec] - changed_path = self.path.with_suffix(f".range{range_}{self.path.suffix}") + original_path = self.path + output_path = original_path.with_stem(f"{original_path.stem}_{['limited', 'full'][range_]}_range") + subprocess.run([ executable, "-hide_banner", "-loglevel", "panic", - "-i", self.path, + "-i", original_path, "-codec", "copy", "-bsf:v", f"{filter_key}=video_full_range_flag={range_}", - str(changed_path) + str(output_path) ], check=True) - self.swap(changed_path) + self.swap(output_path) + self.move(original_path) def ccextractor( self, track_id: Any, out_path: Union[Path, str], language: Language, original: bool = False