115 lines
3.2 KiB
Python
115 lines
3.2 KiB
Python
"""Main FastAPI application for Deltacast SDI Recorder."""
|
|
|
|
import asyncio
|
|
import json
|
|
import logging
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI, HTTPException, WebSocket, WebSocketDisconnect
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import FileResponse
|
|
from pathlib import Path
|
|
|
|
from .config import Settings
|
|
from .recorders.recorder import RecorderManager
|
|
from .recorders.scte35 import SCTE35Manager
|
|
from .utils.hls import HLSPreviewManager
|
|
from .api.routes import router
|
|
from .api import routes as routes_module
|
|
from .api.websocket import ConnectionManager
|
|
|
|
logger = logging.getLogger(__name__)
|
|
settings = Settings()
|
|
|
|
recorder_manager: RecorderManager | None = None
|
|
scte35_manager: SCTE35Manager | None = None
|
|
hls_manager: HLSPreviewManager | None = None
|
|
connection_manager = ConnectionManager()
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
global recorder_manager, scte35_manager, hls_manager
|
|
|
|
logger.info("Starting Deltacast SDI Recorder...")
|
|
|
|
recorder_manager = RecorderManager(settings)
|
|
recorder_manager.initialize()
|
|
|
|
scte35_manager = SCTE35Manager()
|
|
|
|
hls_manager = HLSPreviewManager(settings)
|
|
|
|
# Inject all managers into routes module
|
|
routes_module.recorder_manager = recorder_manager
|
|
routes_module.scte35_manager = scte35_manager
|
|
routes_module.hls_manager = hls_manager
|
|
|
|
status_task = asyncio.create_task(broadcast_port_status())
|
|
|
|
logger.info(f"Deltacast SDI Recorder started — {settings.deltacast_port_count} ports")
|
|
|
|
yield
|
|
|
|
logger.info("Shutting down Deltacast SDI Recorder...")
|
|
status_task.cancel()
|
|
try:
|
|
await status_task
|
|
except asyncio.CancelledError:
|
|
pass
|
|
|
|
for port_index in range(settings.deltacast_port_count):
|
|
await recorder_manager.stop_recording(port_index)
|
|
await hls_manager.stop_preview(port_index)
|
|
|
|
logger.info("Shutdown complete")
|
|
|
|
|
|
async def broadcast_port_status():
|
|
while True:
|
|
try:
|
|
if recorder_manager is not None:
|
|
statuses = recorder_manager.get_all_status()
|
|
data = {
|
|
"type": "port_status",
|
|
"ports": [s.model_dump() for s in statuses]
|
|
}
|
|
await connection_manager.broadcast(data)
|
|
except Exception as e:
|
|
logger.error(f"Error broadcasting port status: {e}")
|
|
await asyncio.sleep(1)
|
|
|
|
|
|
app = FastAPI(
|
|
title="Deltacast SDI Recorder",
|
|
description="Web GUI for Deltacast SDI capture card recording",
|
|
version="1.0.0",
|
|
lifespan=lifespan
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
app.include_router(router)
|
|
|
|
|
|
@app.websocket("/ws")
|
|
async def websocket_endpoint(websocket: WebSocket):
|
|
await connection_manager.connect(websocket)
|
|
try:
|
|
while True:
|
|
data = await websocket.receive_text()
|
|
except WebSocketDisconnect:
|
|
connection_manager.disconnect(websocket)
|
|
|
|
|
|
@app.get("/hls/{filename}")
|
|
async def serve_hls(filename: str):
|
|
hls_path = Path("/tmp/hls") / filename
|
|
if not hls_path.exists():
|
|
raise HTTPException(status_code=404, detail="HLS file not found")
|
|
return FileResponse(str(hls_path))
|