# How WebRTC Streaming Is Implemented and Accessed on ATOMCam (LAN Only)

> Discover how ATOMCam implements WebRTC streaming on your local network. Access your camera feed via WebSocket signalling using go2rtc for seamless LAN viewing.

- Repository: [Mitsuru Nakada/atomcam_tools](https://github.com/mnakada/atomcam_tools)
- Tags: deep-dive
- Published: 2026-03-07

---

**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_ini` configuration
- **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:

```ini
WEBRTC_ENABLE=on

```

### Startup Script Automation

The startup script [`overlay_rootfs/scripts/rtspserver.sh`](https://github.com/mnakada/atomcam_tools/blob/main/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`](https://github.com/mnakada/atomcam_tools/blob/main//tmp/go2rtc.yaml):

```sh
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:

```sh
/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`](https://github.com/mnakada/atomcam_tools/blob/main/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:

```js
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`](https://github.com/mnakada/atomcam_tools/blob/main/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`](https://github.com/mnakada/atomcam_tools/blob/main/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:

```javascript
const pc = new RTCPeerConnection({
  iceServers: [{urls: 'stun:stun.l.google.com:19302'}]
});

```

The client opens a WebSocket connection to the go2rtc API endpoint:

```javascript
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:

1. **Offer creation** – The client generates an SDP offer and transmits it as `{"type":"webrtc/offer","value":...}`
2. **Answer reception** – go2rtc replies with `{"type":"webrtc/answer","value":...}` which the client sets as the remote description
3. **ICE negotiation** – Both sides exchange candidate messages via `{"type":"webrtc/candidate","value":...}`

Received tracks attach to the video element:

```javascript
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:

1. Enable **WebRTC** in the ATOMCam settings UI (requires RTSP_VIDEO0 to be enabled)
2. Note the generated URL displayed in the settings panel (format: `http://192.168.x.x/webrtc.html`)
3. Open this URL in a modern browser on any LAN-connected device
4. 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=on` in `hack_ini` and reboot, or toggle via the web settings panel in [`web/source/vue/Setting.vue`](https://github.com/mnakada/atomcam_tools/blob/main/web/source/vue/Setting.vue)
- **Bridge service**: go2rtc runs via [`overlay_rootfs/scripts/rtspserver.sh`](https://github.com/mnakada/atomcam_tools/blob/main/overlay_rootfs/scripts/rtspserver.sh), listening on ports 1984 (API) and 8555 (WebRTC)
- **Signalling**: WebSocket-based protocol at `ws://<camera-ip>:1984/api/ws` handles SDP offers/answers and ICE candidates
- **Client access**: Static page at [`/webrtc.html`](https://github.com/mnakada/atomcam_tools/blob/main//webrtc.html) creates 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`](https://github.com/mnakada/atomcam_tools/blob/main/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.