- 移除所有emoji (HomePage中的🎬改为VideoCameraOutlined图标)
- 主题重设计: 深蓝色系主色(#1E3A5F),系统sans-serif字体
白色/浅灰背景,现代卡片阴影和圆角,完全去除复古感
- 首页移除管理入口,纯观众视角(渐变横幅+卡片列表)
- 统一品牌名称 StreamCore (替换LiveStream)
- 全部界面英文(antd默认locale,去除zhCN)
- 登录页渐变+卡片居中布局
67 lines
1.9 KiB
Python
67 lines
1.9 KiB
Python
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="StreamCore", 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)
|