@apocaliss92/scrypted-onvif-rebroadcast 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,101 @@
1
1
  # Scrypted ONVIF Rebroadcast
2
2
 
3
- ☕️ If this extension works well for you, consider buying me a coffee. Thanks!
4
- [Buy me a coffee!](https://buymeacoffee.com/apocaliss92)
3
+ Creates virtual ONVIF-compliant camera devices from Scrypted's RTSP rebroadcast streams, enabling third-party NVRs like **UniFi Protect** to adopt cameras that aren't natively supported.
4
+
5
+ ## Features
6
+
7
+ - Wraps Scrypted RTSP rebroadcast streams in ONVIF Profile S endpoints
8
+ - **Unique IP & MAC per camera** via Docker macvlan proxy containers (required for UniFi Protect)
9
+ - Automatic Docker network and proxy container management
10
+ - WS-Discovery for ONVIF auto-detection
11
+ - PTZ, motion events, and object detection forwarded via ONVIF
12
+ - WS-Security and HTTP Basic authentication
13
+ - Persistent IP assignments across restarts
14
+
15
+ ## UniFi Protect Setup
16
+
17
+ UniFi Protect identifies third-party cameras by MAC address. To add multiple cameras, each needs a unique IP and MAC on the network. This plugin handles this automatically using Docker macvlan proxy containers.
18
+
19
+ ### Prerequisites
20
+
21
+ - Scrypted running in Docker with the **Rebroadcast plugin** installed
22
+ - Docker socket mounted in the Scrypted container (`/var/run/docker.sock`)
23
+ - A network interface available for macvlan (e.g. `br0`)
24
+
25
+ ### Docker Socket
26
+
27
+ The plugin needs access to the Docker socket to create proxy containers. Add this path mapping to your Scrypted container:
28
+
29
+ | Container Path | Host Path |
30
+ |---|---|
31
+ | `/var/run/docker.sock` | `/var/run/docker.sock` |
32
+
33
+ ### Plugin Settings
34
+
35
+ | Setting | Description | Example |
36
+ |---|---|---|
37
+ | **Username / Password** | ONVIF authentication credentials | `admin` / `password` |
38
+ | **Auto-assign unique IPs** | Enable automatic proxy container creation | `true` |
39
+ | **IP range start** | First IP to assign to cameras | `192.168.1.240` |
40
+ | **Network interface** | Parent interface for the macvlan Docker network | `br0` |
41
+ | **Subnet prefix length** | CIDR prefix for the macvlan network | `23` |
42
+ | **Gateway** | Default gateway for the macvlan network | `192.168.1.1` |
43
+
44
+ ### IP Range Selection
45
+
46
+ Choose IPs **outside your DHCP pool** on the same subnet as your UniFi controller. For example, if your router assigns `192.168.1.2-200` via DHCP, use `192.168.1.240` as the start.
5
47
 
6
- **Documentation:** [https://advanced-notifier-docs.zentik.app/docs/onvif-rebroadcast](https://advanced-notifier-docs.zentik.app/docs/onvif-rebroadcast)
48
+ ### How It Works
49
+
50
+ ```
51
+ UniFi Protect Docker macvlan proxy Scrypted container
52
+ (192.168.1.x) (192.168.1.240, unique MAC) (192.168.4.40)
53
+ | | |
54
+ |--- ONVIF (port 8000) ---------->|--- TCP proxy (port 18000) --->| ONVIF server
55
+ |--- RTSP (port 554) ---------->|--- TCP proxy (port 42917) -->| RTSP rebroadcast
56
+ ```
57
+
58
+ Each camera gets its own proxy container with:
59
+ - A unique IP address on your LAN
60
+ - A unique MAC address (deterministic, based on device ID)
61
+ - TCP proxies for both ONVIF (port 8000) and RTSP (port 554+) traffic
62
+
63
+ ### Adding Cameras in UniFi Protect
64
+
65
+ 1. Install and configure the plugin in Scrypted
66
+ 2. Enable "Auto-assign unique IPs" and configure the IP range
67
+ 3. The plugin automatically creates proxy containers (visible in Docker)
68
+ 4. In UniFi Protect: **Settings > Cameras > Add Camera > ONVIF**
69
+ 5. Enter each camera's assigned IP with port `8000`
70
+ 6. Enter the ONVIF username/password you configured
71
+
72
+ ### Unraid Notes
73
+
74
+ - If your Scrypted container uses `Custom: br0.2` (ipvlan), create the macvlan network on `br0` instead to get unique MACs
75
+ - The plugin creates a Docker network called `onvif_cameras` for the proxy containers
76
+ - Proxy containers are named `onvif-proxy-{deviceId}` and auto-restart
77
+ - The `alpine/socat` image is pulled automatically on first use
78
+
79
+ ## Architecture
80
+
81
+ The plugin is a Scrypted **MixinProvider** that attaches to Camera and Doorbell devices:
82
+
83
+ 1. **Stream Discovery** - Finds RTSP rebroadcast URLs from the Rebroadcast plugin
84
+ 2. **ONVIF Server** - Creates an HTTP server per camera serving ONVIF SOAP endpoints
85
+ 3. **Proxy Containers** - Spawns Docker containers with macvlan networking for unique IPs/MACs
86
+ 4. **Event Forwarding** - Scrypted motion/detection events are forwarded via ONVIF pull-point subscriptions
87
+
88
+ ## Development
89
+
90
+ ```bash
91
+ npm install
92
+ npm run build
93
+ npx scrypted login <scrypted-ip>
94
+ npm run scrypted-deploy <scrypted-ip>
95
+ ```
96
+
97
+ ---
98
+
99
+ [Buy me a coffee!](https://buymeacoffee.com/apocaliss92)
7
100
 
8
- [For requests and bugs](https://github.com/apocaliss92/scrypted-onvif-rebroadcast)
101
+ [For requests and bugs](https://github.com/apocaliss92/scrypted-onvif-rebroadcast/issues)
package/dist/plugin.zip CHANGED
Binary file
@@ -0,0 +1,187 @@
1
+ # Unique IP / MAC Setup for UniFi Protect
2
+
3
+ UniFi Protect identifies third-party ONVIF cameras by **MAC address**. When multiple virtual cameras share the same host MAC, UniFi sees them as a single device. This guide explains how to configure unique IPs and MACs for each camera so UniFi Protect adopts them as separate devices.
4
+
5
+ ## Prerequisites
6
+
7
+ - Scrypted running in Docker with the **Rebroadcast** plugin installed
8
+ - Docker socket mounted in the Scrypted container (`/var/run/docker.sock`)
9
+ - A network bridge interface available for macvlan (e.g. `br0`)
10
+
11
+ ## How It Works
12
+
13
+ The plugin creates a **Docker macvlan network** and spawns a lightweight **proxy container** (`alpine/socat`) for each camera. Each proxy has:
14
+
15
+ - A **unique IP address** on your LAN
16
+ - A **unique MAC address** (deterministic, based on device ID)
17
+ - TCP proxies for **ONVIF** (port 8000) and **RTSP** (port 554+) traffic
18
+
19
+ ```
20
+ UniFi Protect Docker macvlan proxy Scrypted container
21
+ (your LAN) (unique IP + MAC) (internal IP)
22
+ │ │ │
23
+ │── ONVIF (port 8000) ───────▶│── TCP proxy ─────────────────▶│ ONVIF server
24
+ │── RTSP (port 554) ───────▶│── TCP proxy ─────────────────▶│ RTSP rebroadcast
25
+ ```
26
+
27
+ ## Step 1: Mount Docker Socket
28
+
29
+ The plugin needs access to Docker to create proxy containers. Add this path mapping to your Scrypted container:
30
+
31
+ | Container Path | Host Path |
32
+ |---|---|
33
+ | `/var/run/docker.sock` | `/var/run/docker.sock` |
34
+
35
+ ### Unraid
36
+ Edit the Scrypted container → Add Path → Container: `/var/run/docker.sock`, Host: `/var/run/docker.sock`
37
+
38
+ ### Docker Compose
39
+ ```yaml
40
+ volumes:
41
+ - /var/run/docker.sock:/var/run/docker.sock
42
+ ```
43
+
44
+ ### Docker CLI
45
+ ```bash
46
+ docker run ... -v /var/run/docker.sock:/var/run/docker.sock ...
47
+ ```
48
+
49
+ ## Step 2: Configure Plugin Settings
50
+
51
+ Open the ONVIF Rebroadcast plugin settings in Scrypted and configure the **IP Allocation** section:
52
+
53
+ | Setting | Description | Example |
54
+ |---|---|---|
55
+ | **Auto-assign unique IPs** | Enable automatic proxy container creation | `✓` (checked) |
56
+ | **IP range start** | First IP to assign (must be on the same subnet as your NVR) | `192.168.1.240` |
57
+ | **Network interface** | Parent interface for the macvlan Docker network | `br0` |
58
+ | **Subnet prefix length** | CIDR prefix matching your network | `23` or `24` |
59
+ | **Gateway** | Your network's default gateway | `192.168.1.1` |
60
+
61
+ ### Choosing the Right IP Range
62
+
63
+ - Pick IPs **outside your DHCP pool** to avoid conflicts
64
+ - IPs must be on the **same subnet** as your UniFi controller
65
+ - Example: if your router's DHCP range is `192.168.1.2–200`, use `192.168.1.240` as the start
66
+ - Each camera gets the next sequential IP (`.240`, `.241`, `.242`, etc.)
67
+
68
+ ### Choosing the Network Interface
69
+
70
+ | Platform | Interface | Notes |
71
+ |---|---|---|
72
+ | Unraid (ipvlan on br0.2) | `br0` | Use the main bridge, not the VLAN interface |
73
+ | Docker (bridge network) | `eth0` or `br0` | Check `ip link show` on your host |
74
+ | Synology | `ovs_eth0` or `bond0` | Depends on your network config |
75
+
76
+ > **Important (Unraid):** If your Scrypted container uses `Custom: br0.2` (ipvlan), set the network interface to `br0` — not `br0.2`. ipvlan networks share MAC addresses and won't work with UniFi. The plugin creates a separate macvlan network on `br0` for the proxy containers.
77
+
78
+ ## Step 3: Reload the Plugin
79
+
80
+ After saving the settings, reload the ONVIF Rebroadcast plugin. Check the logs for:
81
+
82
+ ```
83
+ Docker socket found — proxy container mode available
84
+ Created macvlan network on br0 (192.168.0.0/23)
85
+ Proxy container onvif-proxy-133: IP=192.168.1.241 MAC=02:cc:30:40:1c:d7 → 192.168.4.40:18000
86
+ ```
87
+
88
+ Each camera should show its assigned IP and MAC.
89
+
90
+ ## Step 4: Add Cameras in UniFi Protect
91
+
92
+ 1. Open **UniFi Protect**
93
+ 2. Go to the **Devices** list view
94
+ 3. Click the **?** icon (help/question mark) next to the view toggle buttons
95
+ 4. Click **"Can't Find Your Device?"**
96
+ 5. Enter each camera's assigned IP with port **8000** (e.g. `192.168.1.240`)
97
+ 6. Enter the ONVIF username and password (configured in the plugin's Authentication settings)
98
+ 7. The camera will appear in the device list as a third-party camera (shown with the ONVIF icon)
99
+ 8. Click **"Click to Adopt"** to add it
100
+
101
+ Repeat for each camera IP. Each will be recognized as a separate device with its own unique MAC.
102
+
103
+ > **Note:** UniFi will display the camera's actual model number (e.g. "Reolink CX410") as reported by the ONVIF device information.
104
+
105
+ ## Step 5: Verify
106
+
107
+ You can verify the proxy containers are running:
108
+
109
+ ```bash
110
+ docker ps | grep onvif
111
+ ```
112
+
113
+ Test connectivity from any device on your network:
114
+
115
+ ```bash
116
+ curl -s http://192.168.1.240:8000/onvif/device_service -d '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"><s:Body><GetSystemDateAndTime xmlns="http://www.onvif.org/ver10/device/wsdl"/></s:Body></s:Envelope>'
117
+ ```
118
+
119
+ ## Troubleshooting
120
+
121
+ ### "Docker socket not found"
122
+ Mount `/var/run/docker.sock` in the Scrypted container. See Step 1.
123
+
124
+ ### "Failed to create macvlan network: Pool overlaps"
125
+ A Docker network already exists on the same subnet. The plugin will try to find and reuse existing macvlan networks automatically. If it fails, check `docker network ls` and remove stale `onvif_cameras` networks.
126
+
127
+ ### Proxy containers not reachable
128
+ - Ensure the IP range is on the **same subnet** as the device trying to connect
129
+ - Check that the **gateway** is correct
130
+ - Verify the **network interface** exists on the Docker host (`ip link show`)
131
+
132
+ ### UniFi still shows one camera
133
+ - Confirm proxy containers have unique MACs: `docker inspect onvif-proxy-XXX | grep MacAddress`
134
+ - Remove all existing cameras from UniFi Protect before re-adding
135
+ - The macvlan network must be `macvlan` driver (not `ipvlan`) — check with `docker network inspect onvif_cameras | grep Driver`
136
+
137
+ ### Cameras added but no video
138
+ - Check that the Rebroadcast plugin is installed and the camera has RTSP streams configured
139
+ - The RTSP stream URLs are automatically proxied through port 554+ on each camera's IP
140
+ - Verify the RTSP URL works: connect to `rtsp://camera-ip:554/stream-path` with VLC
141
+
142
+ ### IP assignments change after restart
143
+ - IP assignments are persistent — stored in Scrypted's plugin storage
144
+ - Once a camera gets an index, it keeps the same IP forever
145
+ - New cameras get the next available index
146
+
147
+ ## Architecture Details
148
+
149
+ ### Proxy Container Lifecycle
150
+
151
+ - Containers are named `onvif-proxy-{deviceId}`
152
+ - Restart policy: `unless-stopped` (auto-restart on crash)
153
+ - Image: `alpine/socat` (pulled automatically on first use, ~5MB)
154
+ - Each container runs multiple `socat` instances:
155
+ - Port 8000 → Scrypted ONVIF server (internal port)
156
+ - Port 554 → Scrypted RTSP rebroadcast stream 1
157
+ - Port 555 → stream 2, etc.
158
+
159
+ ### MAC Address Generation
160
+
161
+ Each camera gets a deterministic MAC address derived from its Scrypted device ID:
162
+ - Format: `02:xx:xx:xx:xx:xx` (locally administered, unicast)
163
+ - Same device ID always produces the same MAC
164
+ - Survives plugin restarts and container recreation
165
+
166
+ ### Network Topology
167
+
168
+ ```
169
+ ┌─────────────────────────────────────────────────────────┐
170
+ │ Docker Host │
171
+ │ │
172
+ │ ┌──────────────┐ ┌──────────────────────────────┐ │
173
+ │ │ Scrypted │ │ onvif_cameras network │ │
174
+ │ │ Container │ │ (macvlan on br0) │ │
175
+ │ │ │ │ │ │
176
+ │ │ ONVIF:18000 │◄────│ Proxy 1: 192.168.1.240:8000 │ │
177
+ │ │ ONVIF:18001 │◄────│ Proxy 2: 192.168.1.241:8000 │ │
178
+ │ │ RTSP:42917 │◄────│ Proxy 1: 192.168.1.240:554 │ │
179
+ │ │ RTSP:43218 │◄────│ Proxy 2: 192.168.1.241:554 │ │
180
+ │ │ │ │ │ │
181
+ │ │ br0.2 ipvlan│ │ Each proxy has unique MAC │ │
182
+ │ │ 192.168.4.40│ │ │ │
183
+ │ └──────────────┘ └──────────────────────────────┘ │
184
+ │ │
185
+ │ br0 ──── Physical NIC ──── Switch ──── UniFi Protect │
186
+ └─────────────────────────────────────────────────────────┘
187
+ ```
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "https://github.com/apocaliss92/scrypted-onvif-rebroadcast"
7
7
  },
8
- "version": "0.0.4",
8
+ "version": "0.0.5",
9
9
  "scripts": {
10
10
  "scrypted-setup-project": "scrypted-setup-project",
11
11
  "prescrypted-setup-project": "scrypted-package-json",