camview: a low-latency camera viewer in one container
Point it at an RTSP camera and it shows the feed in the browser over WebRTC. Cameras that do not speak H.264 get transcoded on the fly.
The apps that come with IP cameras are laggy. The delay between what the camera sees and what the app draws is long enough that anything moving is always a step behind. camview closes that gap. Open it in a browser and it connects to the RTSP feed and shows it live, with the lowest latency a browser can manage.
WebRTC first, with a fallback
The feed arrives over WebRTC, which is the lowest-latency path a browser has. If WebRTC cannot be set up, the player falls back to Media Source Extensions over the same port, which is fine for watching a hallway and noticeably worse for anything that moves.
Inside the container, go2rtc pulls the RTSP stream and serves it either way. nginx sits in front so the page and the signaling socket share one port:
browser ──HTTP/WS :8080──▶ nginx ──▶ go2rtc :1984 (signaling)
▲ │
└──────────── WebRTC media :8555 ◀──────────────┘ ◀── RTSP from cameraAny camera, any browser
Plenty of cameras emit H.265 or something else browsers refuse to play. camview transcodes those to H.264 on the fly with ffmpeg, so any camera plays in any browser. Set HWACCEL to vaapi, cuda, or qsv and pass the GPU through to keep the transcode off the CPU. If your camera already has an H.264 sub-stream, turn the transcode off and use that.
The one setting people miss
A bridge-networked container cannot discover an address the browser can reach, so real WebRTC needs you to tell it: set WEBRTC_CANDIDATE to the server's LAN address and port. Leave it unset and everything still works, silently over the higher-latency fallback. If the feed looks a second behind, this is the first thing to check.
services:
camview:
image: ghcr.io/chriscorbell/camview:latest
ports:
- "3147:8080"
- "8555:8555/tcp"
- "8555:8555/udp"
environment:
CAMERA_RTSP_URL: ${CAMERA_RTSP_URL}
WEBRTC_CANDIDATE: ${WEBRTC_CANDIDATE:-}There is no authentication, so it stays on the LAN. For a look from outside, I use a VPN. The whole point is a live view of my own cameras from a phone or a laptop, without a vendor app in the middle.
