# Strix
[](https://github.com/eduard256/strix/stargazers)
[](https://hub.docker.com/r/eduard256/strix)
[](https://github.com/eduard256/Strix/blob/main/LICENSE)
Finds working camera streams. Generates Frigate config. 30 seconds.
3,600+ brands. 100,000+ URL patterns. RTSP, HTTP, RTMP, Bubble, DVRIP.
## Install
Any Linux, one command:
```bash
curl -fsSL https://raw.githubusercontent.com/eduard256/Strix/main/install.sh | sudo bash
```
Open `http://YOUR_IP:4567`
## How it works
Enter camera IP. Strix probes the device -- open ports, MAC vendor, mDNS, HTTP server.

Search camera model in database. Enter credentials if needed.

Strix builds all possible stream URLs from database patterns.

20 parallel workers test every URL. Live screenshots, codecs, resolution, latency.

Pick main and sub streams from results.

Generate ready Frigate config. Copy, download, or save directly to Frigate.

Camera works in Frigate. Done.

## Other install methods
### Docker
```bash
docker run -d --name strix --network host --restart unless-stopped eduard256/strix:latest
```
### Home Assistant Add-on
1. **Settings** > **Add-ons** > **Add-on Store**
2. Menu (top right) > **Repositories** > add `https://github.com/eduard256/hassio-strix`
3. Install **Strix**, enable **Start on boot** and **Show in sidebar**
### Binary
Download from [GitHub Releases](https://github.com/eduard256/Strix/releases). No dependencies except `ffmpeg` for screenshot conversion.
```bash
chmod +x strix-linux-amd64
STRIX_LISTEN=:4567 ./strix-linux-amd64
```
## Supported protocols
| Protocol | Port | Description |
|----------|------|-------------|
| RTSP | 554 | Most IP cameras |
| RTSPS | 322 | RTSP over TLS |
| HTTP/HTTPS | 80/443 | MJPEG, JPEG snapshots, HLS, MPEG-TS |
| RTMP | 1935 | Some Chinese NVRs |
| Bubble | 80 | XMeye/NetSurveillance cameras |
| DVRIP | 34567 | Sofia protocol DVR/NVR |
## Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `STRIX_LISTEN` | `:4567` | HTTP listen address |
| `STRIX_DB_PATH` | `cameras.db` | Path to SQLite camera database |
| `STRIX_LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error`, `trace` |
| `STRIX_FRIGATE_URL` | auto-discovery | Frigate URL, e.g. `http://localhost:5000` |
| `STRIX_GO2RTC_URL` | auto-discovery | go2rtc URL, e.g. `http://localhost:1984` |
## Camera database
SQLite database with 3,600+ brands and 100,000+ URL patterns. Maintained separately in [StrixCamDB](https://github.com/eduard256/StrixCamDB). Database is embedded in Docker image and bundled with binary releases.
Three entity types:
- **Presets** -- curated sets of popular URL patterns (e.g. "ONVIF", "Popular RTSP")
- **Brands** -- all URL patterns for a brand (e.g. "Hikvision", "Dahua")
- **Models** -- URL patterns for a specific model within a brand
## API Reference
All endpoints return JSON. CORS enabled. Base path: `/`.
### System
#### `GET /api`
```json
{"version": "2.0.0", "platform": "amd64"}
```
#### `GET /api/health`
```json
{"version": "2.0.0", "uptime": "1h30m0s"}
```
#### `GET /api/log`
Returns in-memory log in `application/jsonlines` format.
#### `DELETE /api/log`
Clears in-memory log. Returns `204`.
### Search
#### `GET /api/search?q={query}`
Search camera database. Empty `q` returns all presets + first brands.
```bash
curl "localhost:4567/api/search?q=hikvision"
```
```json
{
"results": [
{"type": "brand", "id": "b:hikvision", "name": "Hikvision"},
{"type": "model", "id": "m:hikvision:DS-2CD2032", "name": "Hikvision: DS-2CD2032"}
]
}
```
Types: `preset`, `brand`, `model`. ID prefixes: `p:`, `b:`, `m:brandId:model`.
#### `GET /api/streams?ids={ids}&ip={ip}&user={user}&pass={pass}&channel={n}&ports={ports}`
Build stream URLs from database patterns.
| Param | Required | Description |
|-------|----------|-------------|
| `ids` | yes | Comma-separated IDs from search results |
| `ip` | yes | Camera IP address |
| `user` | no | Username |
| `pass` | no | Password |
| `channel` | no | Channel number (default 0) |
| `ports` | no | Comma-separated port filter |
```bash
curl "localhost:4567/api/streams?ids=b:hikvision&ip=192.168.1.100&user=admin&pass=12345"
```
```json
{
"streams": [
"rtsp://admin:12345@192.168.1.100/Streaming/Channels/101",
"rtsp://admin:12345@192.168.1.100/Streaming/Channels/102",
"http://admin:12345@192.168.1.100/ISAPI/Streaming/channels/101/picture"
]
}
```
### Testing
#### `POST /api/test`
Create a test session. Launches 20 parallel workers.
```bash
curl -X POST localhost:4567/api/test -d '{
"sources": {
"streams": [
"rtsp://admin:12345@192.168.1.100/Streaming/Channels/101",
"rtsp://admin:12345@192.168.1.100/Streaming/Channels/102"
]
}
}'
```
```json
{"session_id": "a1b2c3d4e5f6g7h8"}
```
#### `GET /api/test`
List all sessions.
```json
{
"sessions": [
{"session_id": "a1b2c3d4", "status": "running", "total": 604, "tested": 341, "alive": 191, "with_screenshot": 191}
]
}
```
#### `GET /api/test?id={session_id}`
Get session details with results.
```json
{
"session_id": "a1b2c3d4",
"status": "done",
"total": 604,
"tested": 604,
"alive": 375,
"with_screenshot": 375,
"results": [
{
"source": "rtsp://admin:***@192.168.1.100/Streaming/Channels/101",
"codecs": ["H264", "PCMA"],
"width": 1920,
"height": 1080,
"latency_ms": 45,
"screenshot": "api/test/screenshot?id=a1b2c3d4&i=0"
}
]
}
```
Status: `running` or `done`.
#### `DELETE /api/test?id={session_id}`
Cancel and delete session.
#### `GET /api/test/screenshot?id={session_id}&i={index}`
Returns JPEG image. `Content-Type: image/jpeg`.
### Config Generation
#### `POST /api/generate`
Generate Frigate config.
```bash
curl -X POST localhost:4567/api/generate -d '{
"mainStream": "rtsp://admin:12345@192.168.1.100/Streaming/Channels/101",
"subStream": "rtsp://admin:12345@192.168.1.100/Streaming/Channels/102",
"name": "front_door",
"objects": ["person", "car"]
}'
```
```json
{
"config": "mqtt:\n enabled: false\n\nrecord:\n ...",
"added": [1, 2, 3, 4]
}
```
`added` -- 1-based line numbers of new lines. Useful for highlighting in UI.
To merge into existing config, pass `existingConfig`:
```json
{
"mainStream": "rtsp://...",
"existingConfig": "go2rtc:\n streams:\n ...\ncameras:\n ..."
}
```
Strix finds the right insertion points, deduplicates camera and stream names.
Full request schema
| Field | Type | Description |
|-------|------|-------------|
| `mainStream` | string | **Required.** Main stream URL |
| `subStream` | string | Sub stream URL |
| `name` | string | Camera name |
| `existingConfig` | string | Existing Frigate YAML to merge into |
| `objects` | string[] | Objects to track (default: `["person"]`) |
| `go2rtc` | object | Override stream names/sources |
| `frigate` | object | Override Frigate input paths/args |
| `detect` | object | `{enabled, fps, width, height}` |
| `record` | object | `{enabled, retain_days, mode, alerts_days, detections_days, pre_capture, post_capture}` |
| `motion` | object | `{enabled, threshold, contour_area}` |
| `snapshots` | object | `{enabled}` |
| `audio` | object | `{enabled, filters[]}` |
| `ffmpeg` | object | `{hwaccel, gpu}` |
| `live` | object | `{height, quality}` |
| `birdseye` | object | `{enabled, mode}` |
| `onvif` | object | `{host, port, user, password, autotracking, required_zones[]}` |
| `ptz` | object | `{enabled, presets{}}` |
| `notifications` | object | `{enabled}` |
| `ui` | object | `{order, dashboard}` |
### Probe
#### `GET /api/probe?ip={ip}`
Probe a network device. Runs all checks in parallel within 100ms.
```bash
curl "localhost:4567/api/probe?ip=192.168.1.100"
```
```json
{
"ip": "192.168.1.100",
"reachable": true,
"latency_ms": 2.5,
"type": "standard",
"probes": {
"ping": {"latency_ms": 2.5},
"ports": {"open": [80, 554, 8080]},
"dns": {"hostname": "ipcam.local"},
"arp": {"mac": "C0:56:E3:AA:BB:CC", "vendor": "Hikvision"},
"mdns": null,
"http": {"port": 80, "status_code": 401, "server": "Hikvision-Webs"}
}
}
```
Type: `standard`, `homekit`, or `unreachable`.
HomeKit cameras return `mdns` with `name`, `model`, `category`, `device_id`, `paired`, `port`.
### Frigate
#### `GET /api/frigate/config`
Get Frigate config. Frigate is discovered automatically via known candidates or `STRIX_FRIGATE_URL`.
```json
{"connected": true, "url": "http://localhost:5000", "config": "mqtt:\n ..."}
```
```json
{"connected": false, "config": ""}
```
#### `POST /api/frigate/config/save?save_option={option}`
Save config to Frigate. Body: plain text (YAML). Options: `saveonly`, `restart`.
### go2rtc
#### `PUT /api/go2rtc/streams?name={name}&src={source}`
Add stream to go2rtc. Proxied to local go2rtc instance.
```bash
curl -X PUT "localhost:4567/api/go2rtc/streams?name=front_door&src=rtsp://admin:12345@192.168.1.100/Streaming/Channels/101"
```
```json
{"success": true}
```