Decrypt DASH downloads after merging all segments

Since DASH doesn't have the ability to change keys dynamically per-track (Representation), there's no need for the DASH downloader to decrypt segments as they are downloaded (like HLS).

This halves the amount of processes needing to be opened as well as the I/O usage. It may result in noticeably lower CPU usage. Since the IOPS is lowered, you may even see an increase in download speed if downloading to something like a meh HDD.

This also fixes decryption in some weird edge-cases where decrypting each segment individually resulted in timestamp anomalies causing shaka to fail.
This commit is contained in:
rlaphoenix 2023-05-16 21:55:53 +01:00
parent bdc1203514
commit 2a8307b98d
1 changed files with 19 additions and 21 deletions

View File

@ -445,30 +445,19 @@ class DASH:
data_size = segment_save_path.stat().st_size data_size = segment_save_path.stat().st_size
if isinstance(track, Audio) or init_data: # fix audio decryption on ATVP by fixing the sample description index
# TODO: Should this be done in the video data or the init data?
if isinstance(track, Audio):
with open(segment_save_path, "rb+") as f: with open(segment_save_path, "rb+") as f:
segment_data = f.read() segment_data = f.read()
if isinstance(track, Audio):
# fix audio decryption on ATVP by fixing the sample description index
# TODO: Is this in mpeg data, or init data?
segment_data = re.sub( segment_data = re.sub(
b"(tfhd\x00\x02\x00\x1a\x00\x00\x00\x01\x00\x00\x00)\x02", b"(tfhd\x00\x02\x00\x1a\x00\x00\x00\x01\x00\x00\x00)\x02",
b"\\g<1>\x01", b"\\g<1>\x01",
segment_data segment_data
) )
# prepend the init data to be able to decrypt
if init_data:
f.seek(0) f.seek(0)
f.write(init_data)
f.write(segment_data) f.write(segment_data)
if drm:
# TODO: What if the manifest does not mention DRM, but has DRM
drm.decrypt(segment_save_path)
track.drm = None
if callable(track.OnDecrypted):
track.OnDecrypted(track)
return data_size return data_size
progress(total=len(segments)) progress(total=len(segments))
@ -524,10 +513,19 @@ class DASH:
download_sizes.clear() download_sizes.clear()
with open(save_path, "wb") as f: with open(save_path, "wb") as f:
if init_data:
f.write(init_data)
for segment_file in sorted(save_dir.iterdir()): for segment_file in sorted(save_dir.iterdir()):
f.write(segment_file.read_bytes()) f.write(segment_file.read_bytes())
segment_file.unlink() segment_file.unlink()
if drm:
# TODO: What if the manifest does not mention DRM, but has DRM
drm.decrypt(save_path)
track.drm = None
if callable(track.OnDecrypted):
track.OnDecrypted(track)
track.path = save_path track.path = save_path
save_dir.rmdir() save_dir.rmdir()