Spaces:
Running
Running
import re | |
from urllib import parse | |
from mediaflow_proxy.utils.crypto_utils import encryption_handler | |
from mediaflow_proxy.utils.http_utils import encode_mediaflow_proxy_url, get_original_scheme | |
class M3U8Processor: | |
def __init__(self, request, key_url: str = None): | |
""" | |
Initializes the M3U8Processor with the request and URL prefix. | |
Args: | |
request (Request): The incoming HTTP request. | |
key_url (HttpUrl, optional): The URL of the key server. Defaults to None. | |
""" | |
self.request = request | |
self.key_url = parse.urlparse(key_url) if key_url else None | |
self.mediaflow_proxy_url = str(request.url_for("hls_stream_proxy").replace(scheme=get_original_scheme(request))) | |
async def process_m3u8(self, content: str, base_url: str) -> str: | |
""" | |
Processes the m3u8 content, proxying URLs and handling key lines. | |
Args: | |
content (str): The m3u8 content to process. | |
base_url (str): The base URL to resolve relative URLs. | |
Returns: | |
str: The processed m3u8 content. | |
""" | |
lines = content.splitlines() | |
processed_lines = [] | |
for line in lines: | |
if "URI=" in line: | |
processed_lines.append(await self.process_key_line(line, base_url)) | |
elif not line.startswith("#") and line.strip(): | |
processed_lines.append(await self.proxy_url(line, base_url)) | |
else: | |
processed_lines.append(line) | |
return "\n".join(processed_lines) | |
async def process_key_line(self, line: str, base_url: str) -> str: | |
""" | |
Processes a key line in the m3u8 content, proxying the URI. | |
Args: | |
line (str): The key line to process. | |
base_url (str): The base URL to resolve relative URLs. | |
Returns: | |
str: The processed key line. | |
""" | |
uri_match = re.search(r'URI="([^"]+)"', line) | |
if uri_match: | |
original_uri = uri_match.group(1) | |
uri = parse.urlparse(original_uri) | |
if self.key_url: | |
uri = uri._replace(scheme=self.key_url.scheme, netloc=self.key_url.netloc) | |
new_uri = await self.proxy_url(uri.geturl(), base_url) | |
line = line.replace(f'URI="{original_uri}"', f'URI="{new_uri}"') | |
return line | |
async def proxy_url(self, url: str, base_url: str) -> str: | |
""" | |
Proxies a URL, encoding it with the MediaFlow proxy URL. | |
Args: | |
url (str): The URL to proxy. | |
base_url (str): The base URL to resolve relative URLs. | |
Returns: | |
str: The proxied URL. | |
""" | |
full_url = parse.urljoin(base_url, url) | |
query_params = dict(self.request.query_params) | |
has_encrypted = query_params.pop("has_encrypted", False) | |
return encode_mediaflow_proxy_url( | |
self.mediaflow_proxy_url, | |
"", | |
full_url, | |
query_params=dict(self.request.query_params), | |
encryption_handler=encryption_handler if has_encrypted else None, | |
) | |