Add go2rtc proxy to fix CORS-blocked WebRTC/MSE streams
This commit is contained in:
@@ -10,6 +10,7 @@ from config import load_config
|
||||
from mqtt_bridge import start_mqtt
|
||||
from routes.config_routes import router as config_router
|
||||
from routes.ws_routes import router as ws_router
|
||||
from routes.go2rtc_proxy import router as go2rtc_router
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -29,6 +30,7 @@ app = FastAPI(title="Camera Viewer", lifespan=lifespan)
|
||||
|
||||
app.include_router(config_router)
|
||||
app.include_router(ws_router)
|
||||
app.include_router(go2rtc_router)
|
||||
|
||||
# Serve frontend static files
|
||||
if FRONTEND_DIR.exists():
|
||||
|
||||
@@ -4,3 +4,4 @@ aiomqtt==2.3.0
|
||||
pyyaml==6.0.2
|
||||
pydantic==2.9.2
|
||||
websockets==13.1
|
||||
httpx==0.28.1
|
||||
|
||||
65
backend/routes/go2rtc_proxy.py
Normal file
65
backend/routes/go2rtc_proxy.py
Normal file
@@ -0,0 +1,65 @@
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import httpx
|
||||
import websockets
|
||||
from fastapi import APIRouter, Request, WebSocket, WebSocketDisconnect, Response
|
||||
|
||||
from config import get_config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/api/go2rtc")
|
||||
|
||||
|
||||
@router.post("/webrtc")
|
||||
async def proxy_webrtc(request: Request, src: str):
|
||||
"""Proxy WebRTC SDP exchange to go2rtc."""
|
||||
config = get_config()
|
||||
target = f"{config.go2rtc.url}/api/webrtc?src={src}"
|
||||
body = await request.body()
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
resp = await client.post(
|
||||
target,
|
||||
content=body,
|
||||
headers={"Content-Type": "application/sdp"},
|
||||
timeout=10.0,
|
||||
)
|
||||
|
||||
return Response(
|
||||
content=resp.content,
|
||||
status_code=resp.status_code,
|
||||
media_type="application/sdp",
|
||||
)
|
||||
|
||||
|
||||
@router.websocket("/ws")
|
||||
async def proxy_mse_ws(ws: WebSocket, src: str):
|
||||
"""Proxy MSE WebSocket to go2rtc."""
|
||||
config = get_config()
|
||||
go2rtc_ws_url = config.go2rtc.url.replace("http", "ws")
|
||||
target = f"{go2rtc_ws_url}/api/ws?src={src}"
|
||||
|
||||
await ws.accept()
|
||||
|
||||
try:
|
||||
async with websockets.connect(target) as upstream:
|
||||
|
||||
async def forward_to_client():
|
||||
async for msg in upstream:
|
||||
if isinstance(msg, bytes):
|
||||
await ws.send_bytes(msg)
|
||||
else:
|
||||
await ws.send_text(msg)
|
||||
|
||||
async def forward_to_upstream():
|
||||
while True:
|
||||
data = await ws.receive_text()
|
||||
await upstream.send(data)
|
||||
|
||||
await asyncio.gather(
|
||||
forward_to_client(),
|
||||
forward_to_upstream(),
|
||||
)
|
||||
except (WebSocketDisconnect, websockets.ConnectionClosed, Exception):
|
||||
pass
|
||||
Reference in New Issue
Block a user