camview: a low-latency camera viewer in one container
Point it at an RTSP camera and it shows the live feed in your browser over WebRTC. If the camera doesn't send H.264, it transcodes on the fly.
published
length2 min read
The apps that come with IP cameras are laggy. There's enough delay between what the camera sees and what shows up on screen that anything moving is always a step behind. I built camview to fix that. You open it in a browser, it connects to the camera's RTSP feed, and it shows it live with about as little latency as a browser can manage.
WebRTC, with a fallback
The video comes in over WebRTC, which is the fastest option a browser has. If WebRTC can't connect, the player falls back to Media Source Extensions over the same port. That's fine for keeping an eye on a hallway, but you'll notice the delay on anything that moves.
Inside the container, go2rtc pulls the RTSP stream and can serve it either way. nginx sits in front so the page and the signaling socket can share one port:
browser ──HTTP/WS :8080──▶ nginx ──▶ go2rtc :1984 (signaling)
▲ │
└──────────── WebRTC media :8555 ◀──────────────┘ ◀── RTSP from cameraWorks with any camera
A lot of cameras send H.265 or some other format browsers won't play. camview transcodes those to H.264 on the fly with ffmpeg, so any camera works in any browser. If you set HWACCEL to vaapi, cuda, or qsv and pass your GPU through, the transcoding runs on the GPU instead of the CPU. And if your camera already has an H.264 sub-stream, you can turn transcoding off and just use that.
The setting that's easy to miss
When the container is on a bridge network, it can't figure out an address the browser can actually reach, so you have to tell it. Set WEBRTC_CANDIDATE to the server's LAN address and port. If you leave it blank, everything still works, but it quietly drops to the slower fallback. So if the feed seems about a second behind, check this first.
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's no authentication, so keep it on your LAN. When I want to check my cameras while I'm away, I use a VPN. All I really wanted was a live view of my own cameras on my phone or laptop, without going through some vendor's app.
