mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-03-12 01:19:02 +00:00
feat(dl): add --worst flag and SHIELD OkHttp fingerprint preset
Add --worst CLI flag to select the lowest bitrate video track within a specified resolution (e.g. --worst -q 720). Requires -q/--quality. Add shield_okhttp TLS fingerprint preset for NVIDIA SHIELD Android TV with OkHttp 4.11 JA3 signature.
This commit is contained in:
@@ -506,6 +506,12 @@ class dl:
|
|||||||
@click.option(
|
@click.option(
|
||||||
"--reset-cache", "reset_cache", is_flag=True, default=False, help="Clear title cache before fetching."
|
"--reset-cache", "reset_cache", is_flag=True, default=False, help="Clear title cache before fetching."
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--worst",
|
||||||
|
is_flag=True,
|
||||||
|
default=False,
|
||||||
|
help="Select the lowest bitrate track within the specified quality. Requires -q/--quality.",
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--best-available",
|
"--best-available",
|
||||||
"best_available",
|
"best_available",
|
||||||
@@ -991,6 +997,7 @@ class dl:
|
|||||||
no_mux: bool,
|
no_mux: bool,
|
||||||
workers: Optional[int],
|
workers: Optional[int],
|
||||||
downloads: int,
|
downloads: int,
|
||||||
|
worst: bool,
|
||||||
best_available: bool,
|
best_available: bool,
|
||||||
split_audio: Optional[bool] = None,
|
split_audio: Optional[bool] = None,
|
||||||
*_: Any,
|
*_: Any,
|
||||||
@@ -1016,6 +1023,10 @@ class dl:
|
|||||||
self.log.error("--require-subs and --s-lang cannot be used together")
|
self.log.error("--require-subs and --s-lang cannot be used together")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if worst and not quality:
|
||||||
|
self.log.error("--worst requires -q/--quality to be specified")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
if select_titles and wanted:
|
if select_titles and wanted:
|
||||||
self.log.error("--select-titles and -w/--wanted cannot be used together")
|
self.log.error("--select-titles and -w/--wanted cannot be used together")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -1609,20 +1620,18 @@ class dl:
|
|||||||
for resolution, color_range, codec in product(
|
for resolution, color_range, codec in product(
|
||||||
quality or [None], non_hybrid_ranges, vcodec or [None]
|
quality or [None], non_hybrid_ranges, vcodec or [None]
|
||||||
):
|
):
|
||||||
match = next(
|
candidates = [
|
||||||
(
|
t
|
||||||
t
|
for t in non_hybrid_tracks
|
||||||
for t in non_hybrid_tracks
|
if (
|
||||||
if (
|
not resolution
|
||||||
not resolution
|
or t.height == resolution
|
||||||
or t.height == resolution
|
or int(t.width * (9 / 16)) == resolution
|
||||||
or int(t.width * (9 / 16)) == resolution
|
)
|
||||||
)
|
and (not color_range or t.range == color_range)
|
||||||
and (not color_range or t.range == color_range)
|
and (not codec or t.codec == codec)
|
||||||
and (not codec or t.codec == codec)
|
]
|
||||||
),
|
match = candidates[-1] if worst and candidates else next(iter(candidates), None)
|
||||||
None,
|
|
||||||
)
|
|
||||||
if match and match not in non_hybrid_selected:
|
if match and match not in non_hybrid_selected:
|
||||||
non_hybrid_selected.append(match)
|
non_hybrid_selected.append(match)
|
||||||
|
|
||||||
@@ -1632,20 +1641,18 @@ class dl:
|
|||||||
for resolution, color_range, codec in product(
|
for resolution, color_range, codec in product(
|
||||||
quality or [None], range_ or [None], vcodec or [None]
|
quality or [None], range_ or [None], vcodec or [None]
|
||||||
):
|
):
|
||||||
match = next(
|
candidates = [
|
||||||
(
|
t
|
||||||
t
|
for t in title.tracks.videos
|
||||||
for t in title.tracks.videos
|
if (
|
||||||
if (
|
not resolution
|
||||||
not resolution
|
or t.height == resolution
|
||||||
or t.height == resolution
|
or int(t.width * (9 / 16)) == resolution
|
||||||
or int(t.width * (9 / 16)) == resolution
|
)
|
||||||
)
|
and (not color_range or t.range == color_range)
|
||||||
and (not color_range or t.range == color_range)
|
and (not codec or t.codec == codec)
|
||||||
and (not codec or t.codec == codec)
|
]
|
||||||
),
|
match = candidates[-1] if worst and candidates else next(iter(candidates), None)
|
||||||
None,
|
|
||||||
)
|
|
||||||
if match and match not in selected_videos:
|
if match and match not in selected_videos:
|
||||||
selected_videos.append(match)
|
selected_videos.append(match)
|
||||||
title.tracks.videos = selected_videos
|
title.tracks.videos = selected_videos
|
||||||
|
|||||||
@@ -44,6 +44,17 @@ FINGERPRINT_PRESETS = {
|
|||||||
"akamai": "4:16777216|16711681|0|m,p,a,s",
|
"akamai": "4:16777216|16711681|0|m,p,a,s",
|
||||||
"description": "OkHttp 5.x (BoringSSL TLS stack)",
|
"description": "OkHttp 5.x (BoringSSL TLS stack)",
|
||||||
},
|
},
|
||||||
|
"shield_okhttp": {
|
||||||
|
"ja3": (
|
||||||
|
"771," # TLS 1.2
|
||||||
|
"4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53," # Ciphers (OkHttp 4.11)
|
||||||
|
"0-23-65281-10-11-35-16-5-13-51-45-43-21," # Extensions (incl padding ext 21)
|
||||||
|
"29-23-24," # Named groups (x25519, secp256r1, secp384r1)
|
||||||
|
"0" # EC point formats
|
||||||
|
),
|
||||||
|
"akamai": "4:16777216|16711681|0|m,p,a,s",
|
||||||
|
"description": "NVIDIA SHIELD Android TV OkHttp 4.11 (captured JA3)",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user