From c2d669dcc5c581e8fe3a713d89237a97ce13a114 Mon Sep 17 00:00:00 2001 From: Nirvana Date: Fri, 3 Apr 2026 15:14:23 +0200 Subject: [PATCH] Fix movetv --- routes/streams.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/routes/streams.py b/routes/streams.py index 0c21deb..06feda8 100644 --- a/routes/streams.py +++ b/routes/streams.py @@ -29,6 +29,7 @@ from datetime import datetime from bottle import HTTPResponse, redirect, request, response from streaming_providers.base.utils import logger +from streaming_providers.base.utils.manifest_utils import ManifestUtils # --------------------------------------------------------------------------- # Content-type constants — single source of truth used by helpers and routes @@ -227,6 +228,30 @@ def setup_stream_routes(app, manager, service): ) return False # assume no headers needed; let the redirect attempt proceed + def _inject_base_url(manifest_text: str, base_url: str) -> str: + """ + Inject an absolute BaseURL element at the MPD root level if one is not + already present. This anchors relative segment URLs to the upstream + origin, which is necessary when the manifest is served from a different + host than the CDN (e.g. requires_manifest_context providers). + """ + import re + + # If a root-level BaseURL is already present, leave it alone — + # the manifest author's intent takes precedence. + existing = ManifestUtils.extract_base_urls(manifest_text) + if existing: + return manifest_text + + # Insert immediately after the opening tag. + base_url_element = f"{base_url}" + return re.sub( + r"(]*>)", + rf"\1\n {base_url_element}", + manifest_text, + count=1, + ) + def _resolve_stream( content_type: str, provider: str, @@ -333,7 +358,6 @@ def setup_stream_routes(app, manager, service): ) if provider_instance and getattr(provider_instance, 'requires_manifest_context', False): - # For providers that need manifest context, fetch and return the manifest directly logger.debug( f"Provider {provider} requires manifest context — fetching manifest directly " f"for {content_type}/{content_id}" @@ -351,11 +375,15 @@ def setup_stream_routes(app, manager, service): ) } - # Use the service's _fetch_manifest_for_rewriter or a similar helper manifest_text, _, _, _ = service.fetch_manifest_for_rewriter( provider, content_id, manifest_url ) + # Inject the upstream manifest URL as a BaseURL so the player can + # resolve relative segment URLs correctly. Without this, segments + # resolve against the local server URL and all requests fail. + manifest_text = _inject_base_url(manifest_text, manifest_url) + response.content_type = "application/dash+xml; charset=utf-8" return manifest_text