Hotstar with DRM
I forgot to test Hotstar with DRM. Made changes to support DRM correctly.
This commit is contained in:
parent
1c15375821
commit
09e03b47f7
@ -27,6 +27,7 @@ from vinetrimmer.utils.click import (AliasedGroup, ContextData, acodec_param, la
|
|||||||
from vinetrimmer.utils.collections import as_list, merge_dict
|
from vinetrimmer.utils.collections import as_list, merge_dict
|
||||||
from vinetrimmer.utils.io import load_yaml
|
from vinetrimmer.utils.io import load_yaml
|
||||||
from pywidevine import Device, Cdm, RemoteCdm
|
from pywidevine import Device, Cdm, RemoteCdm
|
||||||
|
from pywidevine import PSSH as PSSHWV
|
||||||
|
|
||||||
from vinetrimmer.vendor.pymp4.parser import Box
|
from vinetrimmer.vendor.pymp4.parser import Box
|
||||||
|
|
||||||
@ -476,7 +477,7 @@ def result(ctx, service, quality, range_, wanted, alang, slang, audio_only, subs
|
|||||||
skip_title = True
|
skip_title = True
|
||||||
break
|
break
|
||||||
if "common_privacy_cert" in dir(ctx.obj.cdm):
|
if "common_privacy_cert" in dir(ctx.obj.cdm):
|
||||||
session_id = ctx.obj.cdm.open(track.pssh)
|
session_id = ctx.obj.cdm.open()
|
||||||
log.info(f"CDM Session ID - {session_id.hex()}")
|
log.info(f"CDM Session ID - {session_id.hex()}")
|
||||||
ctx.obj.cdm.set_service_certificate(
|
ctx.obj.cdm.set_service_certificate(
|
||||||
session_id,
|
session_id,
|
||||||
@ -490,7 +491,7 @@ def result(ctx, service, quality, range_, wanted, alang, slang, audio_only, subs
|
|||||||
ctx.obj.cdm.parse_license(
|
ctx.obj.cdm.parse_license(
|
||||||
session_id,
|
session_id,
|
||||||
service.license(
|
service.license(
|
||||||
challenge=ctx.obj.cdm.get_license_challenge(session_id),
|
challenge=ctx.obj.cdm.get_license_challenge(session_id=session_id, pssh=PSSHWV(track.pssh)),
|
||||||
title=title,
|
title=title,
|
||||||
track=track,
|
track=track,
|
||||||
session_id=session_id
|
session_id=session_id
|
||||||
@ -515,7 +516,7 @@ def result(ctx, service, quality, range_, wanted, alang, slang, audio_only, subs
|
|||||||
|
|
||||||
|
|
||||||
content_keys = [
|
content_keys = [
|
||||||
(x.kid, x.key) for x in ctx.obj.cdm.get_keys(session_id, content_only=True)
|
(str(x.kid).replace("-", ""), x.key.hex()) for x in ctx.obj.cdm.get_keys(session_id) if x.type == "CONTENT"
|
||||||
] if "common_privacy_cert" in dir(ctx.obj.cdm) else [
|
] if "common_privacy_cert" in dir(ctx.obj.cdm) else [
|
||||||
(str(x.key_id).replace("-", ""), x.key.hex()) for x in ctx.obj.cdm.get_keys(session_id)
|
(str(x.key_id).replace("-", ""), x.key.hex()) for x in ctx.obj.cdm.get_keys(session_id)
|
||||||
]
|
]
|
||||||
|
Binary file not shown.
@ -419,6 +419,8 @@ class Track:
|
|||||||
headers,
|
headers,
|
||||||
proxy if self.needs_proxy else None
|
proxy if self.needs_proxy else None
|
||||||
))
|
))
|
||||||
|
if self.__class__.__name__ == "AudioTrack":
|
||||||
|
save_path = save_path.replace(".mp4", f".{str(self.language)[:2]}.m4a")
|
||||||
else:
|
else:
|
||||||
asyncio.run(aria2c(
|
asyncio.run(aria2c(
|
||||||
self.url,
|
self.url,
|
||||||
|
@ -139,17 +139,33 @@ def parse(*, url=None, data=None, source, session=None, downloader=None):
|
|||||||
for protection in protections:
|
for protection in protections:
|
||||||
# For HMAX, the PSSH has multiple keys but the PlayReady ContentProtection tag
|
# For HMAX, the PSSH has multiple keys but the PlayReady ContentProtection tag
|
||||||
# contains the correct KID
|
# contains the correct KID
|
||||||
|
if not kid:
|
||||||
kid = protection.get("default_KID")
|
kid = protection.get("default_KID")
|
||||||
if kid:
|
if not kid:
|
||||||
kid = uuid.UUID(kid).hex
|
|
||||||
else:
|
|
||||||
kid = protection.get("kid")
|
kid = protection.get("kid")
|
||||||
if kid:
|
if kid:
|
||||||
kid = uuid.UUID(bytes_le=base64.b64decode(kid)).hex
|
kid = uuid.UUID(bytes_le=base64.b64decode(kid)).hex
|
||||||
if (protection.get("schemeIdUri") or "").lower() != "urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":
|
else:
|
||||||
|
kid = uuid.UUID(kid).hex
|
||||||
|
if (protection.get("schemeIdUri") or "").lower() not in ["urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95", "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"]:
|
||||||
continue
|
continue
|
||||||
pssh = protection.findtext("pssh")
|
pssh = protection.findtext("pssh")
|
||||||
|
|
||||||
|
"""
|
||||||
|
if pssh and ((protection.get("schemeIdUri") or "").lower() == "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed3"):
|
||||||
|
pssh = base64.b64decode(pssh)
|
||||||
|
# noinspection PyBroadException
|
||||||
|
try:
|
||||||
|
pssh = Box.parse(pssh)
|
||||||
|
except Exception:
|
||||||
|
pssh = Box.parse(Box.build(dict(
|
||||||
|
type=b"pssh",
|
||||||
|
version=0, # can only assume version & flag are 0
|
||||||
|
flags=0,
|
||||||
|
system_ID=Cdm.uuid,
|
||||||
|
init_data=pssh
|
||||||
|
)))
|
||||||
|
"""
|
||||||
|
|
||||||
rep_base_url = rep.findtext("BaseURL")
|
rep_base_url = rep.findtext("BaseURL")
|
||||||
if rep_base_url and source not in ["DSCP", "DSNY"]: # TODO: Don't hardcode services
|
if rep_base_url and source not in ["DSCP", "DSNY"]: # TODO: Don't hardcode services
|
||||||
|
@ -294,8 +294,9 @@ async def m3u8dl(uri, out, track, headers=None, proxy=None):
|
|||||||
arguments.extend([
|
arguments.extend([
|
||||||
"-dv", "all",
|
"-dv", "all",
|
||||||
"-ds", "all",
|
"-ds", "all",
|
||||||
"-M", "format=mp4:muxer=ffmpeg",
|
|
||||||
])
|
])
|
||||||
|
if track.source != "HS":
|
||||||
|
arguments.extend(["-M", "format=mp4"])
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"{track.__class__.__name__} not supported yet!")
|
raise ValueError(f"{track.__class__.__name__} not supported yet!")
|
||||||
|
|
||||||
@ -303,8 +304,5 @@ async def m3u8dl(uri, out, track, headers=None, proxy=None):
|
|||||||
arg_str = " ".join(arguments)
|
arg_str = " ".join(arguments)
|
||||||
#print(arg_str)
|
#print(arg_str)
|
||||||
p = subprocess.run(arg_str, check=True)
|
p = subprocess.run(arg_str, check=True)
|
||||||
#os.system(arg_str)
|
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
raise ValueError("N_m3u8DL-RE failed too many times, aborting")
|
raise ValueError("N_m3u8DL-RE failed too many times, aborting")
|
||||||
|
|
||||||
# Removed above call using subprocess due to it failing to correctly pass --header value. The problem might be with spaces within the header string, I think? I know it's not recommended to use os.system but didn't have a choice
|
|
Loading…
x
Reference in New Issue
Block a user