diff options
| author | Astounds <kirito@disroot.org> | 2026-03-27 20:47:44 -0500 |
|---|---|---|
| committer | Astounds <kirito@disroot.org> | 2026-03-27 20:47:44 -0500 |
| commit | 22c72aa842efa6d1dca3bb95eeb47122537ce12a (patch) | |
| tree | a94cf15bd0d7748db0532f56ddefde1fda74a33d /youtube/ytdlp_proxy.py | |
| parent | 56ecd6cb1b461bd3622c669936050fa7e4d83542 (diff) | |
| download | yt-local-22c72aa842efa6d1dca3bb95eeb47122537ce12a.tar.lz yt-local-22c72aa842efa6d1dca3bb95eeb47122537ce12a.tar.xz yt-local-22c72aa842efa6d1dca3bb95eeb47122537ce12a.zip | |
remove yt-dlp, fix captions PO Token issue, fix 429 retry logic
- Remove yt-dlp entirely (modules, routes, settings, dependency)
Was blocking page loads by running synchronously in gevent
- Fix captions: use Android client caption URLs (no PO Token needed)
instead of web timedtext URLs that YouTube now blocks
- Fix 429 retry: fail immediately without Tor (same IP = pointless retry)
Was causing ~27s delays with exponential backoff
- Accept ytdlp_enabled as legacy setting to avoid warning on startup
Diffstat (limited to 'youtube/ytdlp_proxy.py')
| -rw-r--r-- | youtube/ytdlp_proxy.py | 99 |
1 files changed, 0 insertions, 99 deletions
diff --git a/youtube/ytdlp_proxy.py b/youtube/ytdlp_proxy.py deleted file mode 100644 index 023e278..0000000 --- a/youtube/ytdlp_proxy.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python3 -""" -Proxy for serving videos with specific audio using yt-dlp. - -This module provides streaming functionality for unified formats -with specific audio languages. -""" -import logging -from flask import Response, request, stream_with_context -import urllib.request -import urllib.error -from youtube.ytdlp_service import find_best_unified_format - -logger = logging.getLogger(__name__) - - -def stream_video_with_audio(video_id: str, audio_language: str = 'en', max_quality: int = 720): - """ - Stream video with specific audio language. - - Args: - video_id: YouTube video ID - audio_language: Preferred audio language (default: 'en') - max_quality: Maximum video height (default: 720) - - Returns: - Flask Response with video stream, or 404 if not available - """ - logger.info(f'Stream request: {video_id} | audio={audio_language} | quality={max_quality}p') - - # Find best unified format - best_format = find_best_unified_format(video_id, audio_language, max_quality) - - if not best_format: - logger.info(f'No suitable unified format found, returning 404 to trigger fallback') - return Response('No suitable unified format available', status=404) - - url = best_format.get('url') - if not url: - logger.error('Format found but no URL available') - return Response('Format URL not available', status=500) - - logger.debug(f'Streaming from: {url[:80]}...') - - # Stream the video - try: - req = urllib.request.Request(url) - req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') - req.add_header('Accept', '*/*') - - # Add Range header if client requests it - if 'Range' in request.headers: - req.add_header('Range', request.headers['Range']) - logger.debug(f'Range request: {request.headers["Range"]}') - - resp = urllib.request.urlopen(req, timeout=60) - - def generate(): - """Generator for streaming video chunks.""" - try: - while True: - chunk = resp.read(65536) # 64KB chunks - if not chunk: - break - yield chunk - except Exception as e: - logger.error(f'Stream error: {e}') - raise - - # Build response headers - response_headers = { - 'Content-Type': resp.headers.get('Content-Type', 'video/mp4'), - 'Access-Control-Allow-Origin': '*', - } - - # Copy important headers - for header in ['Content-Length', 'Content-Range', 'Accept-Ranges']: - if header in resp.headers: - response_headers[header] = resp.headers[header] - - status_code = resp.getcode() - logger.info(f'Streaming started: {status_code}') - - return Response( - stream_with_context(generate()), - status=status_code, - headers=response_headers, - direct_passthrough=True - ) - - except urllib.error.HTTPError as e: - logger.error(f'HTTP error streaming: {e.code} {e.reason}') - return Response(f'Error: {e.code} {e.reason}', status=e.code) - except urllib.error.URLError as e: - logger.error(f'URL error streaming: {e.reason}') - return Response(f'Network error: {e.reason}', status=502) - except Exception as e: - logger.error(f'Streaming error: {e}', exc_info=True) - return Response(f'Error: {e}', status=500) |
