from fastapi import FastAPI, Request, HTTPException, Query
from fastapi.responses import StreamingResponse
import os
import aiofiles
app = FastAPI()
@app.get("/video")
async def stream_video(request: Request, name: str = Query(..., description="Name of the video file")):
file_path = f"videos/{name}"
if not os.path.isfile(file_path):
raise HTTPException(status_code=404, detail="Video not found")
file_size = os.path.getsize(file_path)
range_header = request.headers.get('Range')
start, end = parse_range_header(range_header, file_size)
async def iterfile(file_path, start: int, end: int):
async with aiofiles.open(file_path, mode='rb') as file:
await file.seek(start)
yield await file.read(end - start + 1)
headers = {
'Content-Range': f'bytes {start}-{end}/{file_size}',
'Accept-Ranges': 'bytes',
'Content-Length': str(end - start + 1),
'Content-Type': 'video/mp4',
}
return StreamingResponse(iterfile(file_path, start, end), headers=headers, status_code=206)
def parse_range_header(range_header: str, file_size: int):
if range_header is None:
return 0, file_size - 1
ranges = range_header.strip().split("=")[-1]
start, end = ranges.split("-")
start = int(start) if start else 0
end = int(end) if end else file_size - 1
if start >= file_size or end >= file_size or start > end:
raise HTTPException(status_code=416, detail="Requested Range Not Satisfiable")
return start, end
if name == "main":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)