Files
camera-viewer/backend/routes/go2rtc_proxy.py
root f26acc409a Fix WebSocket proxy ping timeout killing MSE streams
The websockets library defaults to ping_interval=20, ping_timeout=20.
go2rtc doesn't respond to these pings, so the upstream WebSocket was
being killed after ~50 seconds causing all camera streams to freeze.

Disabled ping_interval and ping_timeout on the upstream connection.
2026-02-26 16:01:22 -06:00

71 lines
1.9 KiB
Python

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,
ping_interval=None,
ping_timeout=None,
close_timeout=5,
) 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