60 lines
2.0 KiB
Python
60 lines
2.0 KiB
Python
import os
|
|
import io
|
|
import uvicorn
|
|
|
|
from pathlib import Path
|
|
from fastapi import FastAPI, Header
|
|
from fastapi.responses import StreamingResponse
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.staticfiles import StaticFiles
|
|
from config import ServerConfig
|
|
|
|
|
|
app = FastAPI()
|
|
app.mount('/home', StaticFiles(directory="static", html=True), name="static")
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"]
|
|
)
|
|
|
|
|
|
@app.get("/fetch/{id}")
|
|
async def fetch_file(id: str, range: str = Header(None)) -> StreamingResponse:
|
|
video_path: Path = Path(os.path.join(ServerConfig.video_play_path, id + '.mp4'))
|
|
video_size: int = video_path.stat().st_size
|
|
start = 0
|
|
end = video_size - 1
|
|
chunk_size = min(video_size, ServerConfig.video_chunk_size)
|
|
headers = {
|
|
'Content-Type': 'video/mp4',
|
|
'Content-Disposition': f'attachment; filename="{id}.mp4"',
|
|
}
|
|
if range:
|
|
start, end = range.replace('bytes=', '').split('-')
|
|
start = int(start)
|
|
end = int(end) if end else video_size - 1
|
|
chunk_size: int = min(end - start + 1, ServerConfig.video_chunk_size)
|
|
headers['Content-Range'] = f'bytes {start}-{end}/{video_size}'
|
|
headers['Accept-Ranges'] = 'bytes'
|
|
headers['Content-Disposition'] = 'inline'
|
|
def file_reader():
|
|
with open(video_path, 'rb') as video:
|
|
video.seek(start)
|
|
while True:
|
|
data = video.read(chunk_size)
|
|
if not data:
|
|
break
|
|
yield data
|
|
return StreamingResponse(file_reader(), status_code=206, headers=headers, media_type='video/mp4')
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
uvicorn.run(app=app)
|
|
|