10 KiB
Strix for Developers
Strix is a single static binary with embedded web UI and SQLite camera database. No config files, no external dependencies (except optional ffmpeg for H264/H265 screenshot conversion). Designed to run alongside your project the same way go2rtc does.
Binary
Download from GitHub Releases. Two platforms: linux/amd64 and linux/arm64.
chmod +x strix-linux-amd64
./strix-linux-amd64
The binary needs cameras.db in the working directory. Download it from StrixCamDB:
curl -fsSL https://github.com/eduard256/StrixCamDB/releases/latest/download/cameras.db -o cameras.db
./strix-linux-amd64
Docker
docker run -d --name strix --network host eduard256/strix:latest
Database is already embedded in the image.
Environment Variables
| Variable | Default | Description |
|---|---|---|
STRIX_LISTEN |
:4567 |
HTTP listen address |
STRIX_DB_PATH |
cameras.db |
Path to SQLite database |
STRIX_LOG_LEVEL |
info |
trace, debug, info, warn, error |
STRIX_FRIGATE_URL |
auto-discovery | Frigate URL, e.g. http://localhost:5000 |
STRIX_GO2RTC_URL |
auto-discovery | go2rtc URL, e.g. http://localhost:1984 |
Integration Flow
Typical automation flow using the API:
1. Probe device GET /api/probe?ip=192.168.1.100
2. Search database GET /api/search?q=hikvision
3. Build stream URLs GET /api/streams?ids=b:hikvision&ip=192.168.1.100&user=admin&pass=12345
4. Test streams POST /api/test {sources: {streams: [...]}}
5. Poll results GET /api/test?id=xxx
6. Generate config POST /api/generate {mainStream: "rtsp://...", subStream: "rtsp://..."}
All endpoints return JSON. CORS is enabled. No authentication.
API Reference
System
GET /api
{"version": "2.0.0", "platform": "amd64"}
GET /api/health
{"version": "2.0.0", "uptime": "1h30m0s"}
GET /api/log
Returns in-memory log in application/jsonlines format. Passwords are masked automatically.
DELETE /api/log
Clears in-memory log. Returns 204.
Search
GET /api/search?q={query}
Search camera database by brand, model, or preset name. Empty q returns all presets + first brands (limit 50).
curl "localhost:4567/api/search?q=hikvision"
{
"results": [
{"type": "brand", "id": "b:hikvision", "name": "Hikvision"},
{"type": "model", "id": "m:hikvision:DS-2CD2032", "name": "Hikvision: DS-2CD2032"}
]
}
Result types:
| Type | ID format | Description |
|---|---|---|
preset |
p:{preset_id} |
Curated URL pattern sets (e.g. "ONVIF", "Popular RTSP") |
brand |
b:{brand_id} |
All URL patterns for a brand |
model |
m:{brand_id}:{model} |
URL patterns for a specific model |
Multi-word queries match independently: hikvision DS-2CD matches brand "Hikvision" AND model containing "DS-2CD".
GET /api/streams
Build full stream URLs from database patterns with credentials and placeholders substituted.
| Param | Required | Description |
|---|---|---|
ids |
yes | Comma-separated IDs from search results |
ip |
yes | Camera IP address |
user |
no | Username (URL-encoded automatically) |
pass |
no | Password (URL-encoded automatically) |
channel |
no | Channel number, default 0 |
ports |
no | Comma-separated port filter (only return URLs matching these ports) |
curl "localhost:4567/api/streams?ids=b:hikvision&ip=192.168.1.100&user=admin&pass=12345"
{
"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"
]
}
Maximum 20,000 URLs per request. URLs are deduplicated.
Testing
POST /api/test
Create a test session. 20 parallel workers connect to each URL, extract codecs, capture screenshots.
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"
]
}
}'
{"session_id": "a1b2c3d4e5f6g7h8"}
GET /api/test
List all active and completed sessions.
{
"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 full results. Poll this endpoint to track progress.
{
"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:runningordonecodecs: detected media codecs (H264, H265, PCMA, PCMU, OPUS, etc.)width,height: resolution extracted from JPEG screenshotscreenshot: relative URL to fetch the JPEG image- Sessions expire 30 minutes after completion
DELETE /api/test?id={session_id}
Cancel a running session and delete it.
{"status": "deleted"}
GET /api/test/screenshot?id={session_id}&i={index}
Returns raw JPEG image. Content-Type: image/jpeg.
Config Generation
POST /api/generate
Generate Frigate config from stream URLs.
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"]
}'
{
"config": "mqtt:\n enabled: false\n\nrecord:\n enabled: true\n\ngo2rtc:\n streams:\n ...",
"added": [1, 2, 3, 4, 5]
}
config: complete Frigate YAMLadded: 1-based line numbers of new lines (for highlighting in UI)
Merge into existing config -- pass existingConfig field:
{
"mainStream": "rtsp://...",
"existingConfig": "go2rtc:\n streams:\n existing_cam:\n - rtsp://...\n\ncameras:\n existing_cam:\n ..."
}
Strix finds the right insertion points in go2rtc streams and cameras sections. Camera and stream names are deduplicated automatically.
Full request schema
| Field | Type | Required | Description |
|---|---|---|---|
mainStream |
string | yes | Main stream URL |
subStream |
string | no | Sub stream URL for detect role |
name |
string | no | Camera name (auto-generated from IP if empty) |
existingConfig |
string | no | Existing Frigate YAML to merge into |
objects |
string[] | no | Objects to track (default: ["person"]) |
go2rtc |
object | no | {mainStreamName, subStreamName, mainStreamSource, subStreamSource} |
frigate |
object | no | {mainStreamPath, subStreamPath, mainStreamInputArgs, subStreamInputArgs} |
detect |
object | no | {enabled, fps, width, height} |
record |
object | no | {enabled, retain_days, mode, alerts_days, detections_days, pre_capture, post_capture} |
motion |
object | no | {enabled, threshold, contour_area} |
snapshots |
object | no | {enabled} |
audio |
object | no | {enabled, filters[]} |
ffmpeg |
object | no | {hwaccel, gpu} |
live |
object | no | {height, quality} |
birdseye |
object | no | {enabled, mode} |
onvif |
object | no | {host, port, user, password, autotracking, required_zones[]} |
ptz |
object | no | {enabled, presets{}} |
notifications |
object | no | {enabled} |
ui |
object | no | {order, dashboard} |
Probe
GET /api/probe?ip={ip}
Probe a network device. Runs 6 checks in parallel within 100ms: port scan, ICMP ping, ARP + OUI vendor lookup, reverse DNS, mDNS/HomeKit query, HTTP probe.
curl "localhost:4567/api/probe?ip=192.168.1.100"
{
"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, orunreachableports.open: scanned from 189 ports known in the camera databasearp.vendor: looked up from OUI table in SQLite database- HomeKit cameras return
mdnswithname,model,category(cameraordoorbell),device_id,paired,port - ICMP ping requires
CAP_NET_RAWcapability. Falls back to port scan only.
Frigate
GET /api/frigate/config
Get current Frigate config. Frigate is discovered automatically by probing known addresses (localhost:5000, ccab4aaf-frigate:5000) or via STRIX_FRIGATE_URL.
{"connected": true, "url": "http://localhost:5000", "config": "mqtt:\n enabled: false\n ..."}
{"connected": false, "config": ""}
POST /api/frigate/config/save?save_option={option}
Save config to Frigate. Request body is plain text (YAML config).
| Option | Description |
|---|---|
saveonly |
Save config without restart (default) |
restart |
Save config and restart Frigate |
go2rtc
PUT /api/go2rtc/streams?name={name}&src={source}
Add a stream to go2rtc. Proxied to local go2rtc instance (discovered automatically or via STRIX_GO2RTC_URL).
curl -X PUT "localhost:4567/api/go2rtc/streams?name=front_door&src=rtsp://admin:12345@192.168.1.100/Streaming/Channels/101"
{"success": true}
{"success": false, "error": "go2rtc not found"}