fix(remote): forward track selection params to server and improve error display

Forward range, vcodec, quality, and best_available from client to server so services fetch the correct manifests (e.g. HDR10 instead of SDR).
Exit with error when no video tracks match the requested range filter.
Use Rich logger for remote API errors instead of plain click.ClickException.
This commit is contained in:
imSp4rky
2026-03-30 05:20:32 +00:00
parent 1a6f2c5b7e
commit d3594ca67c
3 changed files with 60 additions and 4 deletions
+3
View File
@@ -1561,6 +1561,9 @@ class dl:
missing_ranges = [r for r in range_ if not any(x.range == r for x in title.tracks.videos)]
for color_range in missing_ranges:
self.log.warning(f"Skipping {color_range.name} video tracks as none are available.")
if not title.tracks.videos:
self.log.error(f"There's no {', '.join(r.name for r in range_)} Video Track...")
sys.exit(1)
if vbitrate:
if any(r == Video.Range.HYBRID for r in range_):
+37 -1
View File
@@ -1231,7 +1231,39 @@ def _create_service_instance(
cdm = _resolve_server_cdm(normalized_service, profile, data.get("cdm_type"))
ctx.obj = ContextData(config=service_config, cdm=cdm, proxy_providers=proxy_providers, profile=profile)
ctx.params = {"proxy": proxy_param, "no_proxy": data.get("no_proxy", False)}
# Reconstruct track selection params from client data
from unshackle.core.tracks import Video
range_names = data.get("range_")
range_values = None
if range_names:
range_values = []
for name in range_names:
try:
range_values.append(Video.Range[name])
except KeyError:
pass
range_values = range_values or None
vcodec_names = data.get("vcodec")
vcodec_values = None
if vcodec_names:
vcodec_values = []
for name in vcodec_names:
try:
vcodec_values.append(Video.Codec[name])
except KeyError:
pass
vcodec_values = vcodec_values or None
ctx.params = {
"proxy": proxy_param,
"no_proxy": data.get("no_proxy", False),
"range_": range_values,
"vcodec": vcodec_values,
"quality": data.get("quality"),
"best_available": data.get("best_available", False),
}
service_module = Services.load(normalized_service)
@@ -1258,6 +1290,10 @@ def _create_service_instance(
"client_region",
"no_proxy",
"cdm_type",
"range_",
"vcodec",
"quality",
"best_available",
}
service_init_params = inspect.signature(service_module.__init__).parameters
+20 -3
View File
@@ -68,7 +68,8 @@ class RemoteClient:
if resp.status_code >= 400:
error_msg = result.get("message", resp.text)
error_code = result.get("error_code", "UNKNOWN")
raise click.ClickException(f"Server error [{error_code}]: {error_msg}")
log.error(f"Server error [{error_code}]: {error_msg}")
raise SystemExit(1)
return result
def post(self, endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]:
@@ -492,6 +493,20 @@ class RemoteService:
create_data["profile"] = profile
if no_proxy:
create_data["no_proxy"] = True
# Forward track selection params so the server fetches the right manifests
if self.ctx.parent:
range_ = self.ctx.parent.params.get("range_")
if range_:
create_data["range_"] = [r.name for r in range_]
vcodec = self.ctx.parent.params.get("vcodec")
if vcodec:
create_data["vcodec"] = [c.name for c in vcodec]
quality = self.ctx.parent.params.get("quality")
if quality:
create_data["quality"] = list(quality)
if self.ctx.parent.params.get("best_available"):
create_data["best_available"] = True
if self._service_params:
create_data.update(self._service_params)
@@ -530,7 +545,8 @@ class RemoteService:
if status == "failed":
error = resp.get("error", "Authentication failed on server")
raise click.ClickException(f"Remote auth failed: {error}")
log.error(f"Remote auth failed: {error}")
raise SystemExit(1)
if status == "pending_input":
prompt = resp.get("prompt", "Enter input: ")
@@ -543,7 +559,8 @@ class RemoteService:
time.sleep(poll_interval)
raise click.ClickException("Remote authentication timed out")
log.error("Remote authentication timed out")
raise SystemExit(1)
def get_titles(self) -> Titles_T:
if self._titles is not None: