mhdzumair's picture
Fix non-stop Media playback on invalid range headers, bump version & dependencies, update doc
b053b86
raw
history blame
4.66 kB
from typing import Annotated
from fastapi import Request, Depends, APIRouter, Query, HTTPException
from .handlers import handle_hls_stream_proxy, proxy_stream, get_manifest, get_playlist, get_segment, get_public_ip
from .schemas import MPDSegmentParams, MPDPlaylistParams, HLSManifestParams, ProxyStreamParams, MPDManifestParams
from .utils.http_utils import get_proxy_headers, ProxyRequestHeaders
proxy_router = APIRouter()
@proxy_router.head("/hls/manifest.m3u8")
@proxy_router.get("/hls/manifest.m3u8")
async def hls_stream_proxy(
request: Request,
hls_params: Annotated[HLSManifestParams, Query()],
proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)],
):
"""
Proxify HLS stream requests, fetching and processing the m3u8 playlist or streaming the content.
Args:
request (Request): The incoming HTTP request.
hls_params (HLSPlaylistParams): The parameters for the HLS stream request.
proxy_headers (ProxyRequestHeaders): The headers to include in the request.
Returns:
Response: The HTTP response with the processed m3u8 playlist or streamed content.
"""
return await handle_hls_stream_proxy(request, hls_params, proxy_headers)
@proxy_router.head("/stream")
@proxy_router.get("/stream")
async def proxy_stream_endpoint(
request: Request,
stream_params: Annotated[ProxyStreamParams, Query()],
proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)],
):
"""
Proxies stream requests to the given video URL.
Args:
request (Request): The incoming HTTP request.
stream_params (ProxyStreamParams): The parameters for the stream request.
proxy_headers (ProxyRequestHeaders): The headers to include in the request.
Returns:
Response: The HTTP response with the streamed content.
"""
content_range = proxy_headers.request.get("range", "bytes=0-")
if "nan" in content_range.casefold():
# Handle invalid range requests "bytes=NaN-NaN"
raise HTTPException(status_code=416, detail="Invalid Range Header")
proxy_headers.request.update({"range": content_range})
return await proxy_stream(request.method, stream_params, proxy_headers)
@proxy_router.get("/mpd/manifest.m3u8")
async def manifest_endpoint(
request: Request,
manifest_params: Annotated[MPDManifestParams, Query()],
proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)],
):
"""
Retrieves and processes the MPD manifest, converting it to an HLS manifest.
Args:
request (Request): The incoming HTTP request.
manifest_params (MPDManifestParams): The parameters for the manifest request.
proxy_headers (ProxyRequestHeaders): The headers to include in the request.
Returns:
Response: The HTTP response with the HLS manifest.
"""
return await get_manifest(request, manifest_params, proxy_headers)
@proxy_router.get("/mpd/playlist.m3u8")
async def playlist_endpoint(
request: Request,
playlist_params: Annotated[MPDPlaylistParams, Query()],
proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)],
):
"""
Retrieves and processes the MPD manifest, converting it to an HLS playlist for a specific profile.
Args:
request (Request): The incoming HTTP request.
playlist_params (MPDPlaylistParams): The parameters for the playlist request.
proxy_headers (ProxyRequestHeaders): The headers to include in the request.
Returns:
Response: The HTTP response with the HLS playlist.
"""
return await get_playlist(request, playlist_params, proxy_headers)
@proxy_router.get("/mpd/segment")
async def segment_endpoint(
segment_params: Annotated[MPDSegmentParams, Query()],
proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)],
):
"""
Retrieves and processes a media segment, decrypting it if necessary.
Args:
segment_params (MPDSegmentParams): The parameters for the segment request.
proxy_headers (ProxyRequestHeaders): The headers to include in the request.
Returns:
Response: The HTTP response with the processed segment.
"""
return await get_segment(segment_params, proxy_headers)
@proxy_router.get("/ip")
async def get_mediaflow_proxy_public_ip(
use_request_proxy: bool = True,
):
"""
Retrieves the public IP address of the MediaFlow proxy server.
Returns:
Response: The HTTP response with the public IP address in the form of a JSON object. {"ip": "xxx.xxx.xxx.xxx"}
"""
return await get_public_ip(use_request_proxy)