refactor(DSCP): Prioritize clearkey HLS over Widevine DASH
- The program will now look for AES HLS instead of Widevine DASH. - Using '-v H.265' will request DASH manifest even if no H.265 tracks are available. This can be useful if HLS is not available for some reason.
This commit is contained in:
parent
a3ec1f86bc
commit
5a286926ec
@ -12,11 +12,11 @@ from urllib.parse import urljoin
|
|||||||
import click
|
import click
|
||||||
from click import Context
|
from click import Context
|
||||||
from devine.core.credential import Credential
|
from devine.core.credential import Credential
|
||||||
from devine.core.manifests.dash import DASH
|
from devine.core.manifests import DASH, HLS
|
||||||
from devine.core.search_result import SearchResult
|
from devine.core.search_result import SearchResult
|
||||||
from devine.core.service import Service
|
from devine.core.service import Service
|
||||||
from devine.core.titles import Episode, Movie, Movies, Series
|
from devine.core.titles import Episode, Movie, Movies, Series
|
||||||
from devine.core.tracks import Chapter, Tracks
|
from devine.core.tracks import Chapters, Tracks
|
||||||
from requests import Request
|
from requests import Request
|
||||||
|
|
||||||
|
|
||||||
@ -29,7 +29,10 @@ class DSCP(Service):
|
|||||||
Author: stabbedbybrick
|
Author: stabbedbybrick
|
||||||
Authorization: Cookies
|
Authorization: Cookies
|
||||||
Robustness:
|
Robustness:
|
||||||
L3: 2160p, AAC2.0
|
Widevine:
|
||||||
|
L3: 2160p, AAC2.0
|
||||||
|
ClearKey:
|
||||||
|
AES-128: 1080p, AAC2.0
|
||||||
|
|
||||||
\b
|
\b
|
||||||
Tips:
|
Tips:
|
||||||
@ -38,12 +41,12 @@ class DSCP(Service):
|
|||||||
EPISODE: /video/richard-hammonds-workshop/new-beginnings
|
EPISODE: /video/richard-hammonds-workshop/new-beginnings
|
||||||
SPORT: /video/sport/tnt-sports-1/uefa-champions-league
|
SPORT: /video/sport/tnt-sports-1/uefa-champions-league
|
||||||
- Use the --lang LANG_RANGE option to request non-english tracks
|
- Use the --lang LANG_RANGE option to request non-english tracks
|
||||||
- use -v H.265 to request H.265 tracks
|
- use -v H.265 to request H.265 UHD tracks (if available)
|
||||||
|
|
||||||
\b
|
\b
|
||||||
Known issues:
|
Notes:
|
||||||
- Devine can't properly parse certain manifests, causing an error in download workers.
|
- Using '-v H.265' will request DASH manifest even if no H.265 tracks are available.
|
||||||
- Sport streams specifically seem to be the most affected by this.
|
This can be useful if HLS is not available for some reason.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -118,43 +121,53 @@ class DSCP(Service):
|
|||||||
return Series(episodes)
|
return Series(episodes)
|
||||||
|
|
||||||
def get_tracks(self, title: Union[Movie, Episode]) -> Tracks:
|
def get_tracks(self, title: Union[Movie, Episode]) -> Tracks:
|
||||||
platform = "firetv" if self.vcodec == "H.265" else "desktop"
|
payload = {
|
||||||
res = self._request(
|
"videoId": title.id,
|
||||||
"POST",
|
"deviceInfo": {
|
||||||
"/playback/v3/videoPlaybackInfo",
|
"adBlocker": "false",
|
||||||
payload={
|
"drmSupported": "false",
|
||||||
"videoId": title.id,
|
"hwDecodingCapabilities": ["H264", "H265"],
|
||||||
"deviceInfo": {
|
"screen": {"width": 3840, "height": 2160},
|
||||||
"adBlocker": "false",
|
"player": {"width": 3840, "height": 2160},
|
||||||
"drmSupported": "true",
|
|
||||||
"hwDecodingCapabilities": ["H264", "H265"],
|
|
||||||
"screen": {"width": 3840, "height": 2160},
|
|
||||||
"player": {"width": 3840, "height": 2160},
|
|
||||||
},
|
|
||||||
"wisteriaProperties": {
|
|
||||||
"advertiser": {"firstPlay": 0, "fwIsLat": 0},
|
|
||||||
"device": {"browser": {"name": "chrome", "version": "96.0.4664.55"}, "type": platform},
|
|
||||||
"platform": platform,
|
|
||||||
"product": "dplus_emea",
|
|
||||||
"sessionId": str(uuid.uuid1()),
|
|
||||||
"streamProvider": {"suspendBeaconing": 0, "hlsVersion": 7, "pingConfig": 1},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
)
|
"wisteriaProperties": {
|
||||||
|
"product": "dplus_emea",
|
||||||
|
"sessionId": str(uuid.uuid1()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.vcodec == "H.265":
|
||||||
|
payload["wisteriaProperties"]["device"] = {
|
||||||
|
"browser": {"name": "chrome", "version": "96.0.4664.55"},
|
||||||
|
"type": "firetv",
|
||||||
|
}
|
||||||
|
payload["wisteriaProperties"]["platform"] = "firetv"
|
||||||
|
|
||||||
|
res = self._request("POST", "/playback/v3/videoPlaybackInfo", payload=payload)
|
||||||
|
|
||||||
self.license = None
|
|
||||||
streaming = res["data"]["attributes"]["streaming"][0]
|
streaming = res["data"]["attributes"]["streaming"][0]
|
||||||
|
streaming_type = streaming["type"].strip().lower()
|
||||||
manifest = streaming["url"]
|
manifest = streaming["url"]
|
||||||
|
|
||||||
|
self.token = None
|
||||||
|
self.license = None
|
||||||
if streaming["protection"]["drmEnabled"]:
|
if streaming["protection"]["drmEnabled"]:
|
||||||
self.token = streaming["protection"]["drmToken"]
|
self.token = streaming["protection"]["drmToken"]
|
||||||
self.license = streaming["protection"]["schemes"]["widevine"]["licenseUrl"]
|
self.license = streaming["protection"]["schemes"]["widevine"]["licenseUrl"]
|
||||||
|
|
||||||
tracks = DASH.from_url(url=manifest, session=self.session).to_tracks(language=title.language)
|
if streaming_type == "hls":
|
||||||
|
tracks = HLS.from_url(url=manifest, session=self.session).to_tracks(language=title.language)
|
||||||
|
|
||||||
|
elif streaming_type == "dash":
|
||||||
|
tracks = DASH.from_url(url=manifest, session=self.session).to_tracks(language=title.language)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unknown streaming type: {streaming_type}")
|
||||||
|
|
||||||
return tracks
|
return tracks
|
||||||
|
|
||||||
def get_chapters(self, title: Union[Movie, Episode]) -> list[Chapter]:
|
def get_chapters(self, title: Union[Movie, Episode]) -> Chapters:
|
||||||
return []
|
return Chapters()
|
||||||
|
|
||||||
def get_widevine_service_certificate(self, **_: Any) -> str:
|
def get_widevine_service_certificate(self, **_: Any) -> str:
|
||||||
return None
|
return None
|
||||||
@ -186,12 +199,8 @@ class DSCP(Service):
|
|||||||
|
|
||||||
seasons = [
|
seasons = [
|
||||||
self._request(
|
self._request(
|
||||||
"GET",
|
"GET", "/cms/collections/{}?{}&{}".format(content_id, season, show_id),
|
||||||
"/cms/collections/{}?{}&{}".format(content_id, season, show_id),
|
params={"include": "default", "decorators": "playbackAllowed,contentAction,badges"},
|
||||||
params={
|
|
||||||
"include": "default",
|
|
||||||
"decorators": "playbackAllowed,contentAction,badges",
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
for season in season_params
|
for season in season_params
|
||||||
]
|
]
|
||||||
@ -231,15 +240,12 @@ class DSCP(Service):
|
|||||||
if not video_id:
|
if not video_id:
|
||||||
raise IndexError("Episode id not found")
|
raise IndexError("Episode id not found")
|
||||||
|
|
||||||
params = {
|
params = {"decorators": "isFavorite", "include": "primaryChannel"}
|
||||||
"decorators": "isFavorite",
|
|
||||||
"include": "primaryChannel",
|
|
||||||
}
|
|
||||||
content = self._request("GET", "/content/videos/{}".format(video_id), params=params)
|
content = self._request("GET", "/content/videos/{}".format(video_id), params=params)
|
||||||
episode = content["data"]["attributes"]
|
episode = content["data"]["attributes"]
|
||||||
name = episode.get("name")
|
name = episode.get("name")
|
||||||
if episode.get("secondaryTitle"):
|
if episode.get("secondaryTitle"):
|
||||||
name += " - " + episode.get("secondaryTitle")
|
name += f" {episode.get('secondaryTitle')}"
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Episode(
|
Episode(
|
||||||
|
Loading…
Reference in New Issue
Block a user