How WebRTC Streaming Is Implemented and Accessed on ATOMCam (LAN Only)
ATOMCam implements WebRTC streaming by running the go2rtc service as an RTSP-to-WebRTC bridge, exposing the camera feed via WebSocket signalling on port 1984 and serving a browser-based client accessible to any device on the same local network.
The ATOMCam custom firmware (mnakada/atomcam_tools) enables real-time browser-based video streaming without plugins by integrating WebRTC technology. This implementation runs entirely within your local area network, leveraging the go2rtc binary to bridge the device's native RTSP feed to modern web browsers.
Architecture Overview
The WebRTC streaming pipeline consists of four core components:
- Feature flag system – Controls service activation via
hack_iniconfiguration - go2rtc bridge – Converts RTSP streams to WebRTC tracks
- Vue.js settings interface – Generates access URLs and toggles the feature
- Browser client – Handles WebSocket signalling and peer connection management
Enabling WebRTC via Feature Flags
Configuration in hack_ini
WebRTC functionality is controlled through the device's hack_ini file. Setting WEBRTC_ENABLE=on activates the streaming service:
WEBRTC_ENABLE=on
Startup Script Automation
The startup script overlay_rootfs/scripts/rtspserver.sh reads this flag during boot and configures the go2rtc environment. When enabled, it exports the WebRTC listener address and injects it into the temporary configuration file at /tmp/go2rtc.yaml:
WEBRTC_ENABLE=$(awk -F "=" '/^WEBRTC_ENABLE *=/ {print $2}' $HACK_INI)
[ "$WEBRTC_ENABLE" = "on" ] && export WEBRTC_LISTEN=":8555/tcp"
# Configuration template injection
webrtc:
listen: ${WEBRTC_LISTEN:''}
The script then launches the bridge service in the background:
/usr/bin/go2rtc $option >> /tmp/log/go2rtc.log &
The go2rtc Bridge Service
The go2rtc binary acts as the protocol translator between the camera's RTSP output and WebRTC-compatible browsers. According to the source configuration in custompackages/package/go2rtc/go2rtc.mk, this service operates on two key ports:
- Port 1984 – HTTP API and WebSocket signalling endpoint
- Port 8555 – WebRTC listener (TCP)
The service pulls the local video stream from rtsp://localhost/cgi-bin/get_jpeg.cgi and exposes it as WebRTC tracks available through the API.
Web Interface and URL Generation
Settings Panel Implementation
The administrative interface in web/source/vue/Setting.vue provides the control switch and generates the access URL. The SettingSwitch component binds to config.WEBRTC_ENABLE, while the computed property WebRTCUrl constructs the endpoint based on audio codec selection:
WebRTCUrl() {
const opt = this.config.RTSP_AUDIO0 === 'OPUS' ? '?media=video+audio' : '';
return `http://${window.location.host}/webrtc.html${opt}`;
}
When the user enables the feature and the configuration is active, the UI displays a read-only input containing the direct link to webrtc.html, optionally appending ?media=video+audio when the OPUS audio codec is configured.
Client-Side WebRTC Implementation
The browser client web/source/webrtc.html implements the WebRTC signalling protocol. It establishes a RTCPeerConnection configured with Google's public STUN server for NAT traversal within the LAN:
const pc = new RTCPeerConnection({
iceServers: [{urls: 'stun:stun.l.google.com:19302'}]
});
The client opens a WebSocket connection to the go2rtc API endpoint:
const src = new URLSearchParams(location.search).get('src') || 'video0';
const ws = new WebSocket(`ws://${location.host}:1984/api/ws?src=${src}`);
Signalling follows the standard WebRTC exchange pattern:
- Offer creation – The client generates an SDP offer and transmits it as
{"type":"webrtc/offer","value":...} - Answer reception – go2rtc replies with
{"type":"webrtc/answer","value":...}which the client sets as the remote description - ICE negotiation – Both sides exchange candidate messages via
{"type":"webrtc/candidate","value":...}
Received tracks attach to the video element:
const tracks = ['video','audio']
.filter(k => media.includes(k))
.map(k => pc.addTransceiver(k,{direction:'recvonly'}).receiver.track);
document.getElementById('video').srcObject = new MediaStream(tracks);
Accessing the Stream on Your LAN
To view the WebRTC stream from any device on the same network:
- Enable WebRTC in the ATOMCam settings UI (requires RTSP_VIDEO0 to be enabled)
- Note the generated URL displayed in the settings panel (format:
http://192.168.x.x/webrtc.html) - Open this URL in a modern browser on any LAN-connected device
- For audio support, ensure the URL contains
?media=video+audio(automatically added when RTSP_AUDIO0 is set to OPUS)
Because signalling uses the local WebSocket on port 1984 and the implementation relies on public STUN servers only for local NAT traversal, the stream remains accessible strictly within your local network without requiring TURN servers or internet-exposed endpoints.
Summary
- Activation: Set
WEBRTC_ENABLE=oninhack_iniand reboot, or toggle via the web settings panel inweb/source/vue/Setting.vue - Bridge service: go2rtc runs via
overlay_rootfs/scripts/rtspserver.sh, listening on ports 1984 (API) and 8555 (WebRTC) - Signalling: WebSocket-based protocol at
ws://<camera-ip>:1984/api/wshandles SDP offers/answers and ICE candidates - Client access: Static page at
/webrtc.htmlcreates the peer connection and streams video to the browser - Network scope: LAN-only operation using local WebSocket signalling and public STUN for internal NAT traversal
Frequently Asked Questions
Does WebRTC streaming work outside my local network?
No, the ATOMCam WebRTC implementation is designed for LAN access only. While it uses Google's public STUN server (stun:stun.l.google.com:19302) to handle NAT traversal within your local network, it does not include a TURN server or external signalling infrastructure required for internet-based peer connections. Both the browser and camera must reside on the same local network or reachable LAN segment.
What ports does WebRTC streaming use on ATOMCam?
The implementation uses two distinct TCP ports: 1984 for the HTTP API and WebSocket signalling endpoint, and 8555 for the WebRTC listener itself. The browser client connects to port 1984 for signalling via WebSocket, while the actual media stream negotiates through the port 8555 listener configured in the go2rtc startup parameters.
Can I enable audio in the WebRTC stream?
Yes, audio streaming is supported when the RTSP audio codec is configured to use OPUS. In web/source/vue/Setting.vue, the code checks config.RTSP_AUDIO0 === 'OPUS' and automatically appends ?media=video+audio to the generated WebRTC URL. If your audio configuration uses a different codec, the URL defaults to video-only to ensure compatibility.
What is go2rtc and why is it used?
go2rtc is an open-source media gateway that translates between various streaming protocols. In the ATOMCam firmware, it serves as the critical bridge between the camera's native RTSP output (rtsp://localhost/cgi-bin/get_jpeg.cgi) and WebRTC-compatible web browsers. The project bundles go2rtc as a custom package defined in custompackages/package/go2rtc/go2rtc.mk, allowing the camera to serve modern browser-based streaming without requiring browser plugins or additional server infrastructure.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →