Playready

This commit is contained in:
chu23465 2024-12-10 08:14:32 +05:30 committed by GitHub
parent 3d5742471c
commit 4eb227493e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 21 additions and 10 deletions

View File

@ -121,7 +121,7 @@ Config file values can be overridden using command line arguments.
| `--codec-music-video` / `codec_music_video` | Music video codec. | `h264` |
| `--quality-post` / `quality_post` | Post video quality. | `best` |
| `--no-config-file`, `-n` / - | Do not use a config file. | `false` |
| `--playready`, `playready` / - | Use Playready DRM | `false` |
### Tags variables
The following variables can be used in the template folders/files and/or in the `exclude_tags` list:
@ -178,6 +178,7 @@ The following codecs are available:
* `aac-legacy`
* `aac-he-legacy`
The following codecs are also available, **but are not guaranteed to work**, as currently most (or all) of the songs fails to be downloaded when using them:
* `aac`
* `aac-he`
@ -190,6 +191,7 @@ The following codecs are also available, **but are not guaranteed to work**, as
* `alac`
* `ask`
* When using this option, Gamdl will ask you which codec from this list to use that is available for the song.
With PlayReady and the right CDM, binaural, atmos and aac should download.
### Music videos codecs
The following codecs are available:

View File

@ -1,6 +1,7 @@
from __future__ import annotations
import functools
import json
import re
import time
import typing
@ -41,7 +42,7 @@ class AppleMusicApi:
self.storefront = self.session.cookies.get_dict()["itua"]
self.session.headers.update(
{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.2903.86", #"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0",
"User-Agent": "iTunes/12.11.3 (Windows; Microsoft Windows 10 x64 Professional Edition (Build 19041); x64) AppleWebKit/7611.1022.4001.1 (dt:2)", #"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.2903.86", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0",
"Accept": "application/json",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate, br",
@ -273,7 +274,7 @@ class AppleMusicApi:
"uri": track_uri,
"adamId": track_id,
"isLibrary": False,
"user-initiated": True,
"user-initiated": False,
},
)
try:
@ -286,7 +287,12 @@ class AppleMusicApi:
requests.exceptions.JSONDecodeError,
AssertionError,
):
if response_dict.get("status") == -1002:
raise Exception("-1002: You do not own the title in the requested quality.")
elif response_dict.get("status") == -1021:
raise Exception("-1021: Device has insufficient security level or is blacklisted/revoked.")
self._raise_response_exception(response)
return license

View File

@ -561,9 +561,10 @@ def main(
logger.warning(
f"({queue_progress}) Song is not downloadable or is not"
" available in the chosen codec, skipping"
f"\n{stream_info.pssh}, {stream_info.stream_url}"
)
continue
logger.debug(f"{stream_info.pssh}, {stream_info.stream_url}")
logger.debug("Getting decryption key")
decryption_key = downloader.get_decryption_key(
stream_info.pssh, track_metadata["id"]

View File

@ -343,7 +343,7 @@ class Downloader:
elif self.drm == DRM.Playready:
from pyplayready import PSSH
try:
pssh_obj = PSSH(pssh.split(",")[-1]).get_wrm_headers(downgrade_to_v4=False)[0]
pssh_obj = PSSH(pssh.split(",")[-1]).get_wrm_headers(downgrade_to_v4=True)[0] # Downgrade to v4 has to be set to True
cdm_session = self.cdm.open()
challenge = base64.b64encode(
self.cdm.get_license_challenge(cdm_session, pssh_obj).encode("utf-8")
@ -354,13 +354,15 @@ class Downloader:
challenge,
self.drm,
)
self.cdm.parse_license(cdm_session, license)
decryption_key = next(
i for i in self.cdm.get_keys(cdm_session) if i.key_type == "AES_128_CBC"
).key.hex()
self.cdm.parse_license(cdm_session, base64.b64decode(license.encode("utf-8")).decode("utf-8"))
decryption_keys = [i.key.hex() for i in self.cdm.get_keys(cdm_session)]
if len(decryption_keys) != 1:
raise ValueError(f"Expecting only one key to be returned, but {len(decryption_keys)} keys were returned")
elif len(decryption_keys) == 1 and "32b8ade1769e26b1ffb8986352793fc6" in decryption_keys:
raise ValueError("Only default key returned for track.")
finally:
self.cdm.close(cdm_session)
return decryption_key
return decryption_keys[0]
def download(self, path: Path, stream_url: str):
if self.download_mode == DownloadMode.YTDLP: