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.io import load_yaml
 | 
			
		||||
from pywidevine import Device, Cdm, RemoteCdm
 | 
			
		||||
from pywidevine import PSSH as PSSHWV
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
						break
 | 
			
		||||
					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()}")
 | 
			
		||||
						ctx.obj.cdm.set_service_certificate(
 | 
			
		||||
							session_id,
 | 
			
		||||
@ -490,7 +491,7 @@ def result(ctx, service, quality, range_, wanted, alang, slang, audio_only, subs
 | 
			
		||||
						ctx.obj.cdm.parse_license(
 | 
			
		||||
							session_id,
 | 
			
		||||
							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,
 | 
			
		||||
								track=track,
 | 
			
		||||
								session_id=session_id
 | 
			
		||||
@ -515,7 +516,7 @@ def result(ctx, service, quality, range_, wanted, alang, slang, audio_only, subs
 | 
			
		||||
						
 | 
			
		||||
					
 | 
			
		||||
					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 [
 | 
			
		||||
						(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,
 | 
			
		||||
                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:
 | 
			
		||||
            asyncio.run(aria2c(
 | 
			
		||||
                self.url,
 | 
			
		||||
 | 
			
		||||
@ -139,17 +139,33 @@ def parse(*, url=None, data=None, source, session=None, downloader=None):
 | 
			
		||||
                for protection in protections:
 | 
			
		||||
                    # For HMAX, the PSSH has multiple keys but the PlayReady ContentProtection tag
 | 
			
		||||
                    # contains the correct KID
 | 
			
		||||
                    if not kid:
 | 
			
		||||
                        kid = protection.get("default_KID")
 | 
			
		||||
                    if kid:
 | 
			
		||||
                        kid = uuid.UUID(kid).hex
 | 
			
		||||
                    else:
 | 
			
		||||
                        if not kid:
 | 
			
		||||
                            kid = protection.get("kid")
 | 
			
		||||
                            if kid:
 | 
			
		||||
                                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
 | 
			
		||||
                    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")
 | 
			
		||||
                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([
 | 
			
		||||
			"-dv", "all",
 | 
			
		||||
			"-ds", "all", 
 | 
			
		||||
			"-M", "format=mp4:muxer=ffmpeg",
 | 
			
		||||
		])
 | 
			
		||||
		if track.source != "HS":
 | 
			
		||||
			arguments.extend(["-M", "format=mp4"])
 | 
			
		||||
	else:
 | 
			
		||||
		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)
 | 
			
		||||
		#print(arg_str)
 | 
			
		||||
		p = subprocess.run(arg_str, check=True)
 | 
			
		||||
		#os.system(arg_str)
 | 
			
		||||
	except subprocess.CalledProcessError:
 | 
			
		||||
		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