Files
yt-dlp-proxy/app.py
T
Mikhail Yevchenko 01a376ae21 Enhance HLS proxy functionality and improve caching mechanism
- Updated AGENTS.md to clarify dlp.py module usage and segment handling.
- Modified README.md to include ALLOW_LOCAL configuration for testing.
- Refactored app.py to streamline HLS proxy logic and improve error handling.
- Enhanced dlp.py to optimize caching and segment retrieval processes.
- Updated player.html to ensure proper JSON formatting for proxy URLs.
- Improved test_integration.py to validate HLS segment proxying and added test for Pornhub HLS extraction.
- Adjusted test_proxy.py to reflect changes in caching functions and data structure.
2026-04-01 12:47:21 +00:00

102 lines
3.1 KiB
Python

import logging
import os
from flask import Flask, render_template, request, Response, abort, jsonify
from werkzeug.exceptions import HTTPException
import dlp
from utils import is_valid_url, get_error_message
app = Flask(__name__)
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
logging.basicConfig(
level=getattr(logging, LOG_LEVEL),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
PORT = int(os.getenv("PORT", 5000))
@app.route("/")
def index():
return render_template("index.html")
@app.route("/player")
def player():
video_url = request.args.get("url")
if not video_url:
abort(400, description="Missing url parameter")
if not is_valid_url(video_url):
abort(400, description="Invalid or disallowed URL")
try:
stream_info = dlp.get_stream_info(video_url)
from urllib.parse import quote
encoded_url = quote(video_url, safe="")
proxy_hls_url = f"/hls?url={encoded_url}&path=index.m3u8"
return render_template(
"player.html",
video_url=video_url,
proxy_hls_url=proxy_hls_url,
title=stream_info.get("title", "Video"),
thumbnail=stream_info.get("thumbnail")
)
except Exception as e:
logger.error(f"Error getting stream info: {e}")
abort(500, description=str(e))
@app.route("/hls")
def hls_proxy():
try:
url_param = request.args.get("url", "")
if not url_param:
abort(400, description="Missing url parameter")
from urllib.parse import unquote
path = request.args.get("path", "")
video_url = unquote(url_param)
if not is_valid_url(video_url):
abort(400, description="Invalid URL")
# Main playlist request - get from yt-dlp and rewrite URLs
if path == "index.m3u8" or path == "":
playlist = dlp.get_hls_playlist(video_url)
return Response(playlist, mimetype="application/vnd.apple.mpegurl")
# Sub-playlist or segment request - path is the absolute URL
segment_data = dlp.get_hls_segment(video_url, path)
if segment_data is None:
abort(500, description="Failed to fetch segment")
if path.endswith(".m3u8"):
return Response(segment_data, mimetype="application/vnd.apple.mpegurl")
return Response(segment_data, mimetype="video/mp2t")
except HTTPException:
raise
except ValueError as e:
logger.warning(f"Validation error: {e}")
abort(400, description=str(e))
except Exception as e:
logger.error(f"HLS proxy error: {e}")
abort(500, description="Error fetching stream")
@app.errorhandler(Exception)
def handle_error(e):
if isinstance(e, HTTPException):
return jsonify({"error": get_error_message(e.code), "message": str(e.description)}), e.code
logger.error(f"Unexpected error: {e}")
return jsonify({"error": "Internal Server Error", "message": str(e)}), 500
if __name__ == "__main__":
app.run(host="0.0.0.0", port=PORT)