improved video streams

This commit is contained in:
Simon
2026-02-08 20:08:23 +00:00
parent 10ebcc87c0
commit 313ba70fec

View File

@@ -126,12 +126,41 @@ def stream_video():
def is_hls(url):
return '.m3u8' in urllib.parse.urlparse(url).path
def is_dash(url):
return urllib.parse.urlparse(url).path.lower().endswith('.mpd')
def guess_content_type(url):
path = urllib.parse.urlparse(url).path.lower()
if path.endswith('.m3u8'):
return 'application/vnd.apple.mpegurl'
if path.endswith('.mpd'):
return 'application/dash+xml'
if path.endswith('.mp4') or path.endswith('.m4v') or path.endswith('.m4s'):
return 'video/mp4'
if path.endswith('.webm'):
return 'video/webm'
if path.endswith('.ts'):
return 'video/mp2t'
if path.endswith('.mov'):
return 'video/quicktime'
if path.endswith('.m4a'):
return 'audio/mp4'
if path.endswith('.mp3'):
return 'audio/mpeg'
if path.endswith('.ogg') or path.endswith('.oga'):
return 'audio/ogg'
return None
def is_direct_media(url):
path = urllib.parse.urlparse(url).path.lower()
return any(path.endswith(ext) for ext in ('.mp4', '.m4v', '.m4s', '.ts', '.webm', '.mov'))
def proxy_response(target_url, content_type_override=None):
# Extract the base domain to spoof the referer
referer_override = request.args.get('referer')
if referer_override:
referer = referer_override
else:
parsed_uri = urllib.parse.urlparse(target_url)
referer = f"{parsed_uri.scheme}://{parsed_uri.netloc}/"
@@ -153,16 +182,23 @@ def stream_video():
}
forwarded_headers = []
response_content_type = None
for name, value in resp.headers.items():
if name.lower() in hop_by_hop:
continue
if name.lower() == 'content-length':
forwarded_headers.append((name, value))
continue
if name.lower() == 'content-type':
response_content_type = value
if name.lower() == 'content-type' and content_type_override:
continue
forwarded_headers.append((name, value))
if not content_type_override:
if not response_content_type or 'application/octet-stream' in response_content_type:
content_type_override = guess_content_type(target_url)
if content_type_override:
forwarded_headers.append(('Content-Type', content_type_override))
@@ -180,7 +216,7 @@ def stream_video():
return Response(generate(), status=resp.status_code, headers=forwarded_headers)
def proxy_hls_playlist(playlist_url):
def proxy_hls_playlist(playlist_url, referer_hint=None):
headers = {
'User-Agent': request.headers.get('User-Agent', 'Mozilla/5.0'),
'Accept': request.headers.get('Accept', '*/*')
@@ -188,16 +224,30 @@ def stream_video():
resp = session.get(playlist_url, headers=headers, timeout=30)
resp.raise_for_status()
base_url = resp.url
if referer_hint:
referer = referer_hint
else:
referer = f"{urllib.parse.urlparse(base_url).scheme}://{urllib.parse.urlparse(base_url).netloc}/"
def proxied_url(target):
absolute = urljoin(base_url, target)
return f"/api/stream?url={urllib.parse.quote(absolute, safe='')}&referer={urllib.parse.quote(referer, safe='')}"
lines = resp.text.splitlines()
rewritten = []
for line in lines:
stripped = line.strip()
if not stripped or stripped.startswith('#'):
# Rewrite URI attributes inside tags (keys/maps)
if 'URI="' in line:
def repl(match):
uri = match.group(1)
return f'URI="{proxied_url(uri)}"'
import re
line = re.sub(r'URI="([^"]+)"', repl, line)
rewritten.append(line)
continue
absolute = urljoin(base_url, stripped)
proxied = f"/api/stream?url={urllib.parse.quote(absolute, safe='')}"
rewritten.append(proxied)
rewritten.append(proxied_url(stripped))
if request.method == 'HEAD':
return Response("", status=200, content_type='application/vnd.apple.mpegurl')
@@ -206,7 +256,11 @@ def stream_video():
if is_hls(video_url):
try:
return proxy_hls_playlist(video_url)
referer_hint = request.args.get('referer')
if not referer_hint:
parsed = urllib.parse.urlparse(video_url)
referer_hint = f"{parsed.scheme}://{parsed.netloc}/"
return proxy_hls_playlist(video_url, referer_hint)
except Exception as e:
return jsonify({"error": str(e)}), 500
@@ -219,7 +273,8 @@ def stream_video():
try:
# Configure yt-dlp options
ydl_opts = {
'format': 'best[ext=mp4]/best[vcodec^=avc1]/best[vcodec^=vp]/best',
# 'format': 'best[protocol*=m3u8]/best[ext=mp4]/best',
'format_sort': ['res', 'fps', 'vcodec:avc1', 'acodec:aac'],
'quiet': True,
'no_warnings': True,
'socket_timeout': 30,
@@ -237,6 +292,7 @@ def stream_video():
# Try to get the URL from the info dict (works for progressive downloads)
stream_url = info.get('url')
protocol = info.get('protocol')
# If no direct URL, try to get it from formats
if not stream_url and 'formats' in info:
@@ -249,8 +305,21 @@ def stream_video():
if not stream_url:
return jsonify({"error": "Could not extract stream URL"}), 500
referer_hint = None
if isinstance(info.get('http_headers'), dict):
referer_hint = info['http_headers'].get('Referer') or info['http_headers'].get('referer')
if not referer_hint:
parsed = urllib.parse.urlparse(video_url)
referer_hint = f"{parsed.scheme}://{parsed.netloc}/"
if protocol and 'm3u8' in protocol:
return proxy_hls_playlist(stream_url, referer_hint)
if is_hls(stream_url):
return proxy_hls_playlist(stream_url)
return proxy_hls_playlist(stream_url, referer_hint)
if is_dash(stream_url):
return proxy_response(stream_url, content_type_override='application/dash+xml')
return proxy_response(stream_url)
except Exception as e: