Initial commit: LiveStream Platform
Backend: FastAPI + SQLAlchemy + SQLite Frontend: React + Vite + Ant Design (serif Anthropic theme) Media server: MediaMTX with edge node support Load balancing: round-robin / weighted / least-conn Multicast detection with automatic fallback Transcoding support via FFmpeg (configurable quality) hls.js player with line & quality switching Admin panel with password auth Windows compatible scripts
This commit is contained in:
commit
2e4594fa77
43 files changed
+2196
No files matched your search
@@ -0,0 +1,66 @@
|
||||
import os
|
||||
from contextlib import asynccontextmanager
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import FileResponse
|
||||
from starlette.responses import RedirectResponse
|
||||
from starlette.background import BackgroundTask
|
||||
import httpx
|
||||
from database import init_db
|
||||
from services.transcoder import transcode_mgr
|
||||
from routes import streams_router, nodes_router, auth_router
|
||||
from config import settings
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
await init_db()
|
||||
yield
|
||||
transcode_mgr.stop_all()
|
||||
|
||||
|
||||
app = FastAPI(title="LiveStream Platform", lifespan=lifespan)
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
app.include_router(streams_router)
|
||||
app.include_router(nodes_router)
|
||||
app.include_router(auth_router)
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
async def health():
|
||||
from services.multicast_detector import multicast_detector
|
||||
return {
|
||||
"status": "ok",
|
||||
"multicast_available": multicast_detector.is_available(),
|
||||
}
|
||||
|
||||
|
||||
@app.get("/hls/{path:path}")
|
||||
async def serve_hls(path: str):
|
||||
hls_root = "/tmp/hls"
|
||||
fs_path = os.path.join(hls_root, path)
|
||||
if os.path.isfile(fs_path):
|
||||
return FileResponse(fs_path)
|
||||
|
||||
target = f"http://127.0.0.1:{settings.media_origin_hls_port}/{path}"
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=httpx.Timeout(10)) as client:
|
||||
req = client.build_request("GET", target)
|
||||
resp = await client.send(req, stream=True)
|
||||
from starlette.responses import StreamingResponse
|
||||
return StreamingResponse(
|
||||
resp.aiter_bytes(),
|
||||
status_code=resp.status_code,
|
||||
headers=dict(resp.headers),
|
||||
media_type=resp.headers.get("content-type"),
|
||||
)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=404)
|
||||
Reference in new issue
Block a user