Compare commits

...

105 commits

Author SHA1 Message Date
eduard256
593f2fc14f Sync README install command 2026-04-16 19:00:45 +00:00
eduard256
0a41dac8e4 Sync install.sh fix 2026-04-16 18:58:46 +00:00
eduard256
1f8414079a Replace install.sh with new modular navigator 2026-04-16 18:57:35 +00:00
eduard256
43a097586a Sync scripts from develop 2026-04-16 18:54:08 +00:00
eduard256
fb4797f6b3 Sync scripts from develop 2026-04-16 18:47:55 +00:00
eduard256
4308039e08 Sync scripts from develop 2026-04-16 18:00:56 +00:00
eduard256
df32774b50 Remove test script 2026-04-16 17:51:33 +00:00
eduard256
100149241c Sync all scripts to main 2026-04-16 17:51:19 +00:00
eduard256
f6c80a2c72 Update install.sh with system detection display 2026-04-16 17:06:23 +00:00
eduard256
c86f1b936e Add modular installer scripts
Worker scripts with JSON event streaming:
- detect.sh: system/Docker/Frigate/go2rtc detection
- prepare.sh: Docker and Compose installation
- strix.sh: deploy Strix standalone
- strix-frigate.sh: deploy Strix + Frigate with HW autodetect
- proxmox-lxc-create.sh: create Ubuntu LXC on Proxmox
- install.sh: animated frontend with owl display
2026-04-16 16:56:17 +00:00
eduard256
ffe77cb9c4 Merge develop into main for v2.1.0 release 2026-04-08 11:31:03 +00:00
eduard256
29e03ce85a Release v2.1.0 2026-04-08 11:30:58 +00:00
eduard256
e47c0f7ce6 Add top-1000 checkbox to ONVIF page, classify JPEG streams as alternative
- Add checked-by-default checkbox to also test popular stream patterns
- Move JPEG-only streams (no H264/H265) to Alternative group in test results
2026-04-08 11:27:08 +00:00
eduard256
0fb7356a5e Add ONVIF stream handler for tester
- Add testOnvif(): resolves all profiles via ONVIF client, tests
  each RTSP stream, returns two Results per profile (onvif + rtsp)
  with shared screenshot
- Route onvif:// URLs in worker.go alongside homekit://
- Classify onvif:// streams as recommended in test.html
- Harden create.html against undefined/null URL values
2026-04-08 11:00:32 +00:00
eduard256
ce4b777e98 Add ONVIF camera page and probe routing
- Add onvif.html: credentials form, Discover Streams button,
  fallback to Standard Discovery and HomeKit Pairing
- Update index.html routing: onvif type -> onvif.html with all
  probe params (onvif_url, onvif_port, onvif_name, onvif_hardware,
  mdns_* for HomeKit fallback)
2026-04-08 10:50:05 +00:00
eduard256
5be8d4aa00 Add ONVIF probe detector via unicast WS-Discovery
- Add ProbeONVIF() prober: sends unicast WS-Discovery to ip:3702,
  parses XAddrs, Name, Hardware from response (no auth needed)
- Add ONVIFResult struct to probe models
- Register ONVIF detector with highest priority (before HomeKit)
- Fix homekit.html back-wrapper max-width to match design system
2026-04-08 10:31:46 +00:00
eduard256
1291e6a5b6 Add frontend_design_strix skill for UI page creation
Design guide with principles, layout patterns, component usage,
navigation rules, and checklist. References homekit.html as the
design gold standard and design-system.html for components.
2026-04-08 09:49:25 +00:00
eduard256
699ddda39b Update design system with centered layout, PIN input, floating back button
Add true-center layout pattern, back-wrapper for floating navigation,
PIN digit input component with all states, and centered page demo
with HomeKit logo example. Document PIN input JS pattern.
2026-04-08 09:39:36 +00:00
eduard256
89c5d83a6f Refine HomeKit page: add Apple HomeKit logo, centered layout, back button
Replace text-only header with official HomeKit house icon and
"Apple HomeKit" label. Pin input centered on screen, back button
aligned to container edge. Remove device info table and decorative
elements for a cleaner look matching the rest of the frontend.
2026-04-08 09:30:31 +00:00
eduard256
8398832960 Redesign HomeKit page, add design system reference
Rebuild homekit.html with centered layout, cleaner PIN input,
and consistent styling matching the rest of the frontend.
Add www/design-system.html as a living component reference
for all UI elements used across the Strix frontend.
2026-04-08 08:54:40 +00:00
eduard256
a16799fa8d Add Docker Compose files for Strix, Frigate, and go2rtc setups
Add three docker-compose variants: standalone Strix,
Strix + Frigate, and Strix + go2rtc. Update README with
Docker Compose install instructions linking to the files.
2026-04-05 14:47:54 +00:00
eduard256
0652e53bc7 Update README: add HomeKit protocol and StrixAHKCamFake reference 2026-04-05 14:41:19 +00:00
eduard256
528ec8e00b Add HomeKit stream testing via HAP snapshot
- Add worker_homekit.go with direct hap.Dial + GetImage flow
- Bypass SRTP/Producer pipeline for homekit:// URLs
- Route homekit:// streams to dedicated handler in worker.go
2026-04-05 12:58:26 +00:00
eduard256
a9820abc37 Add HomeKit camera pairing support
- Add POST /api/homekit/pair endpoint that calls hap.Pair() from go2rtc
- Rewrite homekit.html with PIN input UI (XXX-XX-XXX format)
- Auto-advance between digit fields, paste support, error/success states
- On successful pairing, redirect to create.html with homekit:// URL
- Pass mdns_port and mdns_paired from probe to homekit.html
- Detect HomeKit cameras regardless of pairing status
2026-04-05 12:43:06 +00:00
eduard256
e2e24c7578 Switch mDNS probe to multicast, use mDNS for reachability
Unicast mDNS queries (direct to IP:5353) are ignored by some HomeKit
devices. Switch to multicast (224.0.0.251:5353) and filter responses
by sender IP. Also consider mDNS response as reachability signal.

Split probe timeouts: 100ms for ports/DNS/HTTP, 120ms total to give
mDNS extra time. HomeKit responds in ~0.2ms via multicast.
2026-04-05 12:06:11 +00:00
eduard256
f084135701 Remove ICMP ping from probe, add HomeKit port 51826
ICMP requires root or CAP_NET_RAW which is not available in
unprivileged containers. Probe now relies solely on port scanning
for reachability detection, which works without any special
permissions. Add port 51826 (HomeKit) to both default and
database-loaded port lists.
2026-04-05 11:54:24 +00:00
eduard256
4e9ffd1440 Show LAN IP instead of localhost in install summary
Detect local network IP address using ip route / hostname -I / ifconfig
fallback chain and display it in the post-install summary box so users
can immediately open Strix from other devices on the network.
2026-04-05 10:45:46 +00:00
eduard256
83659c9a82 Replace double dashes with single dashes 2026-04-05 10:36:48 +00:00
eduard256
e0ccef8683 Replace double dashes with single dashes 2026-04-05 10:36:47 +00:00
eduard256
166feceab9 Add StrixCamFake link to DEVELOPERS.md 2026-04-05 10:36:11 +00:00
eduard256
66f9131cff Add StrixCamFake link to DEVELOPERS.md 2026-04-05 10:36:10 +00:00
eduard256
8cf3195b51 Add StrixCamFake link to README 2026-04-05 10:35:51 +00:00
eduard256
600141d11b Add StrixCamFake link to README 2026-04-05 10:35:50 +00:00
eduard256
608d4989ff Link feature bullets to corresponding screenshots 2026-04-05 10:28:55 +00:00
eduard256
5fb1efe599 Link feature bullets to corresponding screenshots 2026-04-05 10:28:54 +00:00
eduard256
2ab8106b01 Add supported cameras link to quick links 2026-04-05 10:25:42 +00:00
eduard256
acc456f3f5 Add supported cameras link to quick links 2026-04-05 10:25:41 +00:00
eduard256
22baefd57f Add camera database browse and contribute links 2026-04-05 10:23:33 +00:00
eduard256
f06d60f6ff Add camera database browse and contribute links 2026-04-05 10:23:32 +00:00
eduard256
6044df6ee4 Add horizontal rule before demo GIF 2026-04-05 10:20:39 +00:00
eduard256
56c02f6b72 Add horizontal rule before demo GIF 2026-04-05 10:20:38 +00:00
eduard256
43632fb8c2 Add live demo, video, and API docs links after banner 2026-04-05 10:19:33 +00:00
eduard256
55a4a62752 Add live demo, video, and API docs links after banner 2026-04-05 10:19:32 +00:00
eduard256
4c1fab86b1 Add separator between logo and title 2026-04-05 10:18:26 +00:00
eduard256
1c50564548 Add separator between logo and title 2026-04-05 10:18:25 +00:00
eduard256
1efe3cc9ba Add STRIX text next to logo in header 2026-04-05 10:17:40 +00:00
eduard256
21c96d6548 Add STRIX text next to logo in header 2026-04-05 10:17:39 +00:00
eduard256
4ea3485c9b Move API reference to DEVELOPERS.md 2026-04-05 10:15:47 +00:00
eduard256
dd8966a8d7 Move API reference to DEVELOPERS.md 2026-04-05 10:15:46 +00:00
eduard256
74eed5ede9 Redesign README header with centered layout and feature list 2026-04-05 10:09:26 +00:00
eduard256
96354f018f Redesign README header with centered layout and feature list 2026-04-05 10:09:25 +00:00
eduard256
75947be26b Remove title text from README header 2026-04-05 10:03:45 +00:00
eduard256
e4a28fe61a Remove title text from README header 2026-04-05 10:03:44 +00:00
eduard256
4cb00ec85f Left-align logo and badges in README 2026-04-05 10:03:15 +00:00
eduard256
2fc9be2d9f Left-align logo and badges in README 2026-04-05 10:03:14 +00:00
eduard256
0cf9f7d44e Remove logo caption from README 2026-04-05 10:02:39 +00:00
eduard256
39da8d2d50 Remove logo caption from README 2026-04-05 10:02:38 +00:00
eduard256
8c1a6b1b0e Add MIT license and license badge 2026-04-05 10:02:03 +00:00
eduard256
258f3712c2 Add MIT license and license badge 2026-04-05 10:02:02 +00:00
eduard256
2db7ae6f25 Move badges above icon in README 2026-04-05 10:00:31 +00:00
eduard256
bb740a04bc Move badges above icon in README 2026-04-05 10:00:30 +00:00
eduard256
09bd2ce220 Use PNG icon in README 2026-04-05 09:00:15 +00:00
eduard256
8a4201936a Use PNG icon in README 2026-04-05 09:00:10 +00:00
eduard256
0a30496991 Add README for v2.0.0 2026-04-05 08:58:55 +00:00
eduard256
eb6719237d Add README for v2.0.0 2026-04-05 08:58:23 +00:00
eduard256
ded8aebcad Merge develop into main for v2.0.0 release
# Conflicts:
#	DOCKER.md
#	README.md
2026-04-05 08:32:14 +00:00
eduard256
e2f84ec0f6 Release v2.0.0 2026-04-05 08:32:05 +00:00
eduard256
5f21a91ff9 Add universal Linux installer script
Bash installer that works on any Linux distro:
- Auto-detects OS and architecture
- Installs Docker via get.docker.com if missing
- Installs Docker Compose plugin if missing
- Auto-discovers local Frigate and go2rtc instances
- Interactive dialogs with 10s timeouts
- Generates docker-compose.yml and .env in /opt/strix/
- Supports install and update modes
- CLI flags for non-interactive use (--yes, --version, --no-logo)
- Returns machine-readable status for parent scripts (Proxmox LXC)
2026-04-05 08:13:28 +00:00
eduard256
44ab0651cb Add DVRIP protocol support
- Register dvrip stream handler using go2rtc pkg/dvrip
- Add default port 34567 for dvrip scheme in URL builder
2026-04-03 21:01:39 +00:00
eduard256
51b11e233f Add RTMP protocol support
Register rtmp, rtmps, rtmpx stream handlers using go2rtc
pkg/rtmp.DialPlay for TCP connect, handshake, and play.
2026-04-03 20:33:30 +00:00
eduard256
d59816543d Add direct stream URL input support to web UI 2026-04-03 20:03:45 +00:00
eduard256
4880e1ad14 Add 15s timeout for HTTP handler requests
Cameras under load may accept TCP connection but never respond,
hanging tester workers indefinitely. Context timeout on the HTTP
request ensures workers are released.
2026-04-03 19:26:17 +00:00
eduard256
6abb8409cb Add HTTP/HTTPS protocol support for snapshots and streams
Register http, https, httpx handlers with content-type detection:
- image/jpeg: single JPEG snapshots via go2rtc image.Open
- multipart/x-mixed-replace: MJPEG streams via mpjpeg.Open
- application/vnd.apple.mpegurl: HLS via hls.OpenURL
- auto-detect fallback via magic.Open (MPEG-TS, raw MJPEG, etc.)

Uses go2rtc tcp.Do for Basic + Digest auth and TLS handling.
2026-04-03 16:03:45 +00:00
eduard256
8ce89bec75 Always include port in URL for protocols with raw TCP dial
Bubble protocol uses net.DialTimeout with u.Host directly,
which requires explicit port. Add portRequired set to force
port in generated URLs for such protocols.
2026-04-01 17:53:00 +00:00
eduard256
8e8f568251 Add bubble protocol support
- Register bubble stream handler using go2rtc pkg/bubble
- Add default port 80 for bubble scheme
2026-04-01 17:24:02 +00:00
eduard256
20d5ad2f0b Fix screenshot URL path: remove leading slash 2026-04-01 16:07:22 +00:00
eduard256
f34a7b96c7 Add go2rtc module, test/config/urls pages, Frigate config fixes 2026-03-26 22:45:32 +00:00
eduard256
8dc8ba1096 Add resolution extraction from JPEG screenshots in tester 2026-03-26 10:40:41 +00:00
eduard256
74b4b61198 Add frontend pages, move static to www/, add resolution to tester
Frontend:
- index.html: probe device, navigate to standard/homekit by type
- standard.html: camera config, model search with multi-select
- create.html: stream URL list, custom URL input, create test session
- homekit.html: HomeKit device info, contact links, fallback to standard

Backend:
- Move static files to www/ package with embed (go2rtc pattern)
- Add initStatic() in api with FileServer
- Add width/height to test results from H264 SPS parsing
- Contribute links to gostrix.github.io with auto-filled params
2026-03-26 10:18:40 +00:00
eduard256
0ecf1eb75f Use app.Env for consistent env var access in frigate module 2026-03-25 19:41:25 +00:00
eduard256
e2fdf0d3d6 Add Frigate config proxy with auto-discovery 2026-03-25 19:20:07 +00:00
eduard256
fe4a5dfa2e Simplify Frigate detection, use known HA addon hostname 2026-03-25 19:08:23 +00:00
eduard256
5fdeca8701 Add raw Supervisor API response to frigate check endpoint 2026-03-25 18:58:53 +00:00
eduard256
124007ea31 Rebuild dev image 2026-03-25 18:46:56 +00:00
eduard256
62dcd89fc5 Simplify listHAAddons to return raw Supervisor API JSON 2026-03-25 18:37:53 +00:00
eduard256
a9ab7e2ba6 Add Frigate autodiscovery via HA Supervisor API 2026-03-25 18:30:38 +00:00
eduard256
b060a5372e Add frigate connectivity check endpoint 2026-03-25 18:15:31 +00:00
eduard256
0bf2a83e9d Add probe detector skill 2026-03-25 17:42:22 +00:00
eduard256
bfeae738e3 Add add_protocol skill, update release skills with DB download step 2026-03-25 17:37:20 +00:00
eduard256
4d171f69c7 Add Dockerfile, fix SQLite immutable mode, URL-encode credentials
- Dockerfile: multi-stage build with golang:1.26 and alpine + ffmpeg
- SQLite: use file: URI with immutable=1 for read-only access
- URL builder: encode user/pass with PathEscape/QueryEscape for
  special characters (@, \, :, etc.)
- Health endpoint: truncate uptime to seconds
- Release skill: update smoke test to /api endpoint
- Remove unused ValidateID function
2026-03-25 11:28:47 +00:00
eduard256
27117900eb Rewrite Strix from scratch as single binary
Complete architecture rewrite following go2rtc patterns:
- pkg/ for pure logic (camdb, tester, probe, generate)
- internal/ for application glue with Init() modules
- Single HTTP server on :4567 with all endpoints
- zerolog with password masking and memory ring buffer
- Environment-based config only (no YAML files)

API endpoints: /api/search, /api/streams, /api/test,
/api/probe, /api/generate, /api/health, /api/log

Dependencies: go2rtc v1.9.14, go-sqlite3, miekg/dns, zerolog
2026-03-25 10:38:46 +00:00
eduard256
51b0d06062 Fix database link to homepage 2026-03-23 20:25:03 +00:00
eduard256
3b29188924 Fix database link to homepage 2026-03-23 20:25:02 +00:00
eduard256
efd04367cf Add camera database browse link to README 2026-03-23 20:21:00 +00:00
eduard256
3a18390f42 Add camera database browse link to README 2026-03-23 20:20:59 +00:00
eduard256
cbe1a428b2 Add camera contribution link to README 2026-03-23 20:17:03 +00:00
eduard256
87c96970a6 Add camera contribution link to README 2026-03-23 20:12:13 +00:00
eduard256
7cab640bf2 Add Podman installation docs with required capabilities
Document NET_RAW and NET_ADMIN capabilities needed for network
scanning when running Strix with Podman. Includes podman run,
podman-compose, and Quadlet (systemd) setup instructions.

Addresses #6
2026-03-22 17:57:24 +00:00
eduard256
9e493a2bac Add Podman installation docs with required capabilities
Document NET_RAW and NET_ADMIN capabilities needed for network
scanning when running Strix with Podman. Includes podman run,
podman-compose, and Quadlet (systemd) setup instructions.

Addresses #6
2026-03-22 17:56:10 +00:00
eduard256
3fafdbc6ce Separate structured logs from human-readable output
Move SetupLogger() to a standalone function called before config.Load()
so the logger is available from the very start. Replace all fmt.Printf
calls in config.go with slog calls. Redirect banner and endpoint info
to stderr, keeping stdout clean for structured log output (JSON/text).

Fixes #5
2026-03-22 17:44:16 +00:00
eduard256
4fe5ae9447 URL-encode credentials with special characters in stream URLs
Passwords containing @, #, :, ?, /, %, &, space and other special
characters broke URL parsing, causing streams to not be detected.

Replaced fmt.Sprintf string concatenation with url.URL struct for
building RTSP/HTTP URLs. Credentials in userinfo are now handled via
url.UserPassword() which encodes special chars automatically.

Split replacePlaceholders into two phases:
- Phase 1: safe placeholders (channel, width, IP, port)
- Phase 2: credential placeholders with context-aware encoding:
  - Query string: url.Values.Set + Encode (auto percent-encoding)
  - Path segments: url.PathEscape

Normal passwords (letters, digits, -._~) produce identical URLs
as before -- encoding is a no-op for safe characters.

Fixes #10
2026-03-22 17:13:38 +00:00
eduard256
3acc966658 Mask URL-encoded passwords in debug logs
SecretStore.Add now registers both plain text and URL-encoded forms
of the password. Fixes cases where passwords with special characters
(e.g. @, #, :) appear percent-encoded in URLs but were not matched
by the masking handler.
2026-03-20 19:59:22 +00:00
eduard256
8cf05a1576 Fix credentials leaking in debug logs (#4)
Add a secret-masking slog.Handler that automatically replaces registered
passwords with "***" in all log output. Secrets are registered per-scan
when a discovery request arrives and unregistered when it completes.

This approach masks credentials everywhere they appear in logs — URL
userinfo, query parameters, path segments, and Go HTTP error messages —
without modifying any business logic in scanner, builder, tester, or
ONVIF components. API responses are unaffected and still return full
URLs with credentials for frontend use.
2026-03-20 11:03:01 +00:00
eduard256
c95740137d Merge icon variants from develop 2026-03-19 12:56:31 +00:00
eduard256
e269e243da Add icon variants with dark background and transparent versions 2026-03-19 12:44:20 +00:00
3768 changed files with 15888 additions and 282425 deletions

View file

@ -0,0 +1,316 @@
---
name: add_probe_detector_strix
description: Add a new device type detector to the Strix probe system. Covers adding new probers, result types, and detector functions.
disable-model-invocation: true
argument-hint: [detector-name]
---
# Add Probe Detector to Strix
You are adding a new device type detector to the Strix probe system. The probe system runs when a user enters an IP address -- it discovers what's at that IP and determines the device type. The device type drives the frontend flow.
The detector name is provided as argument (e.g. `/add_probe_detector_strix onvif`). If no argument, use AskUserQuestion to ask which detector to add.
## Repository
- Strix: `/home/user/Strix`
- go2rtc (reference): `/home/user/go2rtc`
---
## STEP 0: Understand the probe system
Before writing anything, read these files COMPLETELY:
```
/home/user/Strix/internal/probe/probe.go -- glue: Init(), runProbe(), detectors, API handler
/home/user/Strix/pkg/probe/models.go -- all data structures (Response, Probes, result types)
/home/user/Strix/pkg/probe/ping.go -- prober example: ICMP ping
/home/user/Strix/pkg/probe/ports.go -- prober example: TCP port scan
/home/user/Strix/pkg/probe/arp.go -- prober example: ARP lookup
/home/user/Strix/pkg/probe/dns.go -- prober example: reverse DNS
/home/user/Strix/pkg/probe/http.go -- prober example: HTTP HEAD request
/home/user/Strix/pkg/probe/mdns.go -- prober example: HomeKit mDNS query
/home/user/Strix/pkg/probe/oui.go -- prober example: OUI vendor lookup
```
Read ALL of them. Every prober is different. Understand the full picture before proceeding.
### How the probe system works
The probe has three layers:
**Layer 1: Probers** (`pkg/probe/`)
Pure functions that gather raw data about an IP address. Each runs in parallel with a shared 100ms timeout context. They do NOT interpret results -- just collect facts.
Current probers:
- `Ping()` -- ICMP echo, returns latency
- `ScanPorts()` -- TCP connect to all known camera ports, returns open ports
- `ReverseDNS()` -- reverse DNS lookup, returns hostname
- `LookupARP()` -- reads /proc/net/arp, returns MAC address
- `LookupOUI()` -- looks up MAC prefix in SQLite, returns vendor name
- `ProbeHTTP()` -- HTTP HEAD to ports 80/8080, returns status + server header
- `QueryHAP()` -- mDNS query for HomeKit Accessory Protocol, returns device info
Every prober writes its result into `resp.Probes.{Name}` via mutex.
**Layer 2: Detectors** (`internal/probe/probe.go`)
Functions registered in the `detectors` slice. They run AFTER all probers complete. Each detector receives the full `*probe.Response` with all probe results and returns a device type string (or empty string to pass).
```go
var detectors []func(*probe.Response) string
```
Detectors are checked in order. First non-empty result wins and sets `resp.Type`.
Default type is `"standard"`. If device is unreachable, type is `"unreachable"`.
**Layer 3: API** (`internal/probe/probe.go`)
`GET /api/probe?ip=192.168.1.100` returns the full Response JSON. The frontend uses `type` field to decide which UI flow to show.
### Data flow
```
IP address
|
v
[All probers run in parallel, 100ms timeout]
|
v
probe.Response filled with results
|
v
[Detectors run in order on the Response]
|
v
resp.Type = "homekit" | "standard" | "unreachable" | ...
|
v
JSON response to frontend
```
### API response example
```json
{
"ip": "192.168.1.100",
"reachable": true,
"latency_ms": 2.5,
"type": "homekit",
"probes": {
"ping": {"latency_ms": 2.5},
"ports": {"open": [80, 554, 5353]},
"dns": {"hostname": "camera.local"},
"arp": {"mac": "C0:56:E3:AA:BB:CC", "vendor": "Hikvision"},
"mdns": {
"name": "My Camera",
"device_id": "AA:BB:CC:DD:EE:FF",
"model": "Camera 1080p",
"category": "camera",
"paired": false,
"port": 80
},
"http": {"port": 80, "status_code": 200, "server": "nginx"}
}
}
```
---
## STEP 1: Determine what you need
Use AskUserQuestion to discuss with the user. There are two scenarios:
### Scenario A: Detector only (using existing probe data)
The detector can determine device type from data already collected by existing probers. No new prober needed.
Examples:
- Detect ONVIF cameras by checking if port 80 is open and HTTP server header contains "onvif" or specific vendor strings
- Detect specific brands by ARP vendor name
- Detect UPnP devices by checking specific open ports
In this case: skip to STEP 3.
### Scenario B: New prober + detector
Need to collect new data that existing probers don't provide. Requires adding a new prober to `pkg/probe/` and a new result type to `models.go`.
Examples:
- ONVIF discovery (send ONVIF GetCapabilities request)
- UPnP SSDP discovery
- Specific protocol handshake
In this case: proceed to STEP 2.
---
## STEP 2: Add new prober (Scenario B only)
### 2a: Add result type to models.go
Edit `/home/user/Strix/pkg/probe/models.go`:
1. Add new result struct:
```go
type {Name}Result struct {
// fields specific to this probe
}
```
2. Add field to `Probes` struct:
```go
type Probes struct {
Ping *PingResult `json:"ping"`
Ports *PortsResult `json:"ports"`
DNS *DNSResult `json:"dns"`
ARP *ARPResult `json:"arp"`
MDNS *MDNSResult `json:"mdns"`
HTTP *HTTPResult `json:"http"`
{Name} *{Name}Result `json:"{name}"` // add here
}
```
### 2b: Write prober function
Create `/home/user/Strix/pkg/probe/{name}.go`.
Rules:
- Pure function, no app/api imports
- Takes `context.Context` and `ip string` as first params
- Returns `(*{Name}Result, error)`
- Respects context deadline (timeout comes from runProbe)
- Returns `nil, nil` when device doesn't support this (NOT an error)
- Keep it simple -- one file, one function
Pattern:
```go
package probe
import "context"
func Probe{Name}(ctx context.Context, ip string) (*{Name}Result, error) {
// respect context deadline
deadline, ok := ctx.Deadline()
if !ok {
// set sensible default
}
// do the probe work...
// not supported = nil, nil (not an error)
// found = &{Name}Result{...}, nil
// actual error = nil, err
}
```
### 2c: Wire prober into runProbe
Edit `/home/user/Strix/internal/probe/probe.go`, add to `runProbe()` alongside other probers:
```go
run(func() {
r, _ := probe.Probe{Name}(ctx, ip)
mu.Lock()
resp.Probes.{Name} = r
mu.Unlock()
})
```
All probers run in parallel inside the same `run()` pattern. The mutex protects writes to `resp.Probes`.
---
## STEP 3: Add detector function
Edit `/home/user/Strix/internal/probe/probe.go`, add detector in `Init()`:
```go
// {Name} detector
detectors = append(detectors, func(r *probe.Response) string {
// check probe results to determine device type
// return type string or "" to pass
if r.Probes.{Something} != nil && {condition} {
return "{type_name}"
}
return ""
})
```
### Detector rules
1. Return a SHORT type string: `"homekit"`, `"onvif"`, `"tapo"`, etc.
2. Return `""` (empty) to pass to the next detector
3. Detectors run in order -- put more specific detectors BEFORE generic ones
4. A detector can use ANY combination of probe results (ports, HTTP, ARP, mDNS, custom)
5. Don't do network I/O in detectors -- all data should come from probers
### Type string convention
The type string is used by the frontend to select UI flow:
- `"unreachable"` -- device not found (set automatically, don't return this)
- `"standard"` -- default, normal camera (set automatically if no detector matches)
- `"homekit"` -- Apple HomeKit device
- Custom types: lowercase, one word, matches the protocol/brand name
---
## STEP 4: Build and test
```bash
cd /home/user/Strix
go build ./...
```
If it compiles, rebuild Docker and test:
```bash
docker build -t strix:test .
docker rm -f strix
docker run -d --name strix --network host --restart unless-stopped strix:test
sleep 2
# test probe on a known device
curl -s "http://localhost:4567/api/probe?ip={DEVICE_IP}" | python3 -m json.tool
```
Verify:
1. New probe data appears in `probes` object (if new prober added)
2. `type` field correctly identifies the device
3. No errors in `docker logs strix`
---
## STEP 5: Commit and push
```bash
cd /home/user/Strix
git add -A
git commit -m "Add {name} probe detector"
git push origin develop
```
---
## CODE STYLE
### pkg/probe/ files
- One file per prober
- Pure functions, no globals, no app imports
- `context.Context` as first param for anything with I/O
- Return `nil, nil` for "not applicable" (not an error)
- Short names: `conn`, `resp`, `buf`
### internal/probe/probe.go
- Detectors are inline anonymous functions in Init()
- Keep detector logic minimal -- just check fields and return type
- If detector logic is complex (>10 lines), extract to a named function in the same file
### models.go
- All result structs in one file
- JSON tags use lowercase with underscores
- Optional fields use `omitempty`
- Pointer types for probe results (nil = not collected)

View file

@ -0,0 +1,581 @@
---
name: add_protocol_strix
description: Add a new protocol support to Strix -- full flow from research to implementation. Covers stream handler registration, URL builder updates, database issues, and go2rtc integration.
disable-model-invocation: true
argument-hint: [protocol-name]
---
# Add Protocol to Strix
You are adding support for a new protocol to Strix. Follow every step in order. Be thorough -- read all referenced files completely before writing any code.
The protocol name is provided as argument (e.g. `/add_protocol_strix bubble`). If no argument, use AskUserQuestion to ask which protocol to add.
## Repositories
- Strix: `/home/user/Strix`
- go2rtc: `/home/user/go2rtc` (reference implementation, read-only)
- StrixCamDB: issues at https://github.com/eduard256/StrixCamDB/issues (for database updates)
---
## STEP 0: Understand the existing RTSP implementation (REFERENCE)
Before doing anything, read these files completely to understand the patterns:
```
/home/user/Strix/pkg/tester/source.go -- handler registry + RTSP reference implementation
/home/user/Strix/pkg/tester/worker.go -- how handlers are called, screenshot logic
/home/user/Strix/pkg/tester/session.go -- session data structures
/home/user/Strix/pkg/camdb/streams.go -- URL builder, placeholder replacement
/home/user/Strix/internal/test/test.go -- API layer for tester
/home/user/Strix/internal/search/search.go -- search API (rarely needs changes)
```
### How RTSP works (the reference pattern)
**Registration** in `pkg/tester/source.go`:
```go
var handlers = map[string]SourceHandler{}
func RegisterSource(scheme string, handler SourceHandler) {
handlers[scheme] = handler
}
func init() {
RegisterSource("rtsp", rtspHandler)
RegisterSource("rtsps", rtspHandler)
RegisterSource("rtspx", rtspHandler)
}
```
**Handler** -- receives a URL string, returns go2rtc `core.Producer`:
```go
func rtspHandler(rawURL string) (core.Producer, error) {
rawURL, _, _ = strings.Cut(rawURL, "#")
conn := rtsp.NewClient(rawURL)
conn.Backchannel = false
if err := conn.Dial(); err != nil {
return nil, fmt.Errorf("rtsp: dial: %w", err)
}
if err := conn.Describe(); err != nil {
_ = conn.Stop()
return nil, fmt.Errorf("rtsp: describe: %w", err)
}
return conn, nil
}
```
**Data flow**: URL -> GetHandler(url) -> handler(url) -> core.Producer -> GetMedias() -> codecs, latency -> getScreenshot() -> jpegSize() -> Result (with width, height)
**Key**: The handler ONLY needs to return a `core.Producer`. Everything else (codecs extraction, screenshot capture, session management) is handled automatically by `worker.go`.
### How URLs are built in `pkg/camdb/streams.go`:
1. Database has URL templates like `/cam/realmonitor?channel=[CHANNEL]&subtype=0`
2. `replacePlaceholders()` substitutes `[CHANNEL]`, `[USERNAME]`, `[PASSWORD]`, etc.
3. `buildURL()` prepends `protocol://user:pass@host:port` to the path
4. Credentials are URL-encoded with `url.PathEscape` / `url.QueryEscape`
Default ports are defined in `defaultPorts` map:
```go
var defaultPorts = map[string]int{
"rtsp": 554, "rtsps": 322, "http": 80, "https": 443,
"rtmp": 1935, "mms": 554, "rtp": 5004,
}
```
---
## STEP 1: Research the protocol in go2rtc
go2rtc already implements most camera protocols. Study the implementation:
### Where to look in go2rtc
| What | Where |
|------|-------|
| Protocol client logic | `/home/user/go2rtc/pkg/{protocol}/` |
| Module registration | `/home/user/go2rtc/internal/{protocol}/` |
| Core interfaces | `/home/user/go2rtc/pkg/core/core.go` |
| Stream handler registry | `/home/user/go2rtc/internal/streams/handlers.go` |
| Keyframe capture | `/home/user/go2rtc/pkg/magic/keyframe.go` |
### Protocol map in go2rtc
| Protocol | pkg/ (Dial function) | internal/ (Init glue) |
|----------|---------------------|----------------------|
| rtsp/rtsps | `pkg/rtsp/client.go` | `internal/rtsp/rtsp.go` |
| http/https | `pkg/magic/producer.go`, `pkg/tcp/request.go` | `internal/http/http.go` |
| rtmp | `pkg/rtmp/` | `internal/rtmp/rtmp.go` |
| bubble | `pkg/bubble/` | `internal/bubble/bubble.go` |
| dvrip | `pkg/dvrip/` | `internal/dvrip/dvrip.go` |
| onvif | `pkg/onvif/` | `internal/onvif/onvif.go` |
| homekit | `pkg/homekit/`, `pkg/hap/` | `internal/homekit/homekit.go` |
| tapo | `pkg/tapo/` | `internal/tapo/tapo.go` |
| kasa | `pkg/kasa/` | `internal/kasa/kasa.go` |
| eseecloud | `pkg/eseecloud/` | `internal/eseecloud/eseecloud.go` |
| nest | `pkg/nest/` | `internal/nest/init.go` |
| ring | `pkg/ring/` | `internal/ring/ring.go` |
| wyze | `pkg/wyze/` | `internal/wyze/wyze.go` |
| xiaomi | `pkg/xiaomi/` | `internal/xiaomi/xiaomi.go` |
| tuya | `pkg/tuya/` | `internal/tuya/tuya.go` |
| doorbird | `pkg/doorbird/` | `internal/doorbird/doorbird.go` |
| isapi | `pkg/isapi/` | `internal/isapi/init.go` |
| flussonic | `pkg/flussonic/` | `internal/flussonic/flussonic.go` |
| gopro | `pkg/gopro/` | `internal/gopro/gopro.go` |
| roborock | `pkg/roborock/` | `internal/roborock/roborock.go` |
### What to read
1. Read `/home/user/go2rtc/internal/{protocol}/{protocol}.go` -- find `streams.HandleFunc` call, understand what function is called and how
2. Read `/home/user/go2rtc/pkg/{protocol}/` -- find the `Dial()` or `NewClient()` function, understand its signature and what it returns
3. Understand: does it return `core.Producer`? Does it need special setup before Dial? Does it need credentials differently?
### Typical go2rtc internal module (e.g. kasa -- simplest):
```go
package kasa
import (
"github.com/AlexxIT/go2rtc/internal/streams"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/kasa"
)
func Init() {
streams.HandleFunc("kasa", func(source string) (core.Producer, error) {
return kasa.Dial(source)
})
}
```
Most protocols follow this exact pattern: `pkg/{protocol}.Dial(url)` returns `core.Producer`.
---
## STEP 2: Classify the protocol
Use AskUserQuestion to discuss with the user. Determine the protocol type:
### Type A: Standard URL-based protocol (rtsp, rtmp, bubble, dvrip, http, etc.)
- Has URL scheme (e.g. `bubble://host:port/path`)
- URLs stored in StrixCamDB database
- Flow: user searches camera -> gets URL templates -> URLs built with credentials -> sent to tester
- Needs: stream handler in tester + default port in URL builder + database issue
### Type B: Custom/discovery protocol (homekit, onvif, etc.)
- Does NOT use standard URL templates from database
- Has custom discovery or authentication flow
- Data comes from probe endpoint or direct user input, NOT from camera search
- Needs: source handler in tester with custom logic, possibly probe endpoint update
- Does NOT need database issue
### Type C: HTTP sub-protocol (mjpeg, jpeg snapshot, hls)
- Uses http:// or https:// URL scheme
- Already has URLs in database (same as HTTP)
- Needs special handling in tester based on Content-Type response
- Needs: stream handler that detects content type and handles accordingly
---
## STEP 3: For Type A -- Create StrixCamDB issue
ONLY for Type A protocols that have URL patterns stored in the database.
Create a GitHub issue using `gh` CLI for the new protocol:
```bash
cd /home/user/Strix
gh issue create --repo eduard256/StrixCamDB \
--title "[New Protocol] {PROTOCOL_NAME}" \
--label "new-protocol" \
--body "$(cat <<'ISSUE_EOF'
```yaml
protocol: {PROTOCOL_NAME}
default_port: {PORT}
url_format: {EXAMPLE_URL_PATTERN}
```
## Description
{DESCRIPTION -- what cameras use this, what firmware, how it works}
## Known brands
- {BRAND1}
- {BRAND2}
## URL patterns
- {PATTERN1} -- main stream
- {PATTERN2} -- sub stream
## Where to research
- go2rtc source: https://github.com/AlexxIT/go2rtc/tree/master/pkg/{PROTOCOL_NAME}
- ispyconnect: search for "{PROTOCOL_NAME}" cameras
## Notes
{ANY_NOTES}
ISSUE_EOF
)"
```
If the protocol introduces new placeholders (e.g. `[STREAM]`), create a separate issue:
```bash
gh issue create --repo eduard256/StrixCamDB \
--title "[New Placeholder] {PLACEHOLDER}" \
--label "new-placeholder" \
--body "$(cat <<'ISSUE_EOF'
placeholder: "{PLACEHOLDER}"
alternatives: ["{alt1}", "{alt2}"]
description: "{WHAT_IT_DOES}"
example_values: ["{VAL1}", "{VAL2}"]
## URL examples
- {URL_EXAMPLE_1}
- {URL_EXAMPLE_2}
## Known brands using this
- {BRAND1}
- {BRAND2}
ISSUE_EOF
)"
```
DO NOT wait for issue approval. Continue immediately to the next step.
---
## STEP 4: Update URL builder (Type A only)
If the protocol needs a new default port, edit `/home/user/Strix/pkg/camdb/streams.go`:
Add the port to `defaultPorts` map:
```go
var defaultPorts = map[string]int{
"rtsp": 554, "rtsps": 322, "http": 80, "https": 443,
"rtmp": 1935, "mms": 554, "rtp": 5004,
// add new protocol here:
"bubble": 80,
}
```
If the protocol needs new placeholders in `replacePlaceholders()`, add them to the pairs slice. Follow the existing pattern -- both `[UPPER]` and `[lower]` variants, plus `{curly}` variants.
### Files to edit for URL builder:
- `/home/user/Strix/pkg/camdb/streams.go` -- `defaultPorts` map and `replacePlaceholders()` function
---
## STEP 5: Add stream handler to tester
### Before writing code
1. Read ALL existing handlers in `/home/user/Strix/pkg/tester/source.go` completely
2. Read the go2rtc pkg/ implementation for this protocol (Step 1)
3. Understand what the `Dial()` function needs and returns
### For standard protocols (Type A, most Type C)
Most protocols follow the same pattern as RTSP. The handler:
1. Takes a URL string
2. Calls go2rtc's `pkg/{protocol}.Dial(url)` or equivalent
3. Returns `core.Producer`
Add the handler to `/home/user/Strix/pkg/tester/source.go`.
**Pattern for simple protocols** (bubble, dvrip, rtmp, kasa, etc.):
```go
import "github.com/AlexxIT/go2rtc/pkg/{protocol}"
// in init():
RegisterSource("{scheme}", {scheme}Handler)
// handler:
func {scheme}Handler(rawURL string) (core.Producer, error) {
return {protocol}.Dial(rawURL)
}
```
If the protocol needs extra setup before Dial (like RTSP needs `Backchannel = false`), add it. Study the go2rtc internal module to see what setup is done.
**Pattern for protocols that need connection setup** (like RTSP):
```go
func {scheme}Handler(rawURL string) (core.Producer, error) {
rawURL, _, _ = strings.Cut(rawURL, "#")
conn := {protocol}.NewClient(rawURL)
// any setup specific to this protocol
if err := conn.Dial(); err != nil {
return nil, fmt.Errorf("{scheme}: dial: %w", err)
}
// protocol-specific validation (like RTSP Describe)
return conn, nil
}
```
### For custom protocols (Type B -- homekit, onvif, etc.)
These protocols do NOT go through the standard URL -> handler flow. They need a **source handler** that receives custom parameters and produces results directly.
The current architecture uses `SourceHandler func(rawURL string) (core.Producer, error)` for standard protocols. For custom protocols, you need to:
1. Extend the POST /api/test request to accept custom source blocks
2. Handle them separately from the `streams` array
Current request format:
```json
{
"sources": {
"streams": ["rtsp://...", "http://..."]
}
}
```
Extended format for custom protocols:
```json
{
"sources": {
"streams": ["rtsp://...", "http://..."],
"homekit": {"device_id": "AA:BB:CC", "pin": "123-45-678"},
"onvif": {"host": "192.168.1.100", "username": "admin", "password": "pass"}
}
}
```
To implement this:
1. Define a source handler type in `/home/user/Strix/pkg/tester/source.go`:
```go
// SourceBlockHandler processes a custom source block, writes results directly to session
type SourceBlockHandler func(data json.RawMessage, s *Session)
var sourceHandlers = map[string]SourceBlockHandler{}
func RegisterSourceBlock(name string, handler SourceBlockHandler) {
sourceHandlers[name] = handler
}
```
2. Update `/home/user/Strix/internal/test/test.go` `apiTestCreate()` to parse and dispatch custom source blocks.
3. Write the handler for your protocol. It receives raw JSON and a Session, and is responsible for:
- Parsing its own parameters
- Running its own discovery/test logic
- Adding Results to the Session
- Calling `s.AddTested()` for progress tracking
**IMPORTANT**: Before implementing a custom protocol, discuss the approach with the user. Custom protocols are rare and need careful design.
---
## STEP 6: Test the implementation
### Build and verify
```bash
cd /home/user/Strix
go build ./...
```
If it compiles, test with the running container:
```bash
# rebuild image
docker build -t strix:test .
# restart container
docker rm -f strix
docker run -d --name strix --network host --restart unless-stopped strix:test
# check logs
docker logs strix
# test the new protocol (example for bubble)
curl -s -X POST http://localhost:4567/api/test \
-H 'Content-Type: application/json' \
-d '{"sources":{"streams":["bubble://admin:password@192.168.1.100:80/"]}}'
```
### What to verify
1. Handler is registered -- check logs for no errors at startup
2. URLs with the new scheme are dispatched to the correct handler
3. If Type A: verify `/api/streams` returns URLs with correct scheme and port
4. Test with a real device if available
---
## STEP 7: Commit and push
```bash
cd /home/user/Strix
git add -A
git commit -m "Add {protocol} protocol support
- Register {protocol} stream handler using go2rtc pkg/{protocol}
- Add default port {port} for {protocol} scheme
- {any other changes}"
git push origin develop
```
---
## CODE STYLE RULES
All code MUST follow AlexxIT go2rtc style:
### File organization
- One handler per protocol is fine in `source.go` if it's a one-liner (`return pkg.Dial(url)`)
- If handler needs >10 lines of custom logic, create `source_{protocol}.go`
- Keep `source.go` as the registry + simple handlers
- Complex protocols get their own file
### Naming
- Handler: `{scheme}Handler` (e.g. `bubbleHandler`, `rtmpHandler`)
- Error prefix: `"{scheme}: dial: ..."` or `"{scheme}: ..."`
- Short var names: `conn` for connection, `prod` for producer
### Error handling
- Wrap errors with protocol prefix: `fmt.Errorf("bubble: dial: %w", err)`
- Close/stop connections on error: `_ = conn.Stop()`
- Return nil Producer on error, never a half-initialized one
### Comments
- Comment ONLY if the "why" is not obvious
- No docstrings on every function
- Inline examples: `// ex. "bubble://admin:pass@192.168.1.100:80/"`
### Imports
- go2rtc packages: `"github.com/AlexxIT/go2rtc/pkg/{protocol}"`
- Always import `"github.com/AlexxIT/go2rtc/pkg/core"` for Producer interface
- Group: stdlib, then go2rtc, then project packages
---
## go2rtc INTERNALS REFERENCE
### core.Producer interface (pkg/core/core.go)
Every protocol handler must return something that implements `core.Producer`:
```go
type Producer interface {
GetMedias() []*Media // what tracks are available (video/audio codecs)
GetTrack(media *Media, codec *Codec) (*Receiver, error) // get specific track
Start() error // start receiving packets (blocking)
Stop() error // close connection
}
```
The tester uses:
1. `GetMedias()` -- to list codecs (H264, AAC, etc.)
2. `GetTrack()` + `Start()` -- to capture screenshot (keyframe)
3. `Stop()` -- to clean up
### How screenshot and resolution work (pkg/tester/worker.go)
1. `getScreenshot(prod)` is called after successful Dial
2. Creates `magic.NewKeyframe()` consumer
3. Matches video media between producer and consumer
4. Gets track via `prod.GetTrack()`
5. Starts `prod.Start()` in goroutine (blocking -- reads packets)
6. Waits for first keyframe via `cons.WriteTo()` with 10s timeout
7. If H264/H265 -- converts to JPEG via ffmpeg
8. If already JPEG -- uses as-is
9. `jpegSize(jpeg)` extracts width and height from JPEG SOF0/SOF2 marker
10. Resolution stored in `Result.Width` and `Result.Height`
This works automatically for ANY protocol that returns a valid `core.Producer`. You do NOT need to implement screenshot or resolution logic per protocol.
### Result struct (pkg/tester/session.go)
```go
type Result struct {
Source string `json:"source"`
Screenshot string `json:"screenshot,omitempty"`
Codecs []string `json:"codecs,omitempty"`
Width int `json:"width,omitempty"` // from JPEG screenshot
Height int `json:"height,omitempty"` // from JPEG screenshot
LatencyMs int64 `json:"latency_ms,omitempty"`
Skipped bool `json:"skipped,omitempty"`
}
```
Resolution is extracted from the JPEG screenshot, not from SDP or protocol-specific data. This means width/height are only available when a screenshot was successfully captured. The frontend uses these values to classify streams as Main (HD) or Sub (SD).
### magic.NewKeyframe() (pkg/magic/keyframe.go)
Captures first video keyframe from any Producer. Supports H264, H265, JPEG, MJPEG. The tester uses this -- you never call it directly from a protocol handler.
### Connection patterns in go2rtc
**Simple Dial** (most protocols):
```go
// pkg/bubble/client.go
func Dial(rawURL string) (core.Producer, error) {
// parse URL, connect, return producer
}
```
**Client with setup** (rtsp):
```go
// pkg/rtsp/client.go
conn := rtsp.NewClient(rawURL)
conn.Backchannel = false // optional setup
conn.Dial() // TCP connect
conn.Describe() // RTSP DESCRIBE (gets SDP)
// conn is now a Producer
```
**HTTP-based** (complex -- content type detection):
```go
// pkg/magic/producer.go
// Opens HTTP connection, detects Content-Type:
// - multipart/x-mixed-replace -> MJPEG
// - image/jpeg -> single JPEG frame
// - application/vnd.apple.mpegurl -> HLS
// - video/mp2t -> MPEG-TS
// - etc.
```
### TCP/TLS connection (pkg/tcp/)
Many protocols use `pkg/tcp` for low-level connection:
- `tcp.Dial(rawURL)` -- TCP connect with timeout
- `tcp.Client` -- HTTP client with digest/basic auth
- Used by RTSP, HTTP, and others internally
---
## CHECKLIST BEFORE FINISHING
- [ ] Read all existing protocol handlers in `source.go`
- [ ] Read go2rtc pkg/ and internal/ for this protocol
- [ ] Determined protocol type (A/B/C)
- [ ] For Type A: created StrixCamDB issue (protocol + placeholders if needed)
- [ ] For Type A: added default port to `defaultPorts` in `streams.go` (if not already there)
- [ ] Added handler registration in `source.go` init() or new file
- [ ] Handler follows RTSP pattern: Dial -> return Producer
- [ ] Error messages prefixed with protocol name
- [ ] Connections closed on error
- [ ] Code compiles: `go build ./...`
- [ ] Committed and pushed to develop

View file

@ -0,0 +1,211 @@
---
name: frontend_design_strix
description: Create or redesign frontend pages for Strix. Use when building new HTML pages, redesigning existing ones, or working on any UI task in the www/ directory. Covers design principles, layout patterns, and component usage.
disable-model-invocation: true
---
# Strix Frontend Design
You are creating or modifying a frontend page for Strix. Your goal is to produce a page that looks **identical in quality** to the existing pages, especially `www/homekit.html` which is the design reference.
## Before you start
Read these files completely:
1. **`www/design-system.html`** -- All CSS variables, every component, JS patterns. This is your component library.
2. **`www/homekit.html`** -- The design reference. This page is the gold standard. Study its structure, spacing, how little text it uses, how the back button is positioned.
3. **`www/index.html`** -- The entry point. Understand the probe flow and how data is passed between pages via URL params.
If you need to understand backend APIs or the probe system, read:
- `www/standard.html` -- how probe data flows into a configuration page
- `www/test.html` -- how polling and real-time updates work
- `www/config.html` -- complex two-column layout with live preview
## Design Philosophy
### Radical minimalism
Every element on screen must earn its place. If something doesn't help the user complete their task, remove it.
- **10% text, 90% meaning.** A label that says "Pairing Code" with an info-icon is better than a paragraph explaining what a pairing code is.
- **Hide details behind info-icons.** Long explanations go into tooltips (the `(i)` icon pattern). The user who needs the explanation can hover. The user who doesn't is not bothered.
- **No decorative elements without function.** No ornamental icons, no badges that don't convey information, no cards-as-decoration.
- **One action per screen.** Each page should have one primary thing the user does. Everything else is secondary.
### How we think about design decisions
When building homekit.html, we went through this process:
1. **Started with all the data** -- device info table, long descriptions, badges, decorative icons
2. **Asked "does the user need this?"** for every element
3. **Removed everything that wasn't essential** -- the device info table (IP, MAC, vendor) was removed because the user doesn't need it to enter a PIN code
4. **Moved explanations into tooltips** -- "This camera supports Apple HomeKit. Enter the 8-digit pairing code printed on your camera or included in the manual" became just a label "Pairing Code" with a tooltip
5. **Removed format hints** -- "Format: XXX-XX-XXX" was removed because the input fields themselves make the format obvious
6. **Made the primary action obvious** -- big button, full width, impossible to miss
Apply this same thinking to every page you create.
### Visual rules
- Dark theme with purple accent -- never deviate from the color palette in `:root`
- All icons are inline SVG -- never use emoji, never use icon fonts, never use external icon libraries
- Fonts: system font stack for UI, monospace for technical values (URLs, IPs, codes)
- Borders are subtle: `rgba(139, 92, 246, 0.15)` -- barely visible purple tint
- Glow effects on focus and hover, never on static elements (except logos)
- Animations are fast (150ms) and subtle -- translateY(-2px) on hover, fadeIn on page load
- No rounded corners larger than 8px (except special cases like toggle switches)
## Layout Patterns
### Pages after probe (like homekit.html) -- TRUE CENTER
This is the most common case for new pages. Content is vertically centered on screen.
```
.screen {
min-height: 100vh;
display: flex;
align-items: center; /* TRUE CENTER -- not flex-start */
justify-content: center;
}
.container { max-width: 480px; width: 100%; }
```
**Back button** is positioned OUTSIDE the container, wider than content, using `.back-wrapper`:
```
.back-wrapper {
position: absolute; top: 1.5rem;
left: 50%; transform: translateX(-50%);
width: 100%; max-width: 600px; /* wider than container */
padding: 0 1.5rem;
z-index: 10;
}
```
This is MANDATORY for all centered layout pages. The back button must NOT be inside the centered container.
### Entry page (like index.html) -- TOP CENTER
Content is near the top with `margin-top: 8vh`. Used for the main entry point only.
### Content pages (like standard.html, create.html) -- STANDARD
Back button at top, then title, then content flowing down. `max-width: 600px`, no vertical centering.
### Data-heavy pages (like test.html) -- WIDE
`max-width: 1200px` with card grids.
### Two-column (like config.html) -- SPLIT
Settings left, live preview right. Collapses to tabs on mobile.
## Hero Section Pattern
For centered pages, the hero contains a logo/icon + short title:
```html
<div class="hero">
<svg class="logo-icon">...</svg> <!-- 48-72px, with glow filter -->
<h1 class="title">Short Name</h1> <!-- 1.25rem, white, font-weight 600 -->
</div>
```
- The icon should be recognizable and relevant (Strix owl for main, HomeKit house for HomeKit)
- The title is SHORT -- one or two words max
- No subtitles unless absolutely necessary
- Glow effect on the icon via `filter: drop-shadow()`
## Component Usage
All components are documented with live examples in `www/design-system.html`. Key ones:
- **Buttons**: `.btn .btn-primary .btn-large` for primary action (full width), `.btn-outline` for secondary
- **Inputs**: `.input` with `.label` and optional `.info-icon` with `.tooltip`
- **Toast**: Every page needs `<div id="toast" class="toast hidden"></div>` and the `showToast()` function
- **Error box**: `.error-box` with `.visible` class toggled
- **Info icon + tooltip**: For hiding explanations -- always prefer this over visible text
## Navigation -- CRITICAL
### Always pass ALL known data forward
When navigating to another page, pass every piece of data you have. This is non-negotiable. Future pages may need any of these values.
```javascript
function navigateNext() {
var p = new URLSearchParams();
p.set('primary_data', value);
// Pass through EVERYTHING known:
if (ip) p.set('ip', ip);
if (mac) p.set('mac', mac);
if (vendor) p.set('vendor', vendor);
if (model) p.set('model', model);
if (server) p.set('server', server);
if (hostname) p.set('hostname', hostname);
if (ports) p.set('ports', ports);
if (user) p.set('user', user);
if (channel) p.set('channel', channel);
// ... any other params from probe
window.location.href = 'next.html?' + p.toString();
}
```
### Page init always reads all params
```javascript
var params = new URLSearchParams(location.search);
var ip = params.get('ip') || '';
var mac = params.get('mac') || '';
var vendor = params.get('vendor') || '';
// ... read ALL possible params even if this page doesn't use them
// They need to be available for passing to the next page
```
## JavaScript Rules
- Use `var`, not `let`/`const` -- ES5 compatible
- Build DOM with `document.createElement`, not innerHTML
- Use `async function` + `fetch()` for API calls
- Always handle errors: check `!r.ok`, catch exceptions, show toast
- Debounce input handlers if they trigger API calls (300ms)
- Use `addEventListener`, never inline event handlers in HTML
## API Pattern
```javascript
async function doSomething() {
try {
var r = await fetch('api/endpoint', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!r.ok) {
var text = await r.text();
showToast(text || 'Error ' + r.status);
return;
}
var data = await r.json();
// success...
} catch (e) {
showToast('Connection error: ' + e.message);
}
}
```
## Checklist before finishing
- [ ] Page uses correct layout pattern for its type
- [ ] Back button positioned correctly (`.back-wrapper` for centered, inline for standard)
- [ ] All CSS variables from `:root` -- no hardcoded colors
- [ ] No unnecessary text -- everything possible hidden behind info-icons
- [ ] All known URL params are read at init and passed forward on navigation
- [ ] Toast element present, showToast function included
- [ ] Error states handled (API errors, validation)
- [ ] Mobile responsive (test at 375px width)
- [ ] No emoji anywhere
- [ ] All icons are inline SVG
- [ ] Primary action is obvious and full-width
- [ ] Page looks like it belongs with homekit.html and index.html

View file

@ -1,6 +1,6 @@
---
name: release_strix
description: Full release of Strix -- merge develop to main, tag, build multiarch Docker image, push to Docker Hub, update hassio-strix, create GitHub Release.
description: Full release of Strix -- merge develop to main, tag, build multiarch Docker image, build static binaries, push to Docker Hub, update hassio-strix, create GitHub Release with binaries attached.
disable-model-invocation: true
---
@ -13,6 +13,10 @@ You are performing a full release of Strix. Follow every step exactly. Do NOT sk
- Strix: `/home/user/Strix`
- hassio-strix: `/home/user/hassio-strix`
## Versioning
Version is injected at build time via ldflags (`-X main.version=$VERSION`). There is NO hardcoded version in the source code -- `main.go` has `var version = "dev"` as default. The Dockerfile passes `--build-arg VERSION` which maps to the same ldflags. Do NOT edit `main.go` to set the version.
## Step 1: Gather information
```bash
@ -47,17 +51,29 @@ Offer options:
Wait for answer. Store the chosen version as VERSION (without "v" prefix).
## Step 3: Verify build
## Step 3: Download latest camera database
```bash
cd /home/user/Strix
gh release download latest --repo eduard256/StrixCamDB --pattern "cameras.db" --clobber
```
Verify the database was downloaded:
```bash
ls -lh cameras.db
```
## Step 4: Verify build
```bash
cd /home/user/Strix
go test ./...
go build ./...
CGO_ENABLED=0 go build ./...
```
If tests or build fail -- STOP and report the error. Do not continue.
## Step 4: Update CHANGELOG.md
## Step 5: Update CHANGELOG.md
Read `/home/user/Strix/CHANGELOG.md`. Add a new section at the top (after the header lines), based on the commits from Step 1. Follow the existing format exactly:
@ -76,7 +92,7 @@ Read `/home/user/Strix/CHANGELOG.md`. Add a new section at the top (after the he
Use today's date. Categorize commits into Added/Fixed/Changed/Technical sections. Only include sections that have entries. Write clear, user-facing descriptions (not raw commit messages).
## Step 5: Git -- commit, merge, tag, push
## Step 6: Git -- commit, merge, tag, push
```bash
cd /home/user/Strix
@ -94,7 +110,7 @@ git merge main
git push origin develop
```
## Step 6: Build and push Docker image
## Step 7: Build and push Docker image
```bash
cd /home/user/Strix
@ -107,7 +123,7 @@ docker buildx build --platform linux/amd64,linux/arm64 \
--push .
```
## Step 7: Verify Docker Hub
## Step 8: Verify Docker Hub
```bash
curl -s "https://hub.docker.com/v2/repositories/eduard256/strix/tags/?page_size=10" | jq '.results[].name'
@ -116,18 +132,18 @@ docker manifest inspect eduard256/strix:$VERSION | jq '.manifests[].platform'
Verify the new version tag exists and both amd64 and arm64 platforms are present.
## Step 8: Smoke test
## Step 9: Smoke test
```bash
docker run --rm -d --name strix-smoke-test -p 14567:4567 eduard256/strix:$VERSION
sleep 5
curl -s http://localhost:14567/api/v1/health | jq '.version'
curl -s http://localhost:14567/api | jq '.version'
docker stop strix-smoke-test
```
Verify the health endpoint returns the correct version string.
## Step 9: Update hassio-strix
## Step 10: Update hassio-strix
```bash
cd /home/user/hassio-strix
@ -136,7 +152,7 @@ git pull origin main
Edit `/home/user/hassio-strix/strix/config.json` -- change `"version"` to the new VERSION.
Edit `/home/user/hassio-strix/strix/CHANGELOG.md` -- add the same CHANGELOG section as in Step 4.
Edit `/home/user/hassio-strix/strix/CHANGELOG.md` -- add the same CHANGELOG section as in Step 5.
```bash
cd /home/user/hassio-strix
@ -145,17 +161,40 @@ git commit -m "Release v$VERSION"
git push origin main
```
## Step 10: GitHub Release
## Step 11: Build static binaries
Build static binaries for both platforms:
```bash
cd /home/user/Strix
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -X main.version=$VERSION" -o strix-linux-amd64 .
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -X main.version=$VERSION" -o strix-linux-arm64 .
```
Verify both binaries are statically linked:
```bash
file strix-linux-amd64 strix-linux-arm64
```
## Step 12: GitHub Release
Create the release and attach binaries:
```bash
cd /home/user/Strix
PREV_TAG=$(git tag --sort=-version:refname | sed -n '2p')
gh release create v$VERSION \
--title "v$VERSION" \
--notes "$(git log --oneline ${PREV_TAG}..v$VERSION)"
--notes "$(git log --oneline ${PREV_TAG}..v$VERSION)" \
strix-linux-amd64 strix-linux-arm64
```
## Step 11: Final report
Clean up binaries after upload:
```bash
rm -f strix-linux-amd64 strix-linux-arm64
```
## Step 13: Final report
Output a summary:
@ -164,6 +203,7 @@ Release v$VERSION complete:
- Git: tag v$VERSION pushed to main
- Docker Hub: eduard256/strix:$VERSION (amd64 + arm64)
- Health check: version "$VERSION" verified
- Binaries: strix-linux-amd64, strix-linux-arm64 attached to GitHub Release
- hassio-strix: config.json updated to $VERSION, pushed to main
- GitHub Release: <URL from gh release create>
```

View file

@ -22,21 +22,29 @@ git rev-parse --short HEAD
Store this as COMMIT_HASH (e.g. `fe93aa3`).
## Step 2: Build Docker image
## Step 2: Download latest camera database
```bash
cd /home/user/Strix
gh release download latest --repo eduard256/StrixCamDB --pattern "cameras.db" --clobber
ls -lh cameras.db
```
## Step 3: Build Docker image
```bash
cd /home/user/Strix
docker build --build-arg VERSION=dev-$COMMIT_HASH -t eduard256/strix:dev -t eduard256/strix:dev-$COMMIT_HASH .
```
## Step 3: Push to Docker Hub
## Step 4: Push to Docker Hub
```bash
docker push eduard256/strix:dev
docker push eduard256/strix:dev-$COMMIT_HASH
```
## Step 4: Update hassio-strix
## Step 5: Update hassio-strix
```bash
cd /home/user/hassio-strix
@ -52,7 +60,7 @@ git commit -m "Dev build dev-$COMMIT_HASH"
git push origin main
```
## Step 5: Report
## Step 6: Report
Output a summary:

View file

@ -1,52 +0,0 @@
# Git
.git
.gitignore
.github
# IDE
.vscode
.idea
*.swp
*.swo
*~
# Build artifacts
bin/
dist/
*.exe
*.dll
*.so
*.dylib
# Test files
*.test
*_test.go
coverage.*
*.out
# Logs
*.log
strix.log
# Config files (user-specific)
strix.yaml
test_*.yaml
config.yaml
# Temporary files
tmp/
temp/
*.dump
*_output.txt
# Documentation (included in image metadata instead)
*.md
!README.md
# OS files
.DS_Store
Thumbs.db
# Development
.env
.env.local

53
.gitignore vendored
View file

@ -1,50 +1,7 @@
# Binaries
bin/
# Binary
strix
main
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binaries
*.test
# Output of the go coverage tool
*.out
coverage.html
# Go workspace file
go.work
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
# Logs
*.log
# Environment
.env
.env.local
# Temporary files
tmp/
temp/
*.dump
*_output.txt
# Configuration (user-specific)
strix.yaml
# Node.js / NPM
node_modules/
package-lock.json
# SQLite database files
*.db
*.db-shm
*.db-wal

View file

@ -1,111 +1,48 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.11] - 2026-03-19
## [2.1.0] - 2026-04-08
### Added
- Project icon assets (SVG, 192x192 PNG, 512x512 PNG) for use in app stores and integrations
### Fixed
- Health endpoint now accepts HEAD requests for Docker and CasaOS healthcheck compatibility
- Registered HEAD route in chi router for /api/v1/health endpoint
## [1.0.10] - 2026-03-17
### Added
- Device probe endpoint (GET /api/v1/probe) for network device inspection
- HTTP prober for detecting camera web interfaces
- mDNS discovery for local network devices
- ARP/OUI vendor identification with camera OUI database (2,400+ entries)
- Probe integration into frontend with modal UI
- Added Trassir and ZOSI to OUI database
- ONVIF protocol support: auto-discovery via unicast WS-Discovery, stream resolution through ONVIF profiles
- ONVIF probe detector: detects ONVIF cameras during network probe (4-7ms response time, no auth required)
- ONVIF camera page (onvif.html): credentials form with option to also test popular stream patterns
- ONVIF stream handler: resolves all camera profiles, tests each via RTSP, returns paired results (onvif:// + rtsp://) with shared screenshots
- Design system reference (design-system.html) with all UI components documented
### Changed
- Removed CI/CD pipelines (GitHub Actions), replaced with local Docker builds
- Removed GoReleaser, unified Docker image for Docker Hub and HA add-on
- Application version now injected at build time via ldflags
- HA add-on reads /data/options.json natively (no more entrypoint script)
- Optimized mDNS discovery timeout
- ONVIF has highest probe priority (above HomeKit and Standard)
- JPEG-only streams (no H264/H265) are classified as Alternative in test results
- HomeKit page redesigned: Apple HomeKit logo, centered layout, floating back button
- Hardened create.html against undefined/null URL values in query parameters
### Fixed
- Removed experimental SSE warning from Home Assistant Add-on documentation
- Clear probe-filled fields when navigating back in frontend
## [1.0.9] - 2025-12-11
### Fixed
- Fixed real-time SSE streaming in Home Assistant Ingress mode
- SSE events now arrive immediately instead of being buffered until completion
### Technical
- Added automatic detection of Home Assistant Ingress via X-Ingress-Path header
- Implemented 64KB padding for SSE events to overcome aiohttp buffer in HA Supervisor
- Adjusted progress update interval to 3 seconds in Ingress mode to reduce traffic
- Normal mode (Docker/direct access) remains unchanged
## [1.0.8] - 2025-11-26
### Changed
- Updated Docker deployment to use host network mode for better compatibility
- Modified docker-compose.yml to use `network_mode: host`
- Updated installation commands to use `--network host` flag
- Removed port mappings as they are not needed with host network mode
### Improved
- Better compatibility with unprivileged LXC containers
- Simplified Docker networking configuration
- Direct network access for improved camera discovery performance
## [1.0.7] - 2025-11-23
### Fixed
- Fixed channel numbering for Hikvision-style cameras (reported by @sergbond_com)
- Removed invalid test data from Hikvision database
- Fixed brand+model search matching in stream discovery
## [2.0.0] - 2025-04-05
### Added
- Universal `[CHANNEL+1]` placeholder support for flexible channel numbering
- Support for both 0-based (channel=0 → 101) and 1-based (channel=1 → 101) channel selection
- Added 6 high-priority Hikvision patterns to popular stream patterns database
- Complete rewrite as a single Go binary with modular architecture
- DVRIP protocol support
- RTMP protocol support
- Bubble protocol support
- HTTP/HTTPS protocol support for snapshots and streams
- Direct stream URL input in web UI
- Frigate config proxy with auto-discovery via HA Supervisor API
- Frigate connectivity check endpoint
- go2rtc module with auto-discovery
- Network probe system: port scanning, ICMP ping, ARP/OUI lookup, mDNS/HomeKit detection, HTTP probing
- Camera stream tester with automatic JPEG screenshot capture and resolution extraction
- Frigate config generator from camera database
- Web UI pages: search, test, config, URLs, go2rtc streams, HomeKit
- SQLite camera database loaded from external StrixCamDB repository
- Universal Linux installer script with Docker/Compose auto-setup
- In-memory log viewer API endpoint
- Dockerfile with multi-stage build and healthcheck
### Fixed
- Screenshot URL path: removed leading slash
- Credentials with special characters are now URL-encoded in stream URLs
- Credentials no longer leak in debug logs
### Changed
- Updated 14 camera brands with universal channel patterns (Hikvision, Hiwatch, Annke, Swann, Abus, 7links, LevelOne, AlienDVR, Oswoo, AV102IP-40, Acvil, TBKVision, Deltaco, Night Owl)
- Hikvision: replaced 10 hardcoded patterns with 6 universal patterns
- Hiwatch: replaced 4 hardcoded patterns with 8 universal patterns (including ISAPI variants)
- Universal patterns now tested first for faster discovery, hardcoded patterns kept as fallback
- Improved stream discovery performance with intelligent pattern ordering
### Technical
- Added support for `[CHANNEL+1]`, `[channel+1]`, `{CHANNEL+1}`, `{channel+1}` placeholders in URL builder
- Modified 16 files: +2448 additions, -1954 deletions
## [0.1.0] - 2025-11-06
### Added
- 🦉 Initial release of Strix
- 🌐 Web-based user interface for camera stream discovery
- 🔍 Automatic RTSP stream discovery for IP cameras
- 📹 Support for multiple camera manufacturers
- 🎯 ONVIF device discovery and PTZ endpoint detection
- 🔐 Credential embedding in stream URLs
- 📊 Camera model database with autocomplete search
- 🎨 Modern, responsive UI with purple owl logo
- ⚙️ Configuration export for Go2RTC and Frigate
- 🔄 Dual-stream support with optional sub-stream selection
- 📡 Server-Sent Events (SSE) for real-time discovery progress
- 🚀 RESTful API for camera search and stream discovery
- 📦 Cross-platform support (Linux, Windows, macOS)
- 🏗️ Built with Go for high performance
### Features
- **Web Interface**: Clean, intuitive UI for camera configuration
- **Stream Discovery**: Automatically finds working RTSP streams
- **ONVIF Support**: Discovers ONVIF devices and PTZ capabilities
- **Multi-Platform**: Binaries for Linux (amd64, arm64, arm/v7), Windows, and macOS
- **Easy Integration**: Export configs for popular NVR systems
[0.1.0]: https://github.com/eduard256/Strix/releases/tag/v0.1.0
- Version is now injected at build time via ldflags (no hardcoded version in source)
- Pure Go build with no CGO dependency (switched from mattn/go-sqlite3 to modernc.org/sqlite)
- Port is always included in URL for protocols with raw TCP dial
- Structured logging with zerolog, separate from human-readable output

View file

@ -1,185 +0,0 @@
# Результаты тестирования дедупликации потоков
## Запуск тестов
```bash
go test -v ./internal/camera/stream -run "Dedup|Worst|Multiple"
```
## ✅ Тесты выполнены успешно
Все тесты **PASS**, что означает, что они успешно **ДЕМОНСТРИРУЮТ ПРОБЛЕМУ** текущей системы дедупликации.
---
## 📊 Результаты
### Тест 1: HTTP Authentication Variants
**Проблема:** Один HTTP endpoint генерирует 4 разных URL
```
http://192.168.1.100/snapshot.jpg
http://admin:12345@192.168.1.100/snapshot.jpg
http://192.168.1.100/snapshot.jpg?pwd=12345&user=admin
http://admin:12345@192.168.1.100/snapshot.jpg?pwd=12345&user=admin
```
- **Реально уникальных:** 1 поток
- **Генерируется:** 4 URL
- **Потери:** 3 лишних теста (75%)
---
### Тест 2: HTTP with Placeholders
**Проблема:** URL с плейсхолдерами генерирует дубликаты
```
Entry: snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]
Generated:
http://192.168.1.100/snapshot.cgi?pwd=&user=
http://admin:12345@192.168.1.100/snapshot.cgi?pwd=&user=
http://192.168.1.100/snapshot.cgi?pwd=12345&user=admin
http://admin:12345@192.168.1.100/snapshot.cgi?pwd=12345&user=admin
```
- **Реально уникальных:** 1 поток
- **Генерируется:** 4 URL
- **Потери:** 3 лишних теста (75%)
---
### Тест 3: RTSP with/without Credentials
**Проблема:** RTSP генерирует 2 варианта одного потока
```
rtsp://admin:12345@192.168.1.100/live/main
rtsp://192.168.1.100/live/main
```
- **Реально уникальных:** 1 поток
- **Генерируется:** 2 URL
- **Потери:** 1 лишний тест (50%)
---
### Тест 4: Multiple Sources (Popular + Model)
**Проблема:** Разные источники генерируют одинаковые паттерны
```
Source 1 (Popular Patterns):
rtsp://admin:12345@192.168.1.100/Streaming/Channels/101
rtsp://192.168.1.100/Streaming/Channels/101
Source 2 (Model Patterns):
rtsp://admin:12345@192.168.1.100/Streaming/Channels/101
rtsp://192.168.1.100/Streaming/Channels/101
```
**Текущая дедупликация:**
- Детектирует: 2 точных совпадения (50%)
- НЕ детектирует: 1 семантический дубль
**Итого:**
- Total generated: 4 URL
- After current dedup: 2 URL
- Real unique: 1 поток
- **Эффективность: 50%** (должна быть 75%)
---
### Тест 5: Worst Case Scenario
**Проблема:** Один паттерн из 3 источников (Popular + Model + ONVIF)
```
Popular patterns generates: 4 URLs
Model patterns generates: 4 URLs
ONVIF returns: 1 URL
```
**После текущей дедупликации:** 4 URL остаются
```
http://192.168.1.100/snapshot.jpg
http://admin:12345@192.168.1.100/snapshot.jpg
http://192.168.1.100/snapshot.jpg?pwd=12345&user=admin
http://admin:12345@192.168.1.100/snapshot.jpg?pwd=12345&user=admin
```
**Canonical analysis:**
- Real unique streams: **1**
- URLs being tested: **4**
- **Waste: 3 unnecessary tests (75%)**
- **Time waste: ~6 seconds** (assuming 2s per test)
---
## 🔴 Критические выводы
### 1. Текущая система НЕ работает для семантических дубликатов
Простое сравнение строк `urlMap[url] = true` детектирует только **точные совпадения**.
### 2. Масштаб проблемы
| Сценарий | Генерируется | Реально | Потери |
|----------|--------------|---------|--------|
| HTTP auth variants | 4 | 1 | 75% |
| RTSP with/without creds | 2 | 1 | 50% |
| Multiple sources | 4 | 1 | 75% |
| Worst case | 4 | 1 | 75% |
**Среднее:** ~69% лишних тестов!
### 3. Реальные последствия
При типичном сканировании:
- **Генерируется:** ~190 URL
- **Реально уникальных:** ~80-95
- **Лишних тестов:** 95-110 (50%)
- **Потери времени:** 3-4 минуты
- **Лишняя нагрузка на камеру:** 100+ запросов
- **Плохой UX:** пользователь видит один поток 4 раза
---
## ✅ Решение
Тесты доказывают необходимость **канонической нормализации URL**.
См. файл `/tmp/dedup_solutions.md` для подробного описания решений.
### Рекомендуемый подход: Гибридный
1. **В Builder:** Уменьшить генерацию вариантов (с 4 до 2-3)
2. **В Scanner:** Добавить `CanonicalURL()` функцию
3. **Ожидаемый результат:** Дедупликация 99% вместо текущих 50%
---
## 📝 Следующие шаги
1. ✅ Написать тесты (done)
2. ⏳ Реализовать `normalizer.go` с `CanonicalURL()`
3. ⏳ Модифицировать `Builder.BuildURLsFromEntry()` - убрать лишние варианты
4. ⏳ Модифицировать `Scanner.collectStreams()` - использовать canonical map
5. ⏳ Добавить метрики дедупликации в логи
6. ⏳ Прогнать тесты заново и убедиться в улучшении
---
## 🎯 Ожидаемый результат
После внедрения решения:
```
Real unique streams: 1
URLs being tested: 1 ← вместо 4
Waste: 0 unnecessary tests (0%) ← вместо 75%
Deduplication effectiveness: 99% ← вместо 50%
```

370
DEVELOPERS.md Normal file
View file

@ -0,0 +1,370 @@
# 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](https://github.com/AlexxIT/go2rtc) does.
For development and testing without real cameras, use [StrixCamFake](https://github.com/eduard256/StrixCamFake) - IP camera emulator with RTSP, HTTP, RTMP, Bubble and more.
## Binary
Download from [GitHub Releases](https://github.com/eduard256/Strix/releases). Two platforms: `linux/amd64` and `linux/arm64`.
```bash
chmod +x strix-linux-amd64
./strix-linux-amd64
```
The binary needs `cameras.db` in the working directory. Download it from [StrixCamDB](https://github.com/eduard256/StrixCamDB/releases):
```bash
curl -fsSL https://github.com/eduard256/StrixCamDB/releases/latest/download/cameras.db -o cameras.db
./strix-linux-amd64
```
## Docker
```bash
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`
```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. 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).
```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"}
]
}
```
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) |
```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"
]
}
```
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.
```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 active and completed 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 full results. Poll this endpoint to track progress.
```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`
- `codecs`: detected media codecs (H264, H265, PCMA, PCMU, OPUS, etc.)
- `width`, `height`: resolution extracted from JPEG screenshot
- `screenshot`: 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.
```json
{"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.
```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 enabled: true\n\ngo2rtc:\n streams:\n ...",
"added": [1, 2, 3, 4, 5]
}
```
- `config`: complete Frigate YAML
- `added`: 1-based line numbers of new lines (for highlighting in UI)
**Merge into existing config** - pass `existingConfig` field:
```json
{
"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.
<details>
<summary>Full request schema</summary>
| 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}` |
</details>
---
### 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.
```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`
- `ports.open`: scanned from 189 ports known in the camera database
- `arp.vendor`: looked up from OUI table in SQLite database
- HomeKit cameras return `mdns` with `name`, `model`, `category` (`camera` or `doorbell`), `device_id`, `paired`, `port`
- ICMP ping requires `CAP_NET_RAW` capability. 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`.
```json
{"connected": true, "url": "http://localhost:5000", "config": "mqtt:\n enabled: false\n ..."}
```
```json
{"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`).
```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}
```
```json
{"success": false, "error": "go2rtc not found"}
```

164
DOCKER.md
View file

@ -1,164 +0,0 @@
# 🐳 Docker Setup for Strix
## Quick Start
### Using Docker Compose (Recommended)
```bash
# Start Strix
docker-compose up -d
# View logs
docker-compose logs -f strix
# Stop Strix
docker-compose down
```
Access: http://localhost:4567
### Using Docker Run
```bash
docker run -d \
--name strix \
-p 4567:4567 \
eduard256/strix:latest
```
## Configuration
### Using Environment Variables
```bash
docker run -d \
--name strix \
-p 8080:8080 \
-e STRIX_API_LISTEN=:8080 \
-e STRIX_LOG_LEVEL=debug \
eduard256/strix:latest
```
### Using Config File
```bash
# Create strix.yaml
cat > strix.yaml <<EOF
api:
listen: ":8080"
EOF
# Run with mounted config
docker run -d \
--name strix \
-p 8080:8080 \
-v $(pwd)/strix.yaml:/app/strix.yaml:ro \
eduard256/strix:latest
```
## Full Stack (Strix + go2rtc + Frigate)
```bash
docker-compose -f docker-compose.full.yml up -d
```
Services:
- Strix: http://localhost:4567
- go2rtc: http://localhost:1984
- Frigate: http://localhost:5000
## Building Locally
```bash
# Build for your platform
docker build -t strix:local .
# Build for multiple platforms
docker buildx build --platform linux/amd64,linux/arm64 -t strix:multi .
```
## Image Information
- **Image**: `eduard256/strix:latest`
- **Platforms**: linux/amd64, linux/arm64
- **Size**: ~80-90MB
- **Base**: Alpine Linux
- **User**: Non-root (strix:1000)
## Included Dependencies
- ffmpeg/ffprobe (stream validation)
- ca-certificates (HTTPS support)
- tzdata (timezone support)
- wget (healthcheck)
- Camera database (3600+ models)
## Health Check
```bash
# Check container health
docker inspect --format='{{.State.Health.Status}}' strix
# Manual health check
docker exec strix wget -q -O- http://localhost:4567/api/v1/health
```
## Troubleshooting
### View logs
```bash
docker logs strix
docker logs -f strix # Follow logs
```
### Check if ffprobe works
```bash
docker exec strix ffprobe -version
```
### Inspect container
```bash
docker exec -it strix sh
```
### Restart container
```bash
docker restart strix
```
## Security
- Runs as non-root user (UID 1000)
- Minimal attack surface (Alpine base)
- No unnecessary packages
- Health checks enabled
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `STRIX_API_LISTEN` | `:4567` | Server listen address |
| `STRIX_LOG_LEVEL` | `info` | Log level (debug, info, warn, error) |
| `STRIX_LOG_FORMAT` | `json` | Log format (json, text) |
| `STRIX_DATA_PATH` | `./data` | Camera database path |
## Volumes
```bash
# Optional: Custom configuration
-v ./strix.yaml:/app/strix.yaml:ro
# Optional: Custom camera database
-v ./data:/app/data:ro
```
## Docker Hub
Pre-built images available at: https://hub.docker.com/r/eduard256/strix
Tags:
- `latest` - Latest stable release
- `v0.1.0` - Specific version
- `0.1` - Minor version
- `0` - Major version
- `main` - Development branch

View file

@ -1,69 +1,26 @@
# Strix - Smart IP Camera Stream Discovery System
# Multi-stage Dockerfile for minimal image size
FROM golang:1.26-alpine AS builder
# Stage 1: Builder
FROM golang:1.24-alpine AS builder
ARG VERSION=dev
WORKDIR /build
# Install build dependencies
RUN apk add --no-cache git
# Copy go mod files
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
# Copy source code
COPY . .
# Build static binary
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build \
-ldflags="-s -w -X main.Version=${VERSION}" \
-o strix \
cmd/strix/main.go
ARG VERSION=dev
RUN CGO_ENABLED=0 go build -ldflags "-s -w -X main.version=${VERSION}" -o /strix .
# Stage 2: Runtime
FROM alpine:latest
# Install runtime dependencies
# - ffmpeg/ffprobe: Required for RTSP stream validation
# - ca-certificates: Required for HTTPS requests to cameras
# - tzdata: Required for correct timestamps
# - wget: Required for healthcheck
RUN apk add --no-cache \
ffmpeg \
ca-certificates \
tzdata \
wget \
&& rm -rf /var/cache/apk/*
RUN apk add --no-cache ffmpeg ca-certificates
COPY --from=builder /strix /usr/local/bin/strix
WORKDIR /app
COPY cameras.db .
# Copy binary from builder
COPY --from=builder /build/strix .
# Copy camera database (CRITICAL - app won't work without it)
COPY --from=builder /build/data ./data
# Create directory for optional config
RUN mkdir -p /app/config
# Create non-root user for security
RUN addgroup -g 1000 strix && \
adduser -D -u 1000 -G strix strix && \
chown -R strix:strix /app
# Switch to non-root user
USER strix
# Expose default port
EXPOSE 4567
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:4567/api/v1/health || exit 1
HEALTHCHECK --interval=30s --timeout=3s CMD wget -q --spider http://localhost:4567/api/health || exit 1
# Start application
CMD ["./strix"]
USER nobody
ENTRYPOINT ["strix"]

View file

@ -1,155 +0,0 @@
# Frigate Configuration - Запись по движению с детекцией объектов
Конфигурация для Frigate с записью при обнаружении движения и детекцией объектов (person, car, cat, dog).
## Dual-Stream конфиг (Main + Sub) - РЕКОМЕНДУЕТСЯ
Используется sub stream для детекции (экономия CPU), main stream для записи (качество).
```yaml
mqtt:
enabled: false
# Глобальные настройки записи
record:
enabled: true
retain:
days: 7
mode: motion # Записывать только при движении
# Go2RTC Configuration (Frigate built-in)
go2rtc:
streams:
'10_0_20_112_main':
- rtsp://admin:password@10.0.20.112/live/main
'10_0_20_112_sub':
- rtsp://admin:password@10.0.20.112/live/sub
# Frigate Camera Configuration
cameras:
camera_10_0_20_112:
ffmpeg:
inputs:
- path: rtsp://127.0.0.1:8554/10_0_20_112_sub
input_args: preset-rtsp-restream
roles:
- detect
- path: rtsp://127.0.0.1:8554/10_0_20_112_main
input_args: preset-rtsp-restream
roles:
- record
live:
streams:
Main Stream: 10_0_20_112_main # HD для просмотра
Sub Stream: 10_0_20_112_sub # Низкое разрешение (опционально)
objects:
track:
- person
- car
- cat
- dog
record:
enabled: true
version: 0.16-0
```
## Single-Stream конфиг (Main только)
Когда нет sub stream - используется main для детекции и записи.
```yaml
mqtt:
enabled: false
# Глобальные настройки записи
record:
enabled: true
retain:
days: 7
mode: motion # Записывать только при движении
# Go2RTC Configuration (Frigate built-in)
go2rtc:
streams:
'10_0_20_112_main':
- rtsp://admin:password@10.0.20.112/stream1
# Frigate Camera Configuration
cameras:
camera_10_0_20_112:
ffmpeg:
inputs:
- path: rtsp://127.0.0.1:8554/10_0_20_112_main
input_args: preset-rtsp-restream
roles:
- detect
- record
objects:
track:
- person
- car
- cat
- dog
record:
enabled: true
version: 0.16-0
```
## Режимы записи
### `mode: motion` (рекомендуется)
Записывает видео при обнаружении движения. Экономит место на диске.
### `mode: active_objects`
Записывает только когда обнаружены объекты (person, car, etc). Еще больше экономия.
### `mode: all`
Записывает постоянно 24/7. Требует много места на диске.
## Преимущества Dual-Stream подхода
**Низкая нагрузка на CPU** - детекция на sub stream (обычно 352x288 или 640x480)
**Качественная запись** - запись на main stream в полном разрешении (HD/4K)
**Быстрая детекция** - меньше пикселей = быстрее обработка
**Авто-определение разрешения** - Frigate сам определяет параметры потока
**Одно подключение к камере** - Go2RTC мультиплексирует потоки
## Что делает этот конфиг
**Детекция** - работает постоянно, ищет объекты
**Запись** - начинается при движении
**Объекты** - распознает person, car, cat, dog
**Хранение** - 7 дней записи
**Snapshots** - сохраняются автоматически при детекции
## Добавление других объектов
Чтобы добавить больше объектов для детекции, измените секцию `objects.track`:
```yaml
objects:
track:
- person
- car
- cat
- dog
- motorcycle # Мотоциклы
- bicycle # Велосипеды
- truck # Грузовики
- bus # Автобусы
```
Полный список доступных объектов: https://docs.frigate.video/configuration/objects/
## Примечания
- Dual-stream экономит CPU, используйте когда камера поддерживает sub stream
- Single-stream проще, но требует больше CPU для детекции (особенно на 4K)
- Frigate автоматически определяет разрешение потоков, блок `detect` не нужен
- Запись по движению экономит место, но может пропустить начало события
- Для непрерывной записи используйте `mode: all`
- Frigate автоматически управляет удалением старых записей
- Main stream поддерживает любое разрешение: HD (1920x1080), 4K (3840x2160) и выше

147
Makefile
View file

@ -1,147 +0,0 @@
.PHONY: all build clean run test install deps fmt vet lint
# Variables
BINARY_NAME=strix
BINARY_PATH=bin/$(BINARY_NAME)
MAIN_PATH=cmd/strix/main.go
GO=go
GOFLAGS=-v
LDFLAGS=-ldflags "-s -w -X main.Version=$$(git describe --tags --always --dirty 2>/dev/null || echo 'dev')"
# Default target
all: build
# Build the application
build:
@echo "Building $(BINARY_NAME)..."
@mkdir -p bin
$(GO) build $(GOFLAGS) $(LDFLAGS) -o $(BINARY_PATH) $(MAIN_PATH)
@echo "Build complete: $(BINARY_PATH)"
# Run the application
run: build
@echo "Running $(BINARY_NAME)..."
./$(BINARY_PATH)
# Clean build artifacts
clean:
@echo "Cleaning..."
@rm -rf bin/
@$(GO) clean
@echo "Clean complete"
# Install dependencies
deps:
@echo "Installing dependencies..."
$(GO) mod download
$(GO) mod tidy
@echo "Dependencies installed"
# Format code
fmt:
@echo "Formatting code..."
$(GO) fmt ./...
@echo "Code formatted"
# Run vet
vet:
@echo "Running go vet..."
$(GO) vet ./...
@echo "Vet complete"
# Run linter (requires golangci-lint)
lint:
@echo "Running linter..."
@if command -v golangci-lint > /dev/null; then \
golangci-lint run ./...; \
else \
echo "golangci-lint not installed, skipping..."; \
fi
# Run tests
test:
@echo "Running tests..."
$(GO) test -v -race -cover ./...
@echo "Tests complete"
# Run tests with coverage
test-coverage:
@echo "Running tests with coverage..."
$(GO) test -v -race -coverprofile=coverage.out ./...
$(GO) tool cover -html=coverage.out -o coverage.html
@echo "Coverage report generated: coverage.html"
# Build for multiple platforms
build-all:
@echo "Building for multiple platforms..."
@mkdir -p bin
@echo "Building for Linux amd64..."
GOOS=linux GOARCH=amd64 $(GO) build $(GOFLAGS) $(LDFLAGS) -o bin/$(BINARY_NAME)-linux-amd64 $(MAIN_PATH)
@echo "Building for Linux arm64..."
GOOS=linux GOARCH=arm64 $(GO) build $(GOFLAGS) $(LDFLAGS) -o bin/$(BINARY_NAME)-linux-arm64 $(MAIN_PATH)
@echo "Building for Darwin amd64..."
GOOS=darwin GOARCH=amd64 $(GO) build $(GOFLAGS) $(LDFLAGS) -o bin/$(BINARY_NAME)-darwin-amd64 $(MAIN_PATH)
@echo "Building for Darwin arm64..."
GOOS=darwin GOARCH=arm64 $(GO) build $(GOFLAGS) $(LDFLAGS) -o bin/$(BINARY_NAME)-darwin-arm64 $(MAIN_PATH)
@echo "Building for Windows amd64..."
GOOS=windows GOARCH=amd64 $(GO) build $(GOFLAGS) $(LDFLAGS) -o bin/$(BINARY_NAME)-windows-amd64.exe $(MAIN_PATH)
@echo "Multi-platform build complete"
# Install the binary to GOPATH
install: build
@echo "Installing $(BINARY_NAME)..."
$(GO) install $(GOFLAGS) $(LDFLAGS) $(MAIN_PATH)
@echo "Installation complete"
# Development mode with live reload (requires air)
dev:
@if command -v air > /dev/null; then \
air; \
else \
echo "Air not installed. Install with: go install github.com/air-verse/air@latest"; \
echo "Running without live reload..."; \
$(MAKE) run; \
fi
# Docker build
docker-build:
@echo "Building Docker image..."
docker build -t strix:latest .
@echo "Docker image built: strix:latest"
# Docker run
docker-run:
@echo "Running Docker container..."
docker run -p 8080:8080 -v $(PWD)/data:/data strix:latest
# Check code quality
check: fmt vet lint test
@echo "Code quality check complete"
# Help
help:
@echo "Strix - Smart IP Camera Stream Discovery System"
@echo ""
@echo "Available targets:"
@echo " make build - Build the application"
@echo " make run - Build and run the application"
@echo " make clean - Remove build artifacts"
@echo " make deps - Install dependencies"
@echo " make fmt - Format code"
@echo " make vet - Run go vet"
@echo " make lint - Run linter"
@echo " make test - Run tests"
@echo " make test-coverage - Run tests with coverage"
@echo " make build-all - Build for multiple platforms"
@echo " make install - Install to GOPATH"
@echo " make dev - Run in development mode with live reload"
@echo " make docker-build - Build Docker image"
@echo " make docker-run - Run Docker container"
@echo " make check - Run all quality checks"
@echo " make help - Show this help message"

655
README.md
View file

@ -1,550 +1,177 @@
# Strix
[![GitHub Stars](https://img.shields.io/github/stars/eduard256/strix?style=social)](https://github.com/eduard256/strix/stargazers)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Docker Pulls](https://img.shields.io/docker/pulls/eduard256/strix)](https://hub.docker.com/r/eduard256/strix)
<h1 align="center">
<a href="https://github.com/eduard256/Strix">
<img src="https://github.com/eduard256/Strix/releases/download/v2.0.0/icon-192.png" width="64" alt="Strix" valign="middle">
</a>
&nbsp;|&nbsp;
STRIX
</h1>
<p align="center">
<a href="https://github.com/eduard256/strix/stargazers"><img src="https://img.shields.io/github/stars/eduard256/strix?style=flat-square&logo=github" alt="GitHub Stars"></a>
<a href="https://hub.docker.com/r/eduard256/strix"><img src="https://img.shields.io/docker/pulls/eduard256/strix?style=flat-square&logo=docker&logoColor=white&label=pulls" alt="Docker Pulls"></a>
<a href="https://github.com/eduard256/Strix/releases"><img src="https://img.shields.io/github/downloads/eduard256/Strix/total?color=blue&style=flat-square&logo=github" alt="GitHub Downloads"></a>
<a href="https://github.com/eduard256/Strix/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square" alt="License"></a>
</p>
## Spent 2 years googling URL for your Chinese camera?
Camera stream discovery and Frigate config generator.
**Strix finds working streams automatically. In 30 seconds.**
- **67,288** camera models
- **3,636** brands (from Hikvision to AliExpress no-name)
- **102,787** URL patterns (RTSP, HTTP, MJPEG, JPEG, BUBBLE)
![Demo](assets/main.gif)
- 3,600+ camera brands with 100,000+ [URL patterns](#streams) in SQLite database
- automatic device [probing](#probe) in 100ms: ports, ARP/OUI, mDNS/HomeKit, HTTP
- 20 parallel workers [test every URL](#testing) with live screenshots
- supports [RTSP, HTTP, RTMP, Bubble, DVRIP](#supported-protocols) and more
- ready [Frigate config](#config-generation) with smart merge into existing setup
- auto-discovery of Frigate and [go2rtc](https://github.com/AlexxIT/go2rtc) on local network
- zero-dependency static [binary](#binary) for Linux amd64/arm64
- can be used as [standalone app](#binary), [Docker](#docker), or [Home Assistant add-on](#home-assistant-add-on)
---
## Your Problem?
<a href="https://youtu.be/JgVWsl4NApE">
<img src="https://github.com/eduard256/Strix/releases/download/v2.0.0/demo.gif" width="100%">
</a>
- ❌ Bought ZOSI NVR, zero documentation
- ❌ Camera has no RTSP, only weird JPEG snapshots
- ❌ Frigate eating 70% CPU
- ❌ Config breaks after adding each camera
- ❌ Don't understand Frigate syntax
<p align="center">
<a href="https://gostrix.github.io/demo.html"><b>Live Demo</b></a>
&nbsp;&bull;&nbsp;
<a href="https://gostrix.github.io/"><b>Supported Cameras</b></a>
&nbsp;&bull;&nbsp;
<a href="https://youtu.be/JgVWsl4NApE"><b>Video</b></a>
&nbsp;&bull;&nbsp;
<a href="DEVELOPERS.md"><b>API Docs</b></a>
</p>
## Solution
## Install
- ✅ **Auto-discovery** - tests 102,787 URL variations in parallel
- ✅ **Any protocol** - No RTSP? Finds HTTP MJPEG
- ✅ **Config generation** - ready Frigate.yml in 2 minutes
- ✅ **Sub/Main streams** - CPU from 30% → 8%
- ✅ **Smart merging** - adds camera to existing config with 500+ cameras
---
## 🚀 Installation (One Command)
### Ubuntu / Debian
Any Linux or Proxmox, one command:
```bash
sudo apt update && command -v docker >/dev/null 2>&1 || curl -fsSL https://get.docker.com | sudo sh && docker run -d --name strix --network host --restart unless-stopped eduard256/strix:latest
bash <(curl -fsSL https://raw.githubusercontent.com/eduard256/Strix/main/install.sh)
```
Open **http://YOUR_SERVER_IP:4567**
Run as root (or with `sudo`). Interactive installer detects your system (Linux / Proxmox) and guides you through setup.
Open `http://YOUR_IP:4567`
## How it works
<a id="probe"></a>
Enter camera IP. Strix probes the device - open ports, MAC vendor, mDNS, HTTP server.
![](https://github.com/eduard256/Strix/releases/download/v2.0.0/01-enter-ip.png)
<a id="search"></a>
Search camera model in database. Enter credentials if needed.
![](https://github.com/eduard256/Strix/releases/download/v2.0.0/02-camera-config.png)
<a id="streams"></a>
Strix builds all possible stream URLs from database patterns.
![](https://github.com/eduard256/Strix/releases/download/v2.0.0/03-stream-urls.png)
<a id="testing"></a>
20 parallel workers test every URL. Live screenshots, codecs, resolution, latency.
![](https://github.com/eduard256/Strix/releases/download/v2.0.0/04-testing.png)
Pick main and sub streams from results.
![](https://github.com/eduard256/Strix/releases/download/v2.0.0/05-results.png)
<a id="config-generation"></a>
Generate ready Frigate config. Copy, download, or save directly to Frigate.
![](https://github.com/eduard256/Strix/releases/download/v2.0.0/06-frigate-config.png)
Camera works in Frigate. Done.
![](https://github.com/eduard256/Strix/releases/download/v2.0.0/07-frigate-result.png)
## Other install methods
### Docker
```bash
docker run -d --name strix --network host --restart unless-stopped eduard256/strix:latest
```
### Docker Compose
Strix only:
```bash
sudo apt update && command -v docker >/dev/null 2>&1 || curl -fsSL https://get.docker.com | sudo sh && command -v docker-compose >/dev/null 2>&1 || { sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose; } && curl -fsSL https://raw.githubusercontent.com/eduard256/Strix/main/docker-compose.yml -o docker-compose.yml && docker-compose up -d
curl -O https://raw.githubusercontent.com/eduard256/Strix/main/docker-compose.yml
docker compose up -d
```
Strix + [Frigate](https://github.com/blakeblackshear/frigate):
```bash
curl -O https://raw.githubusercontent.com/eduard256/Strix/main/docker-compose.frigate.yml
docker compose -f docker-compose.frigate.yml up -d
```
Strix + [go2rtc](https://github.com/AlexxIT/go2rtc):
```bash
curl -O https://raw.githubusercontent.com/eduard256/Strix/main/docker-compose.go2rtc.yml
docker compose -f docker-compose.go2rtc.yml up -d
```
### Home Assistant Add-on
**Installation:**
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**
1. Go to **Settings****Add-ons** → **Add-on Store**
2. Click **⋮** (top right) → **Repositories**
3. Add: `https://github.com/eduard256/hassio-strix`
4. Find **"Strix"** in store
5. Click **Install**
6. Enable **"Start on boot"** and **"Show in sidebar"**
7. Click **Start**
### Binary
---
## How to Use
### Step 1: Open Web Interface
```
http://YOUR_SERVER_IP:4567
```
### Step 2: Enter Camera Details
- **IP Address**: `192.168.1.100`
- **Username**: `admin` (if required)
- **Password**: your camera password
- **Model**: optional, improves accuracy
### Step 3: Discover Streams
Click **"Discover Streams"**
Watch real-time progress:
- Which URL is being tested
- How many tested
- Found streams appear instantly
Wait 30-60 seconds.
### Step 4: Choose Stream
Strix shows details for each stream:
| Stream | Details |
|--------|---------|
| **Protocol** | RTSP, HTTP, MJPEG, JPEG |
| **Resolution** | 1920x1080, 640x480 |
| **FPS** | 25, 15, 10 |
| **Codec** | H264, H265, MJPEG |
| **Audio** | Yes / No |
### Step 5: Generate Frigate Config
Click **"Use Stream"** → **"Generate Frigate Config"**
You get ready config:
```yaml
go2rtc:
streams:
'192_168_1_100_main':
- http://admin:pass@192.168.1.100:8000/video.mjpg
'192_168_1_100_sub':
- http://admin:pass@192.168.1.100:8000/video2.mjpg
cameras:
camera_192_168_1_100:
ffmpeg:
inputs:
- path: rtsp://127.0.0.1:8554/192_168_1_100_sub
roles: [detect] # CPU 8% instead of 70%
- path: rtsp://127.0.0.1:8554/192_168_1_100_main
roles: [record] # HD recording
objects:
track: [person, car, cat, dog]
record:
enabled: true
```
**Smart Merging:**
- Paste your existing `frigate.yml` with 500 cameras
- Strix adds camera #501 correctly
- Doesn't break structure
- Preserves all settings
### Step 6: Add to Frigate
Copy config → Paste to `frigate.yml` → Restart Frigate
**Done!**
---
## Features
### Exotic Camera Support
90% of Chinese cameras don't have RTSP. Strix supports everything:
- **HTTP MJPEG** - most old cameras
- **JPEG snapshots** - auto-converted to stream via FFmpeg
- **RTSP** - if available
- **HTTP-FLV** - some Chinese brands
- **BUBBLE** - proprietary Chinese NVR/DVR protocol
- **ONVIF** - auto-discovery
### Camera Database
**67,288 models from 3,636 brands:**
- **Known brands**: Hikvision, Dahua, Axis, Foscam, TP-Link
- **Chinese no-names**: ZOSI, Escam, Sricam, Wanscam, Besder
- **AliExpress junk**: cameras without name, OEM models
- **Old systems**: NVR/DVR with proprietary protocols
### Discovery Methods
Strix tries all methods in parallel:
**1. ONVIF** (30% success rate)
- Asks camera directly for stream URLs
- Works for ONVIF-compatible cameras
**2. Database Lookup** (60% success rate)
- 67,288 models with known working URLs
- Brand and model-specific patterns
**3. Popular Patterns** (90% success rate)
- 206 most common URL paths
- Works even for unknown cameras
**Result: Finds stream for 95% of cameras**
### Frigate Config Generation
**What you get:**
✅ **Main/Sub streams**
- Main (HD) for recording
- Sub (low res) for object detection
- CPU usage reduced 5-10x
✅ **Ready go2rtc config**
- Stream multiplexing
- Protocol conversion
- JPEG → RTSP via FFmpeg
✅ **Smart config merging**
- Add to existing config
- Preserve structure
- No manual YAML editing
✅ **Pre-configured detection**
- person, car, cat, dog
- Ready motion recording
- 7 days retention
### Speed
- Tests **20 URLs in parallel**
- Average discovery time: **30-60 seconds**
- Complex cameras: **2-3 minutes**
- Real-time progress updates via SSE
---
## Advanced Configuration
### Docker Environment Variables
```yaml
environment:
- STRIX_API_LISTEN=:8080 # Custom port
- STRIX_LOG_LEVEL=debug # Detailed logs
- STRIX_LOG_FORMAT=json # JSON logging
```
### Config File
Create `strix.yaml`:
```yaml
api:
listen: ":8080"
```
Example: [strix.yaml.example](strix.yaml.example)
### Discovery Parameters
In web UI under **Advanced**:
- **Channel** - for NVR systems (usually 0)
- **Timeout** - max discovery time (default: 240s)
- **Max Streams** - stop after N streams (default: 10)
---
## FAQ
### No streams found?
**Check network:**
```bash
ping 192.168.1.100
```
Camera must be reachable.
**Verify credentials:**
- Username/password correct?
- Try without credentials (some cameras are open)
**Try without model:**
- Strix will run ONVIF + 206 popular patterns
- Works for cameras not in database
### Camera not in database?
**No problem.**
Strix will still find stream via:
1. ONVIF (if supported)
2. 206 popular URL patterns
3. Common ports and paths
4. HTTP MJPEG on various ports
5. JPEG snapshot endpoints
**Help the project:**
- Found working stream? [Create Issue](https://github.com/eduard256/Strix/issues)
- Share model and URL
- We'll add to database
### Found only JPEG snapshots?
**Normal for old cameras.**
Strix auto-converts JPEG to stream via FFmpeg:
```yaml
go2rtc:
streams:
camera_main:
- exec:ffmpeg -loop 1 -framerate 10 -i http://192.168.1.100/snapshot.jpg -c:v libx264 -f rtsp {output}
```
Frigate gets normal 10 FPS stream.
### Stream found but doesn't work in Frigate?
**Try another stream:**
- Strix usually finds 3-10 variants
- Some may need special FFmpeg parameters
**Use sub stream:**
- For object detection
- Less CPU load
- Better performance
### How does config generation work?
**For new config:**
- Strix creates complete `frigate.yml` from scratch
- Includes go2rtc, camera, object detection
**For existing config:**
- Paste your current `frigate.yml`
- Strix adds new camera
- Preserves all existing cameras
- Doesn't break structure
**Main/Sub streams:**
- Main (HD) - for recording
- Sub (low res) - for detection
- CPU savings 5-10x
### Is it safe to enter passwords?
**Yes.**
- Strix runs locally on your network
- Nothing sent to external servers
- Passwords not saved
- Open source - check the code yourself
### Works offline?
**Yes.**
- Database embedded in Docker image
- Internet only needed to download image
- Runs offline after that
---
## API Reference
REST API available for automation:
### Health Check
Download from [GitHub Releases](https://github.com/eduard256/Strix/releases). No dependencies except `ffmpeg` for screenshot conversion.
```bash
GET /api/v1/health
chmod +x strix-linux-amd64
STRIX_LISTEN=:4567 ./strix-linux-amd64
```
### Search Cameras
## Supported protocols
```bash
POST /api/v1/cameras/search
| 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 |
| HomeKit | 51826 | Apple HomeKit cameras via HAP |
{
"query": "hikvision",
"limit": 10
}
```
## Configuration
### Discover Streams (SSE)
| 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` |
```bash
POST /api/v1/streams/discover
## Camera database
{
"target": "192.168.1.100",
"username": "admin",
"password": "12345",
"model": "DS-2CD2xxx",
"timeout": 240,
"max_streams": 10
}
```
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.
Returns Server-Sent Events with real-time progress.
[Browse supported cameras](https://gostrix.github.io/) - search by brand or model to check if your camera is in the database.
**Full API documentation:** [DOCKER.md](DOCKER.md)
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
---
Camera not in the database? [Add it here](https://gostrix.github.io/#/contribute).
## Technical Details
**Developers:** integrate [Strix HTTP API](DEVELOPERS.md) into your smart home platform.
### Architecture
- **Language:** Go 1.24
- **Database:** 3,636 JSON files
- **Image size:** 80-90 MB (Alpine Linux)
- **Dependencies:** FFmpeg/FFprobe for validation
- **Concurrency:** Worker pool (20 parallel tests)
- **Real-time:** Server-Sent Events (SSE)
### Build from Source
```bash
git clone https://github.com/eduard256/Strix
cd Strix
make build
./bin/strix
```
**Requirements:**
- Go 1.21+
- FFprobe (optional, for stream validation)
### Docker Platforms
- linux/amd64
- linux/arm64
Auto-built and published to Docker Hub on every push to `main`.
---
## Use Cases
### Home Automation
- Add cheap cameras to Home Assistant
- Integrate with Frigate NVR
- Object detection with low CPU
- Motion recording
### Security Systems
- Discover streams in old NVR systems
- Find backup cameras without docs
- Migrate from proprietary DVR to Frigate
- Reduce hardware requirements
### IP Camera Testing
- Test cameras before deployment
- Verify stream quality
- Find optimal resolution/FPS
- Check codec compatibility
---
## Troubleshooting
### Frigate still eating CPU?
**Use sub stream:**
1. Find both main and sub streams with Strix
2. Generate config with both
3. Sub for detect, main for record
4. CPU drops 5-10x
**Example:**
```yaml
inputs:
- path: rtsp://127.0.0.1:8554/camera_sub # 640x480 for detect
roles: [detect]
- path: rtsp://127.0.0.1:8554/camera_main # 1920x1080 for record
roles: [record]
```
### Can't find specific stream quality?
**In web UI:**
- Strix shows all found streams
- Filter by resolution
- Choose optimal FPS
- Select codec (H264 recommended for Frigate)
### Stream works but no audio in Frigate?
**Check Strix stream details:**
- "Has Audio" field shows if audio present
- Some cameras have video-only streams
- Try different stream URL from Strix results
### Discovery takes too long?
**Reduce search scope:**
- Specify exact camera model (faster database lookup)
- Lower "Max Streams" (stops after N found)
- Reduce timeout (default 240s)
**In Advanced settings:**
```
Max Streams: 5 (instead of 10)
Timeout: 120 (instead of 240)
```
---
## Contributing
### Add Your Camera
Found working stream for camera not in database?
1. [Create Issue](https://github.com/eduard256/Strix/issues)
2. Provide:
- Camera brand and model
- Working URL pattern
- Protocol (RTSP/HTTP/etc)
3. We'll add to database
### Report Bugs
- [GitHub Issues](https://github.com/eduard256/Strix/issues)
- Include logs (set `STRIX_LOG_LEVEL=debug`)
- Camera model and IP (if possible)
### Feature Requests
- [GitHub Discussions](https://github.com/eduard256/Strix/discussions)
- Describe use case
- Explain expected behavior
---
## Credits
- **Camera database:** [ispyconnect.com](https://www.ispyconnect.com)
- **Inspiration:** [go2rtc](https://github.com/AlexxIT/go2rtc) by AlexxIT
- **Community:** Home Assistant, Frigate NVR users
---
## License
MIT License - use commercially, modify, distribute freely.
See [LICENSE](LICENSE) file for details.
---
## Support
- **Issues:** [GitHub Issues](https://github.com/eduard256/Strix/issues)
- **Discussions:** [GitHub Discussions](https://github.com/eduard256/Strix/discussions)
- **Docker:** [Docker Hub](https://hub.docker.com/r/eduard256/strix)
---
**Made for people tired of cameras without documentation**
*Tested on Chinese AliExpress junk that finally works now.*
**Testing:** [StrixCamFake](https://github.com/eduard256/StrixCamFake) - IP camera emulator for development and testing. [StrixAHKCamFake](https://github.com/eduard256/StrixAHKCamFake) - Apple HomeKit camera emulator.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

View file

@ -1,15 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="512" width="512" viewBox="0 0 512.001 512.001">
<g>
<path style="fill:#7E57C2;" d="M124.477,378.183L9.347,495.779c21.628,21.628,56.695,21.628,78.324,0L119,464.45 c21.628,21.628,56.696,21.628,78.324,0l28.375-28.375C187.373,426.203,151.825,405.106,124.477,378.183z"/>
<path style="fill:#7E57C2;" d="M447.27,55.383h-55.383V177.22c0.002-40.997,22.277-76.788,55.383-95.939 c16.293-9.425,35.207-14.822,55.383-14.822c0-6.982,0-11.077,0-11.077V0C472.065,0,447.27,24.796,447.27,55.383z"/>
</g>
<path style="fill:#9575CD;" d="M336.504,55.383C336.504,24.796,311.708,0,281.121,0v66.46c20.176,0,39.091,5.397,55.383,14.822 c33.107,19.153,55.383,54.946,55.383,95.945V55.383H336.504z"/>
<path style="fill:#E8E0F5;" d="M391.887,209.772v-27.116c0-3.312,0-5.432,0-5.432c0-40.997-22.276-76.791-55.383-95.942 c-16.293-9.425-35.207-14.822-55.383-14.822v155.073C311.213,191.443,357.554,187.532,391.887,209.772z M314.351,143.996 c0-12.234,9.918-22.153,22.153-22.153s22.153,9.919,22.153,22.153c0,12.235-9.918,22.153-22.153,22.153 S314.351,156.231,314.351,143.996z"/>
<path style="fill:#D1C4E9;" d="M391.887,177.221v32.551c5.151,3.336,10.037,7.246,14.55,11.76h96.216V66.46 c-20.176,0-39.091,5.397-55.383,14.822C414.164,100.434,391.888,136.225,391.887,177.221z M469.423,143.996 c0,12.235-9.918,22.153-22.153,22.153s-22.153-9.918-22.153-22.153c0-12.234,9.918-22.153,22.153-22.153 C459.504,121.843,469.423,131.762,469.423,143.996z"/>
<path style="fill:#9575CD;" d="M281.121,221.532l-10.2,10.2L281.121,221.532z"/>
<path style="fill:#B39DDB;" d="M406.438,221.533c34.606,34.606,34.606,90.712,0,125.319c-69.21,69.21-181.422,69.21-250.633,0.002 l-31.329,31.33c27.348,26.923,62.896,48.02,101.221,57.892c17.714,4.562,36.285,6.989,55.423,6.989 c122.349,0,221.532-99.182,221.532-221.531C502.653,221.533,406.437,221.532,406.438,221.533z"/>
<path style="fill:#9575CD;" d="M281.121,221.532l125.318,125.319c34.606-34.606,34.606-90.713,0-125.319 c-4.515-4.514-9.401-8.425-14.551-11.761C357.554,187.532,311.213,191.443,281.121,221.532z"/>
<path style="fill:#7E57C2;" d="M406.438,346.851L281.12,221.533l-10.199,10.2L155.802,346.851 C225.017,416.062,337.228,416.061,406.438,346.851z"/>
<circle style="fill:#9575CD;" cx="336.507" cy="143.996" r="22.153"/>
<circle style="fill:#7E57C2;" cx="447.274" cy="143.996" r="22.153"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

View file

@ -1,202 +0,0 @@
package main
import (
"context"
"fmt"
"log/slog"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/eduard256/Strix/internal/api"
"github.com/eduard256/Strix/internal/config"
"github.com/eduard256/Strix/internal/utils/logger"
"github.com/eduard256/Strix/webui"
"github.com/go-chi/chi/v5"
)
// Version is set at build time via ldflags:
//
// go build -ldflags="-X main.Version=1.0.10" ./cmd/strix
var Version = "dev"
const Banner = `
Smart IP Camera Stream Discovery System
Version: %s
`
func main() {
// Print banner
fmt.Printf(Banner, Version)
fmt.Println()
// Load configuration
cfg := config.Load()
cfg.Version = Version
// Setup logger
slogger := cfg.SetupLogger()
slog.SetDefault(slogger)
// Create adapter for our interface
log := logger.NewAdapter(slogger)
log.Info("starting Strix",
slog.String("version", Version),
slog.String("go_version", os.Getenv("GO_VERSION")),
slog.String("listen", cfg.Server.Listen),
)
// Check if ffprobe is available
if err := checkFFProbe(); err != nil {
log.Warn("ffprobe not found, stream validation will be limited", slog.String("error", err.Error()))
}
// Create API server
apiServer, err := api.NewServer(cfg, log)
if err != nil {
log.Error("failed to create API server", err)
os.Exit(1)
}
// Create Web UI server
webuiServer := webui.NewServer(log)
// Create unified router combining API and WebUI
unifiedRouter := chi.NewRouter()
// Mount API routes at /api/v1/*
unifiedRouter.Mount("/api/v1", apiServer.GetRouter())
// Mount WebUI routes at /* (serves everything else including root)
unifiedRouter.Mount("/", webuiServer.GetRouter())
// Create unified HTTP server
httpServer := &http.Server{
Addr: cfg.Server.Listen,
Handler: unifiedRouter,
ReadTimeout: cfg.Server.ReadTimeout,
WriteTimeout: cfg.Server.WriteTimeout,
IdleTimeout: 120 * time.Second,
}
// Start server in goroutine
go func() {
log.Info("server starting",
slog.String("address", httpServer.Addr),
slog.String("api_version", "v1"),
)
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Error("server failed", err)
os.Exit(1)
}
}()
// Print endpoints
printEndpoints(cfg.Server.Listen)
// Wait for interrupt signal
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
<-quit
log.Info("shutting down server...")
// Graceful shutdown with timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Shutdown server
if err := httpServer.Shutdown(ctx); err != nil {
log.Error("server shutdown failed", err)
os.Exit(1)
}
log.Info("server stopped gracefully")
}
// checkFFProbe checks if ffprobe is available
func checkFFProbe() error {
// Try to execute ffprobe -version
cmd := os.Getenv("PATH")
if cmd == "" {
return fmt.Errorf("PATH environment variable not set")
}
// For now, just check if ffprobe exists in common locations
locations := []string{
"/usr/bin/ffprobe",
"/usr/local/bin/ffprobe",
"/opt/homebrew/bin/ffprobe",
}
for _, loc := range locations {
if _, err := os.Stat(loc); err == nil {
return nil
}
}
return fmt.Errorf("ffprobe not found in common locations")
}
// getLocalIP returns the local IP address of the machine
func getLocalIP() string {
addrs, err := net.InterfaceAddrs()
if err != nil {
return "localhost"
}
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
return ipnet.IP.String()
}
}
}
return "localhost"
}
// printEndpoints prints available endpoints
func printEndpoints(listen string) {
// Extract port from listen address
port := "4567"
if len(listen) > 0 {
if listen[0] == ':' {
port = listen[1:]
} else {
// Parse host:port format
for i := len(listen) - 1; i >= 0; i-- {
if listen[i] == ':' {
port = listen[i+1:]
break
}
}
}
}
// Get local IP
localIP := getLocalIP()
url := fmt.Sprintf("http://%s:%s", localIP, port)
// ANSI escape codes for clickable link (OSC 8 hyperlink)
clickableURL := fmt.Sprintf("\033]8;;%s\033\\%s\033]8;;\033\\", url, url)
fmt.Println("\n🌐 Web Interface:")
fmt.Println("────────────────────────────────────────────────")
fmt.Printf(" Open in browser: %s\n", clickableURL)
fmt.Println("────────────────────────────────────────────────")
fmt.Println("\n📚 Documentation: https://github.com/eduard256/Strix")
}

View file

@ -1,517 +0,0 @@
# 📹 IoT2mqtt Camera Database Format Specification
**Version:** 1.0.0
**Last Updated:** 2025-10-17
---
## 🎯 Overview
The camera database is a collection of JSON files containing URL patterns and connection details for IP cameras from various manufacturers. This format is designed to be:
- **Universal**: Works with any IP camera brand
- **Extensible**: Easy to add new models and protocols
- **Human-readable**: Simple JSON structure
- **Parseable**: Straightforward for automated tools
---
## 📁 Directory Structure
```
connectors/cameras/data/brands/
├── index.json # Master list of all brands
├── d-link.json # D-Link camera models
├── hikvision.json # Hikvision camera models
├── dahua.json # Dahua camera models
├── axis.json # Axis camera models
└── ... # Additional brands
```
---
## 📋 File Formats
### 1. **index.json** - Brand Directory
Lists all available camera brands with metadata.
```json
[
{
"value": "d-link",
"label": "D-Link",
"models_count": 250,
"entries_count": 85,
"logo": "/assets/brands/d-link.svg"
},
{
"value": "hikvision",
"label": "Hikvision",
"models_count": 320,
"entries_count": 95,
"logo": "/assets/brands/hikvision.svg"
}
]
```
**Fields:**
- `value` (string, required): Brand identifier (lowercase, URL-safe)
- `label` (string, required): Display name
- `models_count` (integer): Total number of camera models
- `entries_count` (integer): Number of URL pattern entries
- `logo` (string, optional): Path to brand logo
---
### 2. **{brand}.json** - Brand Camera Database
Contains all URL patterns and connection details for a specific brand.
```json
{
"brand": "D-Link",
"brand_id": "d-link",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"website": "https://www.dlink.com",
"entries": [
{
"models": ["DCS-930L", "DCS-930LB", "DCS-930LB1"],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "live3.sdp",
"notes": "Main HD stream"
},
{
"models": ["DCS-930L", "DCS-932L"],
"type": "MJPEG",
"protocol": "http",
"port": 80,
"url": "video.cgi?resolution=VGA",
"notes": "Medium quality fallback"
}
]
}
```
**Root Fields:**
- `brand` (string, required): Brand display name
- `brand_id` (string, required): Brand identifier (must match filename)
- `last_updated` (string, ISO 8601 date): When database was last updated
- `source` (string): Where the data came from (e.g., "ispyconnect.com")
- `website` (string, optional): Manufacturer's official website
- `entries` (array, required): List of URL pattern entries
---
### 3. **Entry Object** - URL Pattern Entry
Each entry represents a specific URL pattern that works for one or more camera models.
```json
{
"models": ["DCS-930L", "DCS-930LB", "DCS-930LB1"],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "live3.sdp",
"auth_required": true,
"notes": "Main HD stream with audio"
}
```
**Fields:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `models` | array[string] | ✅ Yes | List of camera model names/numbers this URL works for |
| `type` | string | ✅ Yes | Stream type: `FFMPEG`, `MJPEG`, `JPEG`, `VLC`, `H264` |
| `protocol` | string | ✅ Yes | Protocol: `rtsp`, `http`, `https` |
| `port` | integer | ✅ Yes | Port number (554 for RTSP, 80/443 for HTTP) |
| `url` | string | ✅ Yes | URL path (without protocol/host/port) |
| `auth_required` | boolean | No | Whether authentication is needed (default: true) |
| `notes` | string | No | Human-readable description |
---
## 🔧 URL Template Variables
URL paths support the following template variables:
| Variable | Description | Example |
|----------|-------------|---------|
| `{username}` | Camera username | `admin` |
| `{password}` | Camera password | `12345` |
| `{ip}` | Camera IP address | `192.168.1.100` |
| `{port}` | Port number | `554` |
| `{channel}` | Camera channel (for DVRs) | `1` |
| `{width}` | Video width | `1920` |
| `{height}` | Video height | `1080` |
**Example:**
```
Template: rtsp://{username}:{password}@{ip}:{port}/live3.sdp
Result: rtsp://admin:12345@192.168.1.100:554/live3.sdp
```
---
## 📊 Stream Types
### FFMPEG (Recommended)
- **Protocol**: RTSP, HTTP
- **Format**: H.264, H.265
- **Use case**: High-quality video with audio
- **Priority**: 🥇 First choice
### MJPEG
- **Protocol**: HTTP
- **Format**: Motion JPEG
- **Use case**: Medium quality, wide compatibility
- **Priority**: 🥈 Second choice
### JPEG
- **Protocol**: HTTP
- **Format**: Still images
- **Use case**: Snapshot-only cameras or fallback
- **Priority**: 🥉 Last resort
### VLC
- **Protocol**: RTSP, HTTP
- **Format**: Various (VLC-specific)
- **Use case**: Compatibility with VLC player
---
## 🎯 Priority Order for Testing
When testing multiple URLs for a camera model, use this priority:
1. **RTSP (type="FFMPEG")** - Best quality, supports audio
2. **HTTP MJPEG** - Good compatibility
3. **HTTP JPEG** - Snapshot fallback
**Example:**
```python
def get_urls_for_model(brand_data, model_name):
entries = [e for e in brand_data["entries"] if model_name in e["models"]]
# Sort by priority
priority = {"FFMPEG": 1, "MJPEG": 2, "JPEG": 3, "VLC": 4}
entries.sort(key=lambda e: priority.get(e["type"], 99))
return entries
```
---
## 🔍 Search and Lookup
### By Brand
```python
# Load brand file
with open(f"data/brands/{brand_id}.json") as f:
brand_data = json.load(f)
```
### By Model
```python
# Find all entries for a specific model
def find_model_entries(brand_data, model_name):
return [
entry for entry in brand_data["entries"]
if model_name.upper() in [m.upper() for m in entry["models"]]
]
```
### Fuzzy Search
```python
# Search across all models (case-insensitive, partial match)
def search_model(brand_data, query):
query = query.upper()
results = []
for entry in brand_data["entries"]:
if any(query in model.upper() for model in entry["models"]):
results.append(entry)
return results
```
---
## 🌐 URL Construction
### RTSP URL
```python
def build_rtsp_url(entry, ip, username, password):
return f"rtsp://{username}:{password}@{ip}:{entry['port']}/{entry['url']}"
# Example:
# rtsp://admin:12345@192.168.1.100:554/live3.sdp
```
### HTTP URL
```python
def build_http_url(entry, ip, username, password):
protocol = entry["protocol"] # "http" or "https"
return f"{protocol}://{username}:{password}@{ip}:{entry['port']}/{entry['url']}"
# Example:
# http://admin:12345@192.168.1.100:80/video.cgi?resolution=VGA
```
### With Template Variables
```python
def build_url(entry, ip, username, password, **kwargs):
url_path = entry["url"]
# Replace template variables
replacements = {
"username": username,
"password": password,
"ip": ip,
"port": str(entry["port"]),
**kwargs # Additional variables (channel, width, height, etc.)
}
for key, value in replacements.items():
url_path = url_path.replace(f"{{{key}}}", value)
# Build full URL
if entry["protocol"] == "rtsp":
return f"rtsp://{username}:{password}@{ip}:{entry['port']}/{url_path}"
else:
return f"{entry['protocol']}://{username}:{password}@{ip}:{entry['port']}/{url_path}"
```
---
## ✅ Validation Rules
### Entry Validation
```python
def validate_entry(entry):
# Required fields
assert "models" in entry and isinstance(entry["models"], list)
assert len(entry["models"]) > 0
assert "type" in entry and entry["type"] in ["FFMPEG", "MJPEG", "JPEG", "VLC", "H264"]
assert "protocol" in entry and entry["protocol"] in ["rtsp", "http", "https"]
assert "port" in entry and isinstance(entry["port"], int)
assert "url" in entry and isinstance(entry["url"], str)
# Port ranges
assert 1 <= entry["port"] <= 65535
# Common ports check
if entry["protocol"] == "rtsp":
assert entry["port"] in [554, 8554, 7447] # Common RTSP ports
elif entry["protocol"] == "http":
assert entry["port"] in [80, 8080, 8000, 8081] # Common HTTP ports
```
---
## 📝 Naming Conventions
### Brand IDs
- **Format**: lowercase, kebab-case
- **Examples**: `d-link`, `hikvision`, `tp-link`
- **Invalid**: `D-Link`, `D_Link`, `dlink`
### Model Names
- **Format**: UPPERCASE with hyphens (as manufacturer specifies)
- **Examples**: `DCS-930L`, `DS-2CD2142FWD-I`, `IPC-HFW1230S`
- **Keep original**: Don't normalize or change manufacturer names
### Protocol Values
- `rtsp` - RTSP protocol
- `http` - HTTP protocol
- `https` - HTTPS protocol
- **Invalid**: `RTSP`, `Http`, `tcp`
### Type Values
- `FFMPEG` - H.264/H.265 streams (RTSP or HTTP)
- `MJPEG` - Motion JPEG streams
- `JPEG` - Still image snapshots
- `VLC` - VLC-specific streams
---
## 🔄 Versioning and Updates
### Version Format
```json
{
"brand": "D-Link",
"brand_id": "d-link",
"database_version": "1.2.0",
"last_updated": "2025-10-17T14:30:00Z",
"entries": [...]
}
```
### Update Policy
- **Patch** (1.0.x): Add new models to existing entries
- **Minor** (1.x.0): Add new URL patterns/entries
- **Major** (x.0.0): Breaking changes to structure
---
## 📚 Examples
### Complete Brand File Example
**foscam.json:**
```json
{
"brand": "Foscam",
"brand_id": "foscam",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"website": "https://www.foscam.com",
"entries": [
{
"models": ["FI9821P", "FI9826P", "FI9821W"],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "videoMain",
"notes": "Main stream HD"
},
{
"models": ["FI9821P", "FI9826P"],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "videoSub",
"notes": "Sub stream SD"
},
{
"models": ["FI9821P", "FI9826P", "FI9821W", "C1"],
"type": "MJPEG",
"protocol": "http",
"port": 88,
"url": "cgi-bin/CGIStream.cgi?cmd=GetMJStream&usr={username}&pwd={password}",
"notes": "MJPEG fallback"
},
{
"models": ["FI9821P", "C1", "C2"],
"type": "JPEG",
"protocol": "http",
"port": 88,
"url": "cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr={username}&pwd={password}",
"notes": "Snapshot"
}
]
}
```
---
## 🛠️ Tools and Scripts
### Parser Script (Python)
```python
# scripts/parse_ispyconnect.py
import requests
from bs4 import BeautifulSoup
import json
def parse_brand_page(brand_id):
url = f"https://www.ispyconnect.com/camera/{brand_id}"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
table = soup.find('table', class_='table-striped')
entries = []
for row in table.find_all('tr')[1:]: # Skip header
cols = row.find_all('td')
if len(cols) < 4:
continue
models_text = cols[0].get_text()
models = [m.strip() for m in models_text.split(',')]
entry = {
"models": models,
"type": cols[1].get_text(strip=True),
"protocol": cols[2].get_text(strip=True).replace('://', ''),
"port": int(row.get('data-port', 0)),
"url": cols[3].get_text(strip=True)
}
entries.append(entry)
return {
"brand": brand_id.title(),
"brand_id": brand_id,
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": entries
}
```
### Validator Script
```python
# scripts/validate_database.py
import json
import os
def validate_brand_file(filepath):
with open(filepath) as f:
data = json.load(f)
# Check required fields
assert "brand" in data
assert "brand_id" in data
assert "entries" in data
# Validate each entry
for i, entry in enumerate(data["entries"]):
assert "models" in entry, f"Entry {i} missing models"
assert "type" in entry, f"Entry {i} missing type"
assert "protocol" in entry, f"Entry {i} missing protocol"
assert "port" in entry, f"Entry {i} missing port"
assert "url" in entry, f"Entry {i} missing url"
print(f"✅ {filepath} is valid")
# Run validation
for file in os.listdir('data/brands/'):
if file.endswith('.json') and file != 'index.json':
validate_brand_file(f'data/brands/{file}')
```
---
## 📄 License and Attribution
- **Source**: ispyconnect.com camera database
- **Usage**: Free for IoT2mqtt project
- **Attribution**: Must credit ispyconnect.com as data source
- **Updates**: Community-contributed updates welcome
---
## 🤝 Contributing
To add or update camera models:
1. Follow the JSON format specification
2. Validate using `scripts/validate_database.py`
3. Test URLs with real cameras when possible
4. Submit pull request with changes
---
## 📞 Support
For questions about the database format:
- GitHub Issues: https://github.com/eduard256/Strix/issues
- Documentation: https://github.com/eduard256/Strix#readme
---
**End of Specification**

View file

@ -1,258 +0,0 @@
{
"brand": "255 Ip Cam",
"brand_id": "255-ip-cam",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"255",
"32X 5MP",
"C6F0SgZ3N0PfL2",
"C6F0SoZ3N0P9L2",
"CF0Sgzonopfl2",
"DENVER IPO-1320MK2",
"DRC6F0SgZ3N0P6L2",
"es cam g02",
"HW0029",
"ICAM",
"IIII-551433-ABEBF",
"IUK 5A1",
"Other",
"phr04k",
"pppp-216658-ecdcb",
"ProeliteIP01axBLK",
"q52-5mp-wh",
"SRICAM",
"tttt-489242-vxvmx",
"xly0144"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/11"
},
{
"models": [
"255",
"ICAM",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg"
},
{
"models": [
"255",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/0"
},
{
"models": [
"3030",
"C6F0SoZ3N0P9L2",
"IIII-259624-EAADF",
"IUK 5A1",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/1"
},
{
"models": [
"4455",
"IPC365"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "ch0_0.h264"
},
{
"models": [
"C9F0SgZ3N0PbL0"
],
"type": "JPEG",
"protocol": "http",
"port": 8082,
"url": "/tmpfs/auto.jpg"
},
{
"models": [
"common"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]*[HEIGHT]"
},
{
"models": [
"H.265"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"icam",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/user=[USERNAME]_password=[PASSWORD]_channel=1_stream=0.sdp"
},
{
"models": [
"ICAM",
"Other",
"PoE"
],
"type": "JPEG",
"protocol": "http",
"port": 5544,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"ip66minicam"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/1/h264major"
},
{
"models": [
"Ipc"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Ipc",
"ip-camera",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/snapshot.jpg"
},
{
"models": [
"IPC-V380-Q79"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/onvif1"
},
{
"models": [
"IUK 5A1",
"Other",
"sricam"
],
"type": "MJPEG",
"protocol": "http",
"port": 81,
"url": "videostream.cgi?rate=0&user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"kiina"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image.jpg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&password=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 10554,
"url": "1/h264major"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "/video.mp4"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=320*240"
},
{
"models": [
"sioplus"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/video1"
},
{
"models": [
"top"
],
"type": "FFMPEG",
"protocol": "http",
"port": 8080,
"url": "/videofeed"
}
]
}

View file

@ -1,54 +0,0 @@
{
"brand": "2n Helios",
"brand_id": "2n-helios",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"IP-CAMERA"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"IP-CAMERA",
"Vario"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/h264_stream"
},
{
"models": [
"IP-CAMERA"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?usr=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"VARIO"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot/view[CHANNEL].jpg"
},
{
"models": [
"VARIO"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
}
]
}

View file

@ -1,44 +0,0 @@
{
"brand": "307 Hi Silicon",
"brand_id": "307-hi-silicon",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"101"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg"
},
{
"models": [
"318e"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "user=[USERNAME]&password=[PASSWORD]&channel=1&stream=0.sdp?"
},
{
"models": [
"HI3516C"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/0"
},
{
"models": [
"HI3518E"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/11"
}
]
}

View file

@ -1,266 +0,0 @@
{
"brand": "360 Eye",
"brand_id": "360-eye",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"1111",
"EC101-B3Y2",
"EC107-B3Y2",
"EC107Y-B3Y10",
"EC38",
"EC73-V13",
"EC76-U15",
"Other",
"v380",
"V380"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor"
},
{
"models": [
"360",
"V380"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/11"
},
{
"models": [
"360"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/0"
},
{
"models": [
"360",
"360eye",
"360Eye",
"360EYE",
"360EYE PRO",
"EC101-X15",
"EC76",
"EC76-U15",
"EC80_V13",
"EC80-X15",
"i360",
"Other",
"v380",
"V380"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "live/ch00_0"
},
{
"models": [
"360",
"360Eye Pro"
],
"type": "VLC",
"protocol": "rtsp",
"port": 1935,
"url": "LowResolutionVideo"
},
{
"models": [
"360eye",
"EC101-X15",
"EC107-B3Y2",
"EC107Y-B3Y10",
"EC73-N13",
"IPC365",
"v380"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=1&subtype=00&authbasic=[AUTH]"
},
{
"models": [
"360EYE",
"360Eye Pro",
"EC101Y-B3Y10",
"IPC365"
],
"type": "VLC",
"protocol": "rtsp",
"port": 5544,
"url": "live_mpeg4.sdp"
},
{
"models": [
"360EYE",
"360EYE PRO",
"EC101-X15",
"EC107-B3Y2",
"EC73-N13",
"EC76",
"EC76-U15",
"eyes",
"IPC365",
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam/realmonitor?channel=[CHANNEL]&subtype=1"
},
{
"models": [
"360EYE EC129-X15",
"EC101-B3Y2",
"EC101-X15",
"EC101Y-B3Y10",
"EC107-X15",
"EC37",
"EC73-N13",
"EC73-V13",
"PW2K2N06E-GTWY"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=0&subtype=1"
},
{
"models": [
"603",
"Other",
"V380"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"E101-B3Y2",
"EC101Y-B3Y10"
],
"type": "VLC",
"protocol": "rtsp",
"port": 1935,
"url": "ch0_0.h264"
},
{
"models": [
"EC101-B3Y2",
"EC107-B3Y2",
"EC76-X15",
"epc101",
"Other",
"v380",
"V380 Wifi IP Cam"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/live/ch00_0"
},
{
"models": [
"EC101-X15",
"EC132-X15",
"EC80-X15"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=8080&subtype=1"
},
{
"models": [
"EC101-X15",
"mv12241966"
],
"type": "FFMPEG",
"protocol": "mms",
"port": 554,
"url": "/img/video.asf"
},
{
"models": [
"EC101-X15",
"PW2L2A06A-GTY"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=1&subtype=1"
},
{
"models": [
"EC107-B3Y2",
"EC73-N13"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/LowResolutionVideo"
},
{
"models": [
"EC107-B3Y2"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/live_mpeg4.sdp"
},
{
"models": [
"EC107-X15",
"EC137-X15",
"EC80-X15",
"XM80-8MP"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/realmonitor?channel=0&stream=0.sdp"
},
{
"models": [
"EC137Y-B3Y2"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/ch0_0.h264"
},
{
"models": [
"SL-CAM",
"V380",
"y335"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/onvif1"
},
{
"models": [
"V380"
],
"type": "VLC",
"protocol": "mms",
"port": 0,
"url": "img/video.asf"
}
]
}

View file

@ -1,151 +0,0 @@
{
"brand": "3com",
"brand_id": "3com",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"EX11402-WIFI",
"Other",
"rc8221",
"XHCI-SE"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=2"
},
{
"models": [
"EX11402-WIFI",
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]*[HEIGHT]"
},
{
"models": [
"EX11402-WIFI",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Ipela"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "goform/video2"
},
{
"models": [
"IPELA",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "mjpeg.cgi?user=[USERNAME]&password=[PASSWORD]&channel=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?usr=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other",
"RC8221"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]&strm=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "jpg/image.jpg?size=3"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/net_jpeg.cgi?ch=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video?submenu=mjpg"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other",
"RC8221"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=3"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "3eyes3",
"brand_id": "3eyes3",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"E-2100M"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/11"
}
]
}

View file

@ -1,474 +0,0 @@
{
"brand": "3g Ipcam",
"brand_id": "3g-ipcam",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"002a",
"720 P IP CAMERA",
"L Series",
"Other",
"SRICAM SP004"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?usr=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"002A",
"IPCAM V380",
"IPC-HFW2231R-ZS-IRE6",
"Other",
"P2P"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"002A",
"720 P IP CAMERA",
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"002A",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"1234",
"C6F0SEZ0N0P0L0",
"C6F0SFZ3NOP5L0",
"C6F0SGZ0N0P3L0",
"C6F0SGZ3N0P6L2",
"C6F0SiZ3N0P0L0",
"C6F0SoZ3N0PcL2",
"C9F0SeZ0N0P4L0",
"C9F0SEZ0N0P4L0",
"C9F0SGZ0N0P2L1",
"C9F0SgZ3NP8L0",
"Chemin",
"F-SERIES",
"Other",
"SRICAM"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/11"
},
{
"models": [
"2016w"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?usr=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"2018",
"F-series",
"P2P"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]*[HEIGHT]"
},
{
"models": [
"3245",
"328",
"3285",
"3289",
"454",
"4556",
"546577",
"720 P IP CAMERA",
"B987w",
"BM16",
"C6F0SeZ0N0P0L0",
"C6F0SfZ0N0P3L0",
"C6F0SfZ3NOP5L0",
"C6F0SgZ0N0P3L0",
"C6F0SgZ3N0P6L2",
"C6F0SIZ3N0P0L0",
"C9F0SgZ0N0P2L1",
"CT0276WHUK",
"Fd7902",
"GGGG-152116-FCEEA",
"L SERIES",
"Other",
"p2p",
"sr1",
"SRICAM SP004"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"355566",
"546577",
"Other",
"X6130"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]&strm=[CHANNEL]"
},
{
"models": [
"3g Ipcam: C6F0SoZ3N0PdL2"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/stream_0"
},
{
"models": [
"3g Ipcam: C6F0SoZ3N0PdL2"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/1/h264major"
},
{
"models": [
"556",
"c6f0SoZ3n0P9L2",
"ipc"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/ch0_0.264"
},
{
"models": [
"590"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "iphone/11?[USERNAME]:[PASSWORD]&"
},
{
"models": [
"720 P IP CAMERA",
"IPC701939"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/onvif1"
},
{
"models": [
"720 P IP CAMERA"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]&strm=2"
},
{
"models": [
"720 P IP CAMERA"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]&strm=0"
},
{
"models": [
"720 P IP CAMERA"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/snapshot.jpg"
},
{
"models": [
"C6F0SEZ0N0P0L0",
"c9F0SeZ0N0P4L0",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
},
{
"models": [
"C6F0SFZ0N0P3L0",
"PPCN060874FEGNW"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=2"
},
{
"models": [
"C6F0SGZ3N0P6L2",
"C9F0SeZ0N0P7L0",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/1"
},
{
"models": [
"C9F0SEZ0N0P7L0"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 10554,
"url": "1/h264major"
},
{
"models": [
"ipc720"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"IP-CAM"
],
"type": "VLC",
"protocol": "mms",
"port": 0,
"url": "img/video.asf"
},
{
"models": [
"IP-CAM"
],
"type": "FFMPEG",
"protocol": "mms",
"port": 554,
"url": "/img/video.asf"
},
{
"models": [
"IPCAM v380",
"IPCAM V380"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "live/ch00_0"
},
{
"models": [
"IPCAM V380",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"IPCAM V380",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 10554,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"IPCAM V380",
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam[CHANNEL]/h264"
},
{
"models": [
"L SERIES",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=11"
},
{
"models": [
"L SERIES",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"NEXHT360"
],
"type": "VLC",
"protocol": "rtsp",
"port": 1935,
"url": "/cam/realmonitor?channel=1&subtype=00&authbasic=[AUTH]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "live?camera=[CHANNEL]&fps=5&quality=75&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=VGA"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=0&user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video?submenu=mjpg"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image.jpg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.mjpg?q=30&fps=33&id=0.5"
},
{
"models": [
"Other",
"P2P"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 10554,
"url": "/tcp/av0_0"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "api/mjpegvideo.cgi?InputNumber=1&StreamNumber=[CHANNEL]"
},
{
"models": [
"rc8025"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=3"
},
{
"models": [
"SCRICAM AP004",
"SRICAM AP006"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
}
]
}

View file

@ -1,64 +0,0 @@
{
"brand": "3r",
"brand_id": "3r",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"Other",
"Prestige DVR",
"PRESTİGE DVR"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "current[CHANNEL].jpg"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam[CHANNEL]/h264"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "ipcam/avc.cgi?audiostream=[CHANNEL]"
},
{
"models": [
"Prestige DVR"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image/[CHANNEL].jpg"
},
{
"models": [
"Prestige DVR"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "/control/faststream.jpg?stream=MxPEG&needlength&fps=6"
}
]
}

View file

@ -1,251 +0,0 @@
{
"brand": "3svision",
"brand_id": "3svision",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"N3011",
"N6078",
"N6079"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/cam1/onvif-h264"
},
{
"models": [
"N3071",
"N6078",
"N9071",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam1/onvif-h264-1"
},
{
"models": [
"N3072",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image.jpg"
},
{
"models": [
"N6013"
],
"type": "MJPEG",
"protocol": "http",
"port": 80,
"url": "/axis-cgi/mjpg/video.cgi"
},
{
"models": [
"N6071",
"N8072",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi"
},
{
"models": [
"N6076"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/11"
},
{
"models": [
"N8072"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image/[CHANNEL].jpg"
},
{
"models": [
"N8072",
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam[CHANNEL]/h264"
},
{
"models": [
"N9073"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi?date=1&clock=1&camera=[CHANNEL]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=2"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/video.jpg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "GetData.cgi"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "cgi-bin/view.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam1/mpeg4"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam2/mpeg4"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam3/mpeg4"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam4/mpeg4"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "current[CHANNEL].jpg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
}
]
}

View file

@ -1,245 +0,0 @@
{
"brand": "3xlogic",
"brand_id": "3xlogic",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"3mp",
"vsx"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/video.h264"
},
{
"models": [
"3mp",
"CMC-3MP-OD-I",
"VSX-2MP-MVD40",
"VX-3P28-OD-I"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Channels/1"
},
{
"models": [
"3mp"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/"
},
{
"models": [
"avtech",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/guest/Video.cgi?media=JPEG&channel=[CHANNEL]"
},
{
"models": [
"AVTECH",
"vsx-2mp-d",
"VX-3PV-B-I",
"VX-4S28-MD-I"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "live/mpeg4"
},
{
"models": [
"Other",
"vsx-2m-d",
"VSX-2MP-MVD40"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "video.h264"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "jpg/1/image.jpg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "cgi-bin/view.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "ch0_0.h264"
},
{
"models": [
"Radio"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=0&user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"rc8025"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=3"
},
{
"models": [
"Vigil Server"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "live?camera=[CHANNEL]&quality=75&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Vigil Server"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "live?camera=[USERNAME]&quality=75&resolution=[PASSWORD]"
},
{
"models": [
"Vigil Server"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "live?camera=[USERNAME]&quality=75&fps=5&resolution=[PASSWORD]"
},
{
"models": [
"Vigil Server"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "live?camera=[CHANNEL]&fps=5&quality=75&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"vsx",
"VX-3P28-MD-IA"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/ch0_0.h264"
},
{
"models": [
"VSX-2MP-MVD40"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "img/video.mjpeg"
},
{
"models": [
"VX-3M-F-AWD",
"VX-3m-OD2-RIAWD"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 555,
"url": "/11"
},
{
"models": [
"VX-3P28-MD-IA"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/stream0"
},
{
"models": [
"VX-4S28-MD-I"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=1&subtype=00&authbasic=[AUTH]"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "4er",
"brand_id": "4er",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/live/av0"
}
]
}

View file

@ -1,85 +0,0 @@
{
"brand": "4mp Ip Camera",
"brand_id": "4mp-ip-camera",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"47680146",
"KEYE",
"Other",
"Security"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/11"
},
{
"models": [
"g-240",
"G42"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"ID002A",
"IPB8224"
],
"type": "VLC",
"protocol": "http",
"port": 81,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"ipc-2mpvd28w"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/h264_stream"
},
{
"models": [
"ipc-2mpvd28w"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/?action=stream"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "VIDEO.CGI"
},
{
"models": [
"uniview"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/onvif-stream2"
},
{
"models": [
"zero"
],
"type": "FFMPEG",
"protocol": "http",
"port": 8090,
"url": "/video.mjpg?q=30&fps=33&id=0.5"
}
]
}

View file

@ -1,72 +0,0 @@
{
"brand": "4sdot",
"brand_id": "4sdot",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"4331911061",
"4S-B05W-720P",
"B05W-720"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"4S-B05W-720P",
"B05W-720P",
"CMOS720P",
"hx series"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
},
{
"models": [
"B05W-720P",
"B07BW-1080P-HX",
"HX series",
"HX SERIES",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/11"
},
{
"models": [
"B07BW-1080P-HX",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/1"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/live/av0"
},
{
"models": [
"PW638K"
],
"type": "MJPEG",
"protocol": "http",
"port": 81,
"url": "videostream.cgi"
}
]
}

View file

@ -1,209 +0,0 @@
{
"brand": "4ucam",
"brand_id": "4ucam",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Eyes DVR",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "/cgi-bin/Stream?Video?Acc=[USERNAME]?Pwd=[PASSWORD]?webcamPWD=UserCookie00000"
},
{
"models": [
"EYES DVR",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"EYES DVR",
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "shot.jpg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/Stream?Video?Acc=[USERNAME]?Pwd=[PASSWORD]?webcamPWD=UserCookie00000"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=VGA"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/cam/realmonitor"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "stream.asf"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/guest/Video.cgi?media=JPEG&channel=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/net_jpeg.cgi?ch=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?1"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=2"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "capture[CHANNEL].jpg"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "loginfree.jpg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/video.jpg?cam=[CHANNEL]&quality=3&size=2"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "ch0_0.h264"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
}
]
}

View file

@ -1,179 +0,0 @@
{
"brand": "4xem",
"brand_id": "4xem",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"IP3112",
"IPCAMW45",
"Other",
"PT 3114",
"PZ6114",
"W50",
"WLPTG",
"WLPTS",
"WLPTZ",
"WPT",
"wptz"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/video.jpg?size=2"
},
{
"models": [
"IP3112",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"IP3112"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?1"
},
{
"models": [
"IpCamW45",
"KX SERIES",
"Other",
"W45"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "live.sdp"
},
{
"models": [
"IPCAMW45",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"KX SERIES",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/video.jpg"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other",
"PZ6114"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/net_jpeg.cgi?ch=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/video.jpg?cam=[CHANNEL]&quality=3&size=2"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=VGA"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32"
},
{
"models": [
"Other",
"Other3"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "cgi-bin/view.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"PT 3114"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/cgi-bin/video.jpg?cam=0&quality=3&size=2"
}
]
}

View file

@ -1,26 +0,0 @@
{
"brand": "4xptz",
"brand_id": "4xptz",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"30x"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "live_mpeg4.sdp"
},
{
"models": [
"M400"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/stream0"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "555",
"brand_id": "555",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "5mpbullet",
"brand_id": "5mpbullet",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/Onvif/live/1/1"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "7-star",
"brand_id": "7-star",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"WIPB-SC22"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
}
]
}

View file

@ -1,763 +0,0 @@
{
"brand": "7links",
"brand_id": "7links",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/Streaming/Channels/[CHANNEL+1]01"
},
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/Streaming/Channels/[CHANNEL]01"
},
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/Streaming/Channels/[CHANNEL+1]02"
},
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/Streaming/Channels/[CHANNEL]02"
},
{
"models": [
"3628-675",
"PX-3615-675"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]*[HEIGHT]"
},
{
"models": [
"3655",
"3786-675",
"IPC-440HD",
"IPC-710IR",
"Meins",
"Other",
"PX3309",
"PX3615",
"PX-3628-675",
"PX-3671-675 LHL",
"px-3688-675",
"px-3722-675",
"PX3744",
"Sitzplatz"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf"
},
{
"models": [
"3655",
"ipc-710ir",
"ipc-720",
"IP-CAM",
"PX 3675",
"PX3309",
"PX-3615"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"3655",
"7LinksCamBarn",
"IPC-380",
"IPC-720",
"IPC-720 HD",
"IPC-800.FHD",
"ipc900.ptz",
"NX4275",
"NX-4284-675",
"PX3615",
"PX-3688-675",
"PX-3755"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/live/ch0"
},
{
"models": [
"3671",
"3677",
"3677-675",
"3720-675",
"3720-919",
"3755",
"Incam",
"ipc-720",
"IPC-760HD",
"IPC-770HD",
"IP-Cam-in",
"Other",
"PX3309",
"PX-3671-675 LHL",
"px-3675",
"px-3719-675",
"px-3720-675",
"PX-3720-675",
"Überwachung"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"3671",
"3677",
"3677-675",
"3720-919",
"IPC-440.HD",
"ipc-710ir",
"IPC-710IR",
"IP-Cam-in",
"IP-Wi-Fi",
"lenacam",
"Other",
"PX 3675",
"px 3675-675",
"PX3309",
"PX3614_675",
"PX3615",
"px-3671",
"PX-3671-675 LHL",
"px-3688-675",
"px-3722-675",
"Px3722-675"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"3671",
"as",
"moja",
"Other",
"PX3614_12",
"PX3615",
"PX-3615-675",
"px-3671",
"RoboCam III"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"3677",
"374411",
"3755",
"ipc-20hd",
"IPC-340HD",
"IPC-440.HD",
"IPC440HD",
"IPC-720",
"IPC-770HD",
"IPC-850.FHD",
"Other",
"Px3722-675",
"px3744",
"PX-3744",
"Px3744-675",
"px3755",
"PX-3755",
"PX-3765-675",
"px-3775",
"PX-4760"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=[USERNAME]&pwd=[PASSWORD]&"
},
{
"models": [
"3677",
"HAUSTÜR",
"IPC-710IR",
"IP-WI-FI",
"Other",
"px-1179-675",
"px-1279",
"PX3309",
"PX3615",
"PX-3688-675",
"RoboCam II",
"ROBOCAM III",
"ÜBERWACHUNG",
"Wireless"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi/mjpg/mjpeg.cgi"
},
{
"models": [
"3677",
"IPC-430 WIFI",
"IPC-631.HD",
"IP-CAM",
"Other",
"PX-3615"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
},
{
"models": [
"3720-675",
"ipc-720 HD",
"IPC-760HD",
"IPC-770HD",
"Other",
"PX 3675",
"px 3675-675",
"PX-3671-675 LHL",
"PX36771-1",
"px-3720-675"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/video_snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"3720-675",
"ipc-720",
"NX-4558"
],
"type": "VLC",
"protocol": "rtsp",
"port": 5544,
"url": "ch0_0.h264"
},
{
"models": [
"3744",
"IPC 260",
"IPC-20HD",
"ipc900.ptz",
"Other",
"PX 3760-675",
"PX-3755-675"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "videoMain"
},
{
"models": [
"3775-675"
],
"type": "JPEG",
"protocol": "http",
"port": 88,
"url": "/cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"4336",
"IPC-20HD",
"IPC-430 WIFI",
"IPC-720 HD",
"IP-CAM-IN",
"nx-4341-675",
"NX-4341-675",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"CS131A",
"RoboCam",
"RoboCam II",
"RoboCam III"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi/jpg/image.cgi"
},
{
"models": [
"Haustür",
"IP-Wi-Fi",
"Other",
"PX3614_12",
"PX3615",
"px-3722-675"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=11"
},
{
"models": [
"IPC-220.hd",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": ""
},
{
"models": [
"IPC-340HD",
"ipc-380",
"IPC-770HD",
"IP-CAM",
"PX-37878"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/live/av0"
},
{
"models": [
"IPC-400"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/av0_0"
},
{
"models": [
"IPC-430 WIFI",
"Other",
"PX3615"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?usr=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"IPC-440.HD",
"IPC-440HD",
"IPC-750HD",
"ipc900.ptz",
"NX-4207",
"NX-4209"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 80,
"url": "/videoMain"
},
{
"models": [
"IPC-440.HD",
"IPC-720",
"NX-4558-913"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/live1.264"
},
{
"models": [
"IPC440HD",
"ipc900.ptz"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam/realmonitor?channel=[CHANNEL]&subtype=1"
},
{
"models": [
"IPC-440HD",
"ipc-720",
"Other",
"PX3309",
"PX3615",
"px-3675",
"px-3688-675"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=VGA"
},
{
"models": [
"ipc-631.hd",
"px-3690"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.mjpg"
},
{
"models": [
"ipc-631.hd",
"px-3690"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.mjpg?q=30&fps=33&id=0.5"
},
{
"models": [
"IPC-710IR",
"Other",
"PX3615",
"px-3690"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi"
},
{
"models": [
"ipc-720",
"IPC-720 HD",
"Other",
"PX3615",
"px-3690"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?"
},
{
"models": [
"IPC-720 HD",
"IP-CAM",
"nx 4389",
"NX-4389-675",
"Other",
"pano360s",
"SK7008-T1F1"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg"
},
{
"models": [
"IP-CAM",
"PX3614_675"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"IP-CAM",
"Other",
"PX3615"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?resolution=8&rate=13"
},
{
"models": [
"IP-Wi-Fi",
"Other",
"PX3615"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=0&user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"KT-6764",
"PX-3744",
"RoboCam III"
],
"type": "MJPEG",
"protocol": "http",
"port": 80,
"url": "/?action=stream"
},
{
"models": [
"NX-4209"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 88,
"url": "/live/h264/ch0"
},
{
"models": [
"NX-4336-675"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/11"
},
{
"models": [
"NX-4389-675",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 88,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]&strm=[CHANNEL]"
},
{
"models": [
"Other",
"PX3615"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other",
"PX3309"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video?profile=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"px 3675-675",
"PX3615",
"px3723"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi"
},
{
"models": [
"px 3675-675"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=320*240"
},
{
"models": [
"PX3309",
"PX3615"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"PX3614_675"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=320x240"
},
{
"models": [
"PX-3615-675"
],
"type": "FFMPEG",
"protocol": "http",
"port": 888,
"url": "/videostream.asf"
},
{
"models": [
"PX-3615-675"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&password=[PASSWORD]"
},
{
"models": [
"px-3688-675"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "?action=stream"
},
{
"models": [
"px-3690"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "jpg/image.jpg?size=3"
},
{
"models": [
"px-3690"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/"
},
{
"models": [
"RoboCam II",
"RoboCam III"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi/mjpg/mjpg.cgi"
},
{
"models": [
"RoboCam II"
],
"type": "JPEG",
"protocol": "http",
"port": 82,
"url": "/cgi/jpg/image.cgi"
},
{
"models": [
"RoboCam III"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "user/videostream.cgi"
},
{
"models": [
"RoboCam III"
],
"type": "FFMPEG",
"protocol": "http",
"port": 82,
"url": "/cgi/mjpg/mjpg.cgi"
},
{
"models": [
"IPC-300"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/Streaming/Channels/101"
},
{
"models": [
"IPC-740"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/Streaming/Channels/102"
},
{
"models": [
"PX3615",
"SK7008-T1F1"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/channels/401"
}
]
}

View file

@ -1,36 +0,0 @@
{
"brand": "8level",
"brand_id": "8level",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"IPED-2MP-36-1",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/h264_stream"
},
{
"models": [
"v380"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/11"
}
]
}

View file

@ -1,53 +0,0 @@
{
"brand": "9up",
"brand_id": "9up",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"DIP3"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=2"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/sf.cgi"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "A-bmi",
"brand_id": "a-bmi",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
}
]
}

View file

@ -1,80 +0,0 @@
{
"brand": "A-link",
"brand_id": "a-link",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"101",
"IPC1",
"IPC2",
"IPC3"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi/jpg/image.cgi"
},
{
"models": [
"101",
"IPC1",
"IPC2"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi/mjpg/mjpeg.cgi"
},
{
"models": [
"AICN500W",
"IPC1"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi/mjpg/mjpg.cgi"
},
{
"models": [
"IPC2"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"IPC3",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image.cgi?resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"IPC3",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"IPC3",
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "/Video?Codec=MPEG4&Width=720&Height=576&Fps=30"
}
]
}

View file

@ -1,143 +0,0 @@
{
"brand": "A-mtk",
"brand_id": "a-mtk",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"2570D",
"6566",
"Other",
"SUPER"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "media/media.amp"
},
{
"models": [
"6566",
"AM9539M",
"Dome",
"Other",
"SUPER"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "cgi-bin/net_video.cgi?channel=[CHANNEL]"
},
{
"models": [
"AH2927T-A"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/media.amp"
},
{
"models": [
"AH2927T-A",
"Dome",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi"
},
{
"models": [
"AM2110D"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/media.amp?streamprofile=Profile1"
},
{
"models": [
"AM2110D"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/media.amp?streamprofile=Profile2"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam/realmonitor?channel=[CHANNEL]&subtype=00"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "capture[CHANNEL].jpg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video?profile=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=VGA"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "A-tion",
"brand_id": "a-tion",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"A0528"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/11"
}
]
}

View file

@ -1,55 +0,0 @@
{
"brand": "A1webcam",
"brand_id": "a1webcam",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/jpg.cgi?refresh=0&channel=[CHANNEL]&id=[USERNAME]&pass=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]&oldbrowser=1"
},
{
"models": [
"Other",
"Phone"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]*[HEIGHT]"
},
{
"models": [
"tyytt"
],
"type": "MJPEG",
"protocol": "http",
"port": 8080,
"url": "/videofeed"
},
{
"models": [
"Wanscam",
"web1"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=2"
}
]
}

View file

@ -1,141 +0,0 @@
{
"brand": "A4tech",
"brand_id": "a4tech",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"432b",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/guest/Video.cgi?media=JPEG"
},
{
"models": [
"432b",
"avm457",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/guest/Video.cgi?media=JPEG&channel=[CHANNEL]"
},
{
"models": [
"AVM457",
"Ganek",
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?usr=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"AVM457",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"ITD2016",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.mjpg"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=2"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image.jpg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=11"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "nphMotionJpeg?Resolution=640x480&Quality=Standard"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=0&user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "GetData.cgi"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "[CHANNEL]/[USERNAME]:[PASSWORD]/main"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.mjpg?q=30&fps=33&id=0.5"
}
]
}

View file

@ -1,24 +0,0 @@
{
"brand": "Aanke",
"brand_id": "aanke",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"191BL",
"191BM",
"C500",
"C800",
"I51DL",
"I91BF",
"I91BN",
"I91-DX"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/user=[USERNAME]_password=[PASSWORD]_channel=1_stream=0.sdp"
}
]
}

View file

@ -1,80 +0,0 @@
{
"brand": "Abelcam",
"brand_id": "abelcam",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"005"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi/snapshot.cgi?action=getdata&channel.[CHANNEL].capture=true&channel.[CHANNEL].resolution=1"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/net_jpeg.cgi?ch=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "live/ch00_0"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"WebCam (2)"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "current[CHANNEL].jpg"
},
{
"models": [
"WebCam (2)"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "current[CHANNEL].mjpg"
},
{
"models": [
"WebCam Server"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "screen.jpg"
},
{
"models": [
"WebCam Server"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "screen.mjpg"
}
]
}

View file

@ -1,26 +0,0 @@
{
"brand": "Abient Weather",
"brand_id": "abient-weather",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"AMBIENTCAMHD"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=[USERNAME]&pwd=[PASSWORD]&"
},
{
"models": [
"SK7008-T1F1"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 10554,
"url": "/Streaming/channels/601"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Abo",
"brand_id": "abo",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Ranger Pro"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Abr Security",
"brand_id": "abr-security",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"IPC6200W"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/11"
}
]
}

View file

@ -1,32 +0,0 @@
{
"brand": "Abr",
"brand_id": "abr",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"6100",
"720p",
"ipc6100w"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"6100",
"6200",
"ABR-IPD6200W",
"IPC6100W",
"IPD6200W"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/11"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Abron",
"brand_id": "abron",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"AB-IPR506NB-US"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/rtsph2641080p"
}
]
}

View file

@ -1,108 +0,0 @@
{
"brand": "Abs",
"brand_id": "abs",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"3 series"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"3 series",
"4 series"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "mjpg/1/video.mjpg"
},
{
"models": [
"3 SERIES",
"4 SERIES",
"MegaCam",
"MegaCam 312M",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "jpg/1/image.jpg"
},
{
"models": [
"3 SERIES",
"4 SERIES",
"megacam 4210",
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "mpeg4/[CHANNEL]/media.amp"
},
{
"models": [
"4 series",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=VGA"
},
{
"models": [
"4 SERIES",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "mjpg/[CHANNEL]/video.mjpg"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/net_jpeg.cgi?ch=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=0"
}
]
}

View file

@ -1,35 +0,0 @@
{
"brand": "Absolutron",
"brand_id": "absolutron",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "image.mpg"
},
{
"models": [
"ptz"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]&strm=[CHANNEL]"
}
]
}

View file

@ -1,676 +0,0 @@
{
"brand": "Abus",
"brand_id": "abus",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Channels/[CHANNEL+1]01"
},
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Channels/[CHANNEL]01"
},
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Channels/[CHANNEL+1]02"
},
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Channels/[CHANNEL]02"
},
{
"models": [
"10550",
"Other",
"TV21550",
"TVIP10500",
"TVIP10550",
"TVIP11000",
"TVIP20000",
"TVIP21550",
"TVIP51550",
"TVIP52501"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "jpg/image.jpg"
},
{
"models": [
"21501",
"Other",
"TVIP10001",
"TVIP10050",
"TVIP10051",
"TVIP21050",
"TVIP21500",
"TVIP31050",
"TVIP52501",
"tvip71000",
"TVIP71550"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "jpg/image.jpg?size=3"
},
{
"models": [
"2718",
"Digi-Lan TV7204",
"DIGI-LAN TV7219",
"Digi-Lan TV7230",
"DIGI-LAN TV7230 V2",
"Innenhof",
"Other",
"tv7202",
"TV7203",
"TV7210",
"TV7214",
"tv7216",
"tv7218",
"TV7240-LAN",
"TVIP51550"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/video.jpg"
},
{
"models": [
"ABUS: TVIP82100",
"IPCB64621",
"TVIP42561"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/user=[USERNAME]_password=[PASSWORD]_channel=1_stream=0.sdp"
},
{
"models": [
"casa",
"DIGI-LAN TV7230 V2",
"Other20550",
"TV7203",
"TV7220",
"TVIP41550",
"TVIP52500",
"TVIP52501"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/viewer/video.jpg?resolution=640x480"
},
{
"models": [
"CF3",
"ipcb42501",
"IPCB54611B",
"IPCB74521",
"IPCB78520",
"IPCS84530",
"TVIP11560",
"TVIP41500",
"TVIP42561",
"TVIP42562",
"TVIP44510",
"TVIP60000",
"TVIP61500",
"TVIP61550",
"TVIP61560",
"TVIP62000",
"TVIP62560"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/Streaming/Channels/1"
},
{
"models": [
"Digilan 7230",
"TV7204V2",
"tv7216",
"TV7230"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/video.jpg?size=2"
},
{
"models": [
"DIGILAN 7230",
"Digi-Lan TV7204",
"Digi-Lan TV7230",
"DIGI-LAN TV7230",
"DIGI-LAN TV7230 V2",
"entree",
"foyer",
"Other",
"Other20550",
"TV7203",
"tv7204",
"TV7220",
"TV7240-LAN",
"TVIP11000",
"TVIP21550",
"TVIP41550_CAM1",
"TVIP52500",
"TVIP61560"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "live.sdp"
},
{
"models": [
"Digi-Lan TV7204",
"Other",
"Other20550",
"TV7204v2",
"TV7222",
"TVIP41550",
"TVIP51550"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/viewer/video.jpg?channel=[CHANNEL]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Digi-Lan TV7206",
"Digi-Lan TV7230 v2",
"TVIP41550",
"tvip52500",
"tvip52501",
"TVIP52501",
"TVIP60550"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/viewer/video.jpg"
},
{
"models": [
"Digi-Lan TV7206",
"Digi-Lan TV7230 v2",
"FENIX",
"HD720p Dome",
"Other",
"Other20550",
"TIVP 31500",
"TV21550",
"TV7203",
"TVIP10000",
"TVIP10001",
"TVIP10055",
"TVIP11000",
"TVIP11502",
"TVIP11551",
"TVIP11552",
"TVIP21500",
"TVIP21550",
"tvip21551",
"tvip21552",
"TVIP21552",
"TVIP21560",
"TVIP31551",
"TVIP32500",
"TVIP41550",
"TVIP51550",
"TVIP71501",
"TVIP71551",
"TVIP717551",
"tvipem"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.mjpg"
},
{
"models": [
"DVR90001"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Unicast/channels/101.sdp"
},
{
"models": [
"DVR9001"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Unicast/channels/102.sdp"
},
{
"models": [
"DVR9001"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Unicast/channels/202.sdp"
},
{
"models": [
"HDCC90001"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Unicast/channels/201.sdp"
},
{
"models": [
"IP17550",
"IPS17550",
"IR 1080p",
"tvip10550",
"TVIP21500",
"tvip21551",
"tvip21552",
"TVIP52500",
"TVIP61550",
"TVIP62560",
"TVIP71501"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/video.mp4"
},
{
"models": [
"IP4100",
"TVIP42561",
"TVIP92700"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/stream1"
},
{
"models": [
"IP4100",
"IPCS34511A"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/h264_stream"
},
{
"models": [
"IPCA 62520",
"IPCB42515A",
"IPCB62510A",
"TVIP61560"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/1"
},
{
"models": [
"IPCA 72500",
"IPCB42515A"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/s2"
},
{
"models": [
"IPCB54611B",
"TVIP44510",
"TVIP68510"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/0"
},
{
"models": [
"IPCb64620",
"IPCB78520",
"IPCS84530",
"TVIP 21000",
"TVIP41500",
"TVIP60000",
"TVIP61500",
"TVIP61550",
"TVIP61560",
"TVIP62560"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/live.sdp"
},
{
"models": [
"IPCB7250",
"IPCB74520",
"IPCB74521",
"IPCB78520",
"TVIP22500",
"TVIP31001",
"TVIP31501",
"TVIP32500",
"TVIP60000",
"TVIP71501",
"TVIP72500"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/video.h264"
},
{
"models": [
"IPTV42560"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam[CHANNEL]/h264"
},
{
"models": [
"IPTV605550",
"TVIP41550"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/viewer/video.jpg?resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"Other",
"TVIP10000",
"TVIP20000",
"TVIP20050",
"TVIP21500",
"tvip21551"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/jpg/image"
},
{
"models": [
"Other",
"TVIP20000",
"TVIP21500",
"TVIP717551"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/view/image?pro_[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "cgi-bin/view.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"Other",
"PortCam",
"TV20550",
"TV21550",
"TV32500",
"TVIP10550",
"TVIP11560",
"TVIP20000",
"TVIP20550",
"TVIP21550",
"TVIP41500",
"TVIP41550",
"TVIP61500",
"TVIP71501"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "video.mp4"
},
{
"models": [
"TIVP 31550",
"TVIP10001",
"TVIP10051",
"TVIP10055",
"TVIP11551",
"TVIP21501",
"TVIP21550",
"TVIP40000",
"TVIP41550",
"TVIP51500",
"TVIP51550",
"TVIP71550"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.mjpg?q=30&fps=33&id=0.5"
},
{
"models": [
"TIVP41550"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/cgi-bin/viewer/video.jpg?resolution=320x240"
},
{
"models": [
"tv7203",
"TVIP41550"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/cgi-bin/viewer/video.jpg?resolution=640x480"
},
{
"models": [
"TVIP10055",
"tvip10055A",
"TVIP10055A"
],
"type": "JPEG",
"protocol": "http",
"port": 10001,
"url": "/jpg/image.jpg?size=3"
},
{
"models": [
"TVIP21000",
"tvip41560"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/ch0_0.h264"
},
{
"models": [
"TVIP21500"
],
"type": "MJPEG",
"protocol": "http",
"port": 80,
"url": "/video.mjpg"
},
{
"models": [
"TVIP22500",
"TVIP31001",
"TVIP32500",
"TVIP41560",
"TVIP62520"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "video.h264"
},
{
"models": [
"TVIP41500"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/11"
},
{
"models": [
"TVIP41500",
"TVIP41550_cam1",
"TVIP41550_cam2"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "VideoInput/[CHANNEL]/h264/1"
},
{
"models": [
"TVIP41550"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video[USERNAME].mjpg"
},
{
"models": [
"tvip41560",
"TVIP61550"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/Streaming/Channels/2"
},
{
"models": [
"TVIP62000",
"TVIP62500"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "jpeg/pull"
},
{
"models": [
"TVIP72000"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/VideoInput/0/h264/1"
},
{
"models": [
"TVIP82561"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/mpeg4/media.amp?resolution=640x480"
},
{
"models": [
"IPCA53000",
"IPCB42510B",
"IPCB44510A",
"IPCB64515B"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Channels/102"
},
{
"models": [
"IPCB42550",
"IPCB78520",
"NVR10030",
"TVIP41500",
"TVIP52500"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/Streaming/Channels/101"
}
]
}

View file

@ -1,28 +0,0 @@
{
"brand": "Ac38xx",
"brand_id": "ac38xx",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"dm12",
"MD12"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/onvif/live/2"
},
{
"models": [
"DM12",
"MD12"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/onvif/live/1"
}
]
}

View file

@ -1,36 +0,0 @@
{
"brand": "Acam",
"brand_id": "acam",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"C2100"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/ONVIF/channel2"
},
{
"models": [
"imp2irmptz"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/user=[USERNAME]_password=[PASSWORD]_channel=1_stream=0.sdp"
},
{
"models": [
"n287z752",
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
}
]
}

View file

@ -1,29 +0,0 @@
{
"brand": "Accfly",
"brand_id": "accfly",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"c091wx",
"c102wx",
"c120wx",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/11"
},
{
"models": [
"P72"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=2"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Accsxperts",
"brand_id": "accsxperts",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"5deMayo"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
}
]
}

View file

@ -1,31 +0,0 @@
{
"brand": "Ace",
"brand_id": "ace",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Esperanza",
"Other",
"samsung",
"Xin",
"Yca"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"noname",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/profile0"
}
]
}

View file

@ -1,123 +0,0 @@
{
"brand": "Acer",
"brand_id": "acer",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"A100",
"A500",
"ASPIRE",
"LMT"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"A500"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"A500",
"Apire One",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image.jpg"
},
{
"models": [
"A500"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "current[CHANNEL].jpg"
},
{
"models": [
"A500"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "/control/faststream.jpg?stream=MxPEG&needlength&fps=6"
},
{
"models": [
"Apire One"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "Image.jpg"
},
{
"models": [
"Apire One",
"Aspire"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "out.jpg?id=0.5"
},
{
"models": [
"Aspire"
],
"type": "MJPEG",
"protocol": "http",
"port": 8090,
"url": "/video.mjpg"
},
{
"models": [
"ASPIRE"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Iconia",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "shot.jpg"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/cam/realmonitor"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Aceri-bcn",
"brand_id": "aceri-bcn",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/video.cgi?msubmenu=mjpg"
}
]
}

View file

@ -1,90 +0,0 @@
{
"brand": "Acesee",
"brand_id": "acesee",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"AC04",
"AVZM40P130",
"DSE",
"EB225/SH",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Channels/1"
},
{
"models": [
"acdsee",
"ST-316-2M-AI"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/h264_stream"
},
{
"models": [
"AMB36HL200W"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8061,
"url": "/2"
},
{
"models": [
"AVP40P200",
"Dome",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/0"
},
{
"models": [
"AVTN40P130",
"avzm40p200",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
},
{
"models": [
"AVZM40P130"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "ipcam/avc.cgi?audiostream=[CHANNEL]"
},
{
"models": [
"K9604-W",
"ST-316-2M-AI"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "cgi-bin/view.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
}
]
}

View file

@ -1,56 +0,0 @@
{
"brand": "Achtertuin",
"brand_id": "achtertuin",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"3011",
"N3011"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/cam1/onvif-h264"
},
{
"models": [
"3011",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=VGA"
},
{
"models": [
"Hooldoor",
"huawau"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/11"
},
{
"models": [
"Link"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Panasonic"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "nphMotionJpeg?Resolution=640x480&Quality=Standard"
}
]
}

View file

@ -1,18 +0,0 @@
{
"brand": "Acm-v3002",
"brand_id": "acm-v3002",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Fine",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/stream2"
}
]
}

View file

@ -1,62 +0,0 @@
{
"brand": "Acm",
"brand_id": "acm",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"1311"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/encoder?USER=[USERNAME]&PWD=[PASSWORD]&SNAPSHOT"
},
{
"models": [
"4100b"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": ""
},
{
"models": [
"m101"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"m101"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]&strm=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi/mjpg/mjpeg.cgi"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Acor",
"brand_id": "acor",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "cgi-bin/view.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
}
]
}

View file

@ -1,182 +0,0 @@
{
"brand": "Acromedia",
"brand_id": "acromedia",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"009",
"ACROMEDIA IN-009",
"IN/EX",
"IN/EX Series",
"IN-010",
"IN-09",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 10554,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"009",
"Acromedia IN-009",
"ACROMEDIA IN-009",
"BLW-2004E-AHD",
"IN-010",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/11"
},
{
"models": [
"BLW-2004E-AHD"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"ECESMS",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"in/ex",
"IN/EX Series",
"IN-010",
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"IN/EX",
"IN/EX Series"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=11"
},
{
"models": [
"IN/EX Series",
"IN/EX SERİES",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi"
},
{
"models": [
"in-009",
"IN-010",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/12"
},
{
"models": [
"IN-009",
"IN-010"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
},
{
"models": [
"IN-010"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?usr=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"IN-010"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/ONVIF/channel2"
},
{
"models": [
"IN-010"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&password=[PASSWORD]"
},
{
"models": [
"IN-010"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "ipcam/avc.cgi?audiostream=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam1/mpeg4"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "MediaInput/mpeg4"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg"
}
]
}

View file

@ -1,727 +0,0 @@
{
"brand": "Acti",
"brand_id": "acti",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"000",
"00217",
"1231",
"1239",
"3411",
"3511",
"4200",
"4201",
"5711n",
"7411 B",
"7911",
"8201",
"A41",
"A71",
"acd 2200",
"ACD2000",
"ACD2100",
"ACM-1011",
"ACM11231",
"ACM1231",
"ACM-1431",
"ACM-1431N",
"acm-1431P",
"ACM-1432P",
"acm3001",
"ACM-3001",
"ACM3011",
"ACM-3211",
"ACM3401",
"ACM-3411",
"ACM-3511",
"ACM3601",
"ACM-3601",
"ACM3701",
"acm-4000",
"acm4001",
"ACM-4001",
"ACM-4100",
"ACM-4200",
"acm4201",
"ACM-4201",
"ACM-5001",
"ACM-5601",
"acm-5611",
"ACM5611",
"ACM-7411",
"acm-7511",
"acm8201",
"ACM-8211",
"ACM-8511",
"ACN-3211",
"acti d55",
"ACTI IP CAMERA",
"ACTI-1231",
"ACTiMyView",
"ADC3011",
"B21",
"B27",
"B410",
"B45",
"b53",
"B77A",
"b97",
"D11",
"D12",
"D31",
"D32",
"D51",
"D52",
"D55",
"d61a",
"D64",
"d71a",
"D72",
"D72A",
"D82",
"D92",
"E 913",
"E12",
"E12A",
"E13",
"E22VA",
"E31",
"E32",
"E32A",
"E33",
"E36",
"e37",
"E41",
"E42",
"E42A",
"E43",
"e43b",
"E44A",
"E45A",
"E46",
"E51 Manual",
"E53",
"e56",
"E61",
"E62A",
"E66",
"E72A",
"E77",
"E77--A-XX-14E-00179",
"E77-Phil",
"E816",
"E82",
"E91",
"E92",
"E93",
"E94",
"e97",
"E98",
"I51",
"I96",
"i98",
"KCM-3311",
"KCM-3911",
"KCM-5211",
"KCM5511",
"KCM5611",
"KCM-5611",
"KCM7111",
"Other",
"SED-2120",
"SHS",
"TCM 4301",
"TCM 4511",
"TCM-1111",
"TCM1231",
"TCM-1511",
"TCM3041",
"TCM-3111",
"TCM3401",
"TCM3411",
"TCM-3511",
"TCM-4101",
"TCM-4201",
"TCM4301-09C-X",
"tcm-4511",
"TCM5311",
"TCM5611",
"TCM7411",
"tcm-7811"
],
"type": "JPEG",
"protocol": "http",
"port": 7070,
"url": "cgi-bin/encoder?USER=[USERNAME]&PWD=[PASSWORD]&SNAPSHOT"
},
{
"models": [
"000",
"7411 B",
"acm 8511",
"ACM3601",
"acm4201",
"ACM-4201",
"ACM-7411",
"ACM-8211",
"acti d55",
"D52",
"D55",
"d61a",
"D92",
"Dome",
"E54",
"E77",
"KCM-5211",
"TCM1231",
"TCM-1231",
"tcm-4511"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/cgi-bin/encoder?USER=[USERNAME]&PWD=[PASSWORD]&SNAPSHOT"
},
{
"models": [
"1231",
"3411",
"A41",
"A416",
"ACD2100",
"ACM-1231",
"ACM-1431N",
"ACM3211",
"ACM-3401",
"ACM-3511",
"ACM-4001",
"ACM-4201",
"ACM-7411",
"b53",
"B54",
"B910",
"B95--A2XX-14B-00310",
"d11",
"D12",
"D21",
"D31",
"D32",
"D42",
"D51",
"D52",
"D55",
"D72",
"D82",
"D92",
"DO4M36A",
"E12",
"E13",
"E32",
"E33",
"E33 chan2",
"E42A",
"E43",
"E43A",
"E46",
"E51",
"E52",
"E53",
"E53--A-XX-13G-00029",
"e617",
"E63",
"E65",
"E73",
"E73A-A-XX-15C-00034",
"E76",
"E77",
"E81",
"E82",
"E84",
"E86a",
"E91",
"E96",
"I42",
"I51",
"KCM-3311",
"KCM-3911",
"KCM-5611",
"KCM7211",
"KCM7911",
"KCM8211",
"Other",
"v24",
"Z31",
"Z34",
"Z82",
"z95"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/stream1"
},
{
"models": [
"1231",
"1511",
"4200",
"ACCA",
"ACD2100",
"ACM 5711",
"ACM-1011",
"acm1231",
"acm1431",
"ACM-1511",
"acm3001",
"ACM-3001",
"ACM3211",
"ACM-3311",
"ACM-3401",
"ACM-3411",
"ACM-3511",
"ACM3601",
"ACM-4001",
"ACM-4200",
"ACM-4201",
"ACM-5601",
"ACM-7411",
"ACM-8511",
"ACTI IP CAMERA",
"B41",
"B45",
"B87",
"d11",
"d31",
"D32",
"d51",
"D64",
"d72",
"D82A",
"E12",
"E12A",
"E14",
"E22",
"E271",
"E33 chan2",
"E37",
"E441A",
"E61",
"E66",
"E77",
"E77--A-XX-14E-00179",
"E91",
"E92",
"E93",
"E96",
"E97",
"E98",
"KCM-5611",
"KCM7211",
"kcm-8111",
"Other",
"TCM 4511",
"TCM3011",
"TCM-4201",
"TCM-5111",
"TCM5311",
"TCM5311MG",
"tcm-7811"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/cmd/system?GET_STREAM&USER=[USERNAME]&PWD=[PASSWORD]"
},
{
"models": [
"1231",
"3411",
"4201",
"ACM-1011",
"ACM1231",
"ACM1231 egen",
"ACM-3401",
"ACM-3511",
"ACM-4001",
"ACM-4201",
"acm-5601",
"ACM5611",
"B87",
"d11",
"D12",
"D21",
"d31",
"D51",
"D52",
"D55",
"D72",
"E12",
"E32",
"E33 chan2",
"E46",
"E73",
"E77",
"E91",
"i94",
"KCM-5611",
"KCM7211",
"KCM7311",
"Other",
"TCM 3511",
"TCM 4511",
"TCM1231",
"TCM3111",
"TCM-4201",
"TCM5111"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": ""
},
{
"models": [
"1231",
"22VA",
"A41",
"ACM-1231",
"ACM3211",
"ACM3411",
"ACM-5001",
"ACM5611",
"B55",
"B67",
"B71",
"B95",
"B95--A2XX-14B-00310",
"B97--A-XX-13L-00049",
"d32",
"D32--A-XX-13K-00022",
"D54",
"D55",
"D71A",
"D71--A-XX-13C-00408",
"D81A-A-XX-15E-0",
"D91",
"E11",
"E12",
"E12A",
"E13A",
"E16",
"E22VA",
"E31",
"E32A",
"E43B",
"e46",
"E46",
"E63A",
"E77",
"E77--A-XX-14F-00933",
"E81",
"E816",
"I51",
"I71",
"i910",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 7070,
"url": "/onvif-stream1"
},
{
"models": [
"1231",
"7401",
"acm1231",
"ACM-1231",
"acm4201",
"ACM-4201",
"ACM-5001",
"ACM-7411",
"B71",
"E44",
"I47",
"TCM 4301"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/cgi-bin/cmd/system?GET_STREAM&USER=[USERNAME]&PWD=[PASSWORD]"
},
{
"models": [
"168",
"7911",
"A82",
"A84",
"a94",
"ACM-1231",
"ACM-3511",
"ACM-7411",
"ACTI IP CAMERA",
"B410",
"B43",
"b45",
"B81",
"B83",
"d11",
"D32",
"E12",
"E13A",
"E15",
"e21",
"E22VA",
"E32",
"E33",
"E33A",
"E34",
"E415",
"E42A",
"E51",
"E74A",
"E77",
"E79",
"E81",
"E86A",
"E95",
"EQ1",
"GCO",
"KCM-5311",
"KCM7311",
"KCM8211",
"Other",
"SED-2120",
"TCM 4511",
"TCM-1111",
"TCM1231",
"TCM-1231",
"TCM3111",
"TCM-3511",
"tcm-6630",
"TCM-7411"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 7070,
"url": "/"
},
{
"models": [
"A81",
"ACM3601",
"ACM-3601"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 7070,
"url": "/onvif-media/media.amp"
},
{
"models": [
"ACM-1431",
"ACM-3401",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "jpg/image.jpg"
},
{
"models": [
"ACM-3511"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam[CHANNEL]/h264"
},
{
"models": [
"ACM-3511",
"ACM-4001",
"ACM-4200"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "h264"
},
{
"models": [
"ACM-4001",
"ACTi B97",
"B96",
"B97",
"E11",
"E73--A-XX-13G-00002",
"E73--A-XX-13I-00238"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/stream2"
},
{
"models": [
"ACM-4001",
"D31",
"D82a",
"e925",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 7070,
"url": "/onvif&event&video2"
},
{
"models": [
"ACM-4201",
"TCM-1231"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "mjpeg.cgi?user=[USERNAME]&password=[PASSWORD]&channel=[CHANNEL]"
},
{
"models": [
"ACM-5001",
"ACM-7411",
"ACTi I25",
"b53",
"d10",
"D22VA",
"D61",
"E32A",
"E67a",
"E77",
"e925",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 7070,
"url": "/onvif&event&video1"
},
{
"models": [
"ACM-5001"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 7070,
"url": "/cgi-bin/cmd/encoder?GET_STREAM"
},
{
"models": [
"acm-5611",
"D61",
"d61a",
"E93"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/cgi-bin/encoder?USER=[USERNAME]&PWD=[PASSWORD]&GET_STREAM"
},
{
"models": [
"ACM5611",
"b71",
"B95",
"BS30",
"d32-2",
"E53--A-XX-14C-00157",
"E77",
"E77--A-XX-14E-00179",
"I96--A-XX-13K-00077"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/onvif-stream2"
},
{
"models": [
"ACTi B81",
"d82a",
"E413",
"I96"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 7070,
"url": "/onvif&event&audio&video1"
},
{
"models": [
"av3100ai",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image?res=half&x0=0&y0=0&x1=1600&y1=1200&quality=15&doublescan=0&ssn=1340443365044&id=1340443379230"
},
{
"models": [
"D12"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/view/image?pro_[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi/jpg/image.cgi"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "now.jpg"
},
{
"models": [
"SRICAM"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Z34"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam0/h264"
}
]
}

View file

@ -1,72 +0,0 @@
{
"brand": "Action",
"brand_id": "action",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"000",
"b53"
],
"type": "JPEG",
"protocol": "http",
"port": 7070,
"url": "cgi-bin/encoder?USER=[USERNAME]&PWD=[PASSWORD]&SNAPSHOT"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/live/av0"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "rtsp",
"port": 0,
"url": "cam[CHANNEL]/mjpeg"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "cgi-bin/net_video.cgi?channel=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "ch0_0.h264"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam[CHANNEL]/h264"
}
]
}

View file

@ -1,44 +0,0 @@
{
"brand": "Actioncam",
"brand_id": "actioncam",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"cam300"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=3"
},
{
"models": [
"camm"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"IPM"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "[CHANNEL]/video.cgi"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/guest/Video.cgi?media=JPEG"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Actiontec",
"brand_id": "actiontec",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"rc8021v"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "img/video.asf"
}
]
}

View file

@ -1,28 +0,0 @@
{
"brand": "Activa",
"brand_id": "activa",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"ACT-200W",
"ACT-2800/3100"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi/mjpg/mjpg.cgi"
},
{
"models": [
"ACT-2100",
"ACT-2800/3100"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi/jpg/image.cgi"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Active Vision",
"brand_id": "active-vision",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"ACC-V11"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "GetData.cgi"
}
]
}

View file

@ -1,161 +0,0 @@
{
"brand": "Active",
"brand_id": "active",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/streaming/video0"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "mpeg4/media.amp?resolution=640x480"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?usr=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/guest/Video.cgi?media=JPEG&channel=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/guest/Video.cgi?media=JPEG"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi?date=1&clock=1&camera=[CHANNEL]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi?camera=[CHANNEL]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi?date=1&clock=1&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi?camera=1&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "ch0_0.h264"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "live"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "capture[CHANNEL].jpg"
},
{
"models": [
"SC530"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]&strm=[CHANNEL]"
},
{
"models": [
"SC530"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "mjpeg"
},
{
"models": [
"Vision SX-1200"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "GetData.cgi?CH=[CHANNEL]&Codec=jpeg&Size=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Vision SX-500"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "[USERNAME]/cam[CHANNEL].jpg"
}
]
}

View file

@ -1,36 +0,0 @@
{
"brand": "Activecam",
"brand_id": "activecam",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"ac-d4121ir1v2"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/h264"
},
{
"models": [
"AC-D7111IR1",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/streaming/video0"
},
{
"models": [
"AC-D7111IR1"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/streaming/video1"
}
]
}

View file

@ -1,49 +0,0 @@
{
"brand": "Acumen",
"brand_id": "acumen",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"AiP-B24N",
"AiP-B34",
"AiP-M53",
"Other",
"Y04"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/rtsph2641080p"
},
{
"models": [
"AIS-S22H-B1Y0W"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/user=[USERNAME]_password=[PASSWORD]_channel=1_stream=1.sdp"
},
{
"models": [
"ekran",
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "mpg4/rtsp.amp"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
}
]
}

View file

@ -1,26 +0,0 @@
{
"brand": "Acunico",
"brand_id": "acunico",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/ucast/11"
}
]
}

View file

@ -1,35 +0,0 @@
{
"brand": "Acvil",
"brand_id": "acvil",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/Streaming/Channels/[CHANNEL+1]02"
},
{
"models": [
"ALL"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/Streaming/Channels/[CHANNEL]02"
},
{
"models": [
"WIFI-5MP-30"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/Streaming/channels/702"
}
]
}

View file

@ -1,26 +0,0 @@
{
"brand": "Adamas",
"brand_id": "adamas",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"wnc-01"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"wnc-01"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg?JpegCam=[CHANNEL]"
}
]
}

View file

@ -1,26 +0,0 @@
{
"brand": "Adapter",
"brand_id": "adapter",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"dvr"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf"
}
]
}

View file

@ -1,67 +0,0 @@
{
"brand": "Adata",
"brand_id": "adata",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"1MP HD P2P CAMERA"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/live/ch0"
},
{
"models": [
"AMB",
"AMB-MD",
"APOIP-MB",
"BLC02",
"EYE1.3",
"EYE2MBS",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/cam/realmonitor"
},
{
"models": [
"AMB",
"AMB-MB1.3",
"apollo hd dvr",
"EYE1.3",
"EYE2MBS",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"APOIP-MB",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"APOIP-MB",
"BCC",
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": ""
}
]
}

View file

@ -1,130 +0,0 @@
{
"brand": "Adc",
"brand_id": "adc",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"700x",
"723",
"V510",
"v520ir",
"V520IR",
"V521IR",
"V721W",
"V820"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 1026,
"url": "/live.sdp"
},
{
"models": [
"700X"
],
"type": "JPEG",
"protocol": "http",
"port": 1026,
"url": "cgi-bin/viewer/video.jpg?resolution=640x480"
},
{
"models": [
"723",
"ADCi400-X002",
"D064",
"Ilustra400",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/live1.sdp"
},
{
"models": [
"723",
"Other",
"V520IR",
"V820"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/live2.sdp"
},
{
"models": [
"ILLustra400",
"ILUSTRA400"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "dms"
},
{
"models": [
"ILLustra400",
"ILUSTRA400"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image/jpeg.cgi"
},
{
"models": [
"Other",
"V520IR",
"V723"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.mjpg"
},
{
"models": [
"Other",
"v510",
"V520IR",
"V720W",
"V721W"
],
"type": "JPEG",
"protocol": "http",
"port": 1026,
"url": "cgi-bin/viewer/video.jpg"
},
{
"models": [
"V510"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/viewer/video.jpg?channel=[CHANNEL]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"V520IR",
"V721W"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 1032,
"url": "/live3.sdp"
},
{
"models": [
"V521IR"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/11"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Adeco",
"brand_id": "adeco",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"PTZ"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 5544,
"url": "/11"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Adhua Dh-ipc-hdw4233c-a",
"brand_id": "adhua-dh-ipc-hdw4233c-a",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"DH-IPC-HDW4233C-A"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?1"
}
]
}

View file

@ -1,116 +0,0 @@
{
"brand": "Adhua",
"brand_id": "adhua",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"DH-HAC-HFW1200RMN-0360B-S3",
"DH-IPC-HDW4233C-A",
"HDB4300F-PT",
"MYCAM",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"DH-HAC-HFW1200RMN-0360B-S3",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"DH-IPC-HDW4233C-A"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/live0.264"
},
{
"models": [
"HDB4300F-PT"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"HDB4300F-PT",
"MyCam",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi"
},
{
"models": [
"IPC-D1B20"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/cam/realmonitor?channel=1&subtype=00&authbasic=[AUTH]"
},
{
"models": [
"IPC-HDW1230S"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=htd%402Tg25"
},
{
"models": [
"IPC-HFW1320S-W",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?1"
},
{
"models": [
"N84CL52",
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/11"
},
{
"models": [
"xvr4808"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/cgi-bin/snapshot.cgi?chn=8&u=[USERNAME]&p=[PASSWORD]"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Adiance",
"brand_id": "adiance",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "image.cgi?type=motion"
}
]
}

View file

@ -1,62 +0,0 @@
{
"brand": "Adj",
"brand_id": "adj",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"700-00048"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 1024,
"url": "/Streaming/Channels/1"
},
{
"models": [
"DVR (Channel 1)"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=1&subtype=0"
},
{
"models": [
"DVR (Channel 2)"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=2&subtype=0"
},
{
"models": [
"DVR (Channel 3)"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=3&subtype=0"
},
{
"models": [
"Wireless IPCAM"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&password=[PASSWORD]"
},
{
"models": [
"WIRELESS IPCAM"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.jpg?user=[USERNAME]&pwd=[PASSWORD]"
}
]
}

View file

@ -1,433 +0,0 @@
{
"brand": "Adt",
"brand_id": "adt",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"0c810",
"0C810",
"1000",
"1600hd",
"8025b",
"A-ADT-4HS2",
"AD412-ADT",
"ADT8025B",
"G-Camera",
"i1000",
"ICAMERA",
"icamera 1000",
"Icamera 1000",
"ICAMERA1000",
"ICAMERA-1000-ADT",
"MDC83",
"NV412A-ADT",
"OC810",
"OC810-ADT",
"OC835-ADT",
"Other",
"PULSE",
"RC8010",
"RC8021",
"RC8021W",
"RC8021W-ADT",
"RC8025",
"RC8025-ADT",
"rc8025b",
"Rc8025b",
"RC8025B-adt",
"RC8025B-ADT",
"RC8025B-V2",
"rc8-25b-adt",
"RCR021W-ADT",
"toycam"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "img/video.sav"
},
{
"models": [
"0c810",
"1000",
"8025B",
"ADT8025B",
"ICAMERA1000",
"ICAMERA-1000-ADT",
"MDC835-ADT",
"OC810",
"OC810-ADT",
"OC835-ADT",
"otc810",
"Other",
"pulsar",
"PULSE",
"RC8021",
"RC8021W",
"RC8021W-ADT",
"RC8025",
"RC8025-ADT",
"RC8025B",
"RC8025B-ADT",
"rc8325-v2"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi"
},
{
"models": [
"0C810",
"1234",
"8025",
"8025B",
"A-ADT4HS2",
"ADT8025B",
"Icamera 1000",
"ICamera1000",
"ICAMERA-1000",
"ICAMERA-1000-ADT",
"mdc835",
"NV412A",
"OC810",
"OC810-ADT",
"OC835-ADT",
"oc835v3",
"OTC810",
"Other",
"pulse",
"RC8010",
"RC8021",
"RC8021W",
"rc8021w-adt",
"RC8021W-ADT",
"RC8025",
"RC8025-ADT",
"RC8025b",
"RC8025B-adt",
"RC8025B-V2",
"RC8025b-vb",
"RC8201",
"rc8235",
"RC8326",
"RCR021W-ADT"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "img/video.mjpeg"
},
{
"models": [
"1600hd",
"A-ADT4HS2",
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam/realmonitor?channel=[CHANNEL]&subtype=1"
},
{
"models": [
"8025B",
"iCamera-1000",
"ICAMERA1000",
"OC810-ADT",
"RC8025-ADT",
"RC8025B-ADT"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?img=vga"
},
{
"models": [
"8025B",
"iCamera",
"Icamera 1000",
"ICAMERA1000",
"ICAMERA-1000-ADT",
"NV412A",
"OC810",
"OC810-ADT",
"Other",
"pulse",
"RC8021",
"RC8021W",
"RC8021W-ADT",
"RC8025",
"RC8025-ADT",
"RCR021W-ADT"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=2"
},
{
"models": [
"A-ADT4HS2",
"Icamera 1000",
"ICAMERA1000",
"ICamera-1000-ADT",
"oc810",
"OC810-ADT",
"Other",
"RC8021",
"RC8021W-ADT",
"RC8025",
"RC8025B-ADT"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "img/mjpeg.jpg"
},
{
"models": [
"A-ADT-4HS2"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "cam4/mpeg4"
},
{
"models": [
"AD412-ADT",
"nv412a",
"NV412A-ADT",
"RC8021",
"RC8021W",
"RC8021W-ADT"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "img/video.asf"
},
{
"models": [
"Digital Video Recorder"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=2&subtype=1"
},
{
"models": [
"DYK4500"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"DYK4500"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/net_jpeg.cgi?ch=[CHANNEL]"
},
{
"models": [
"G-CAMERA"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snap.jpg"
},
{
"models": [
"ICAMERA",
"ICAMERA 1000",
"ICAMERA-1000-ADT",
"OC810",
"Other",
"PULSE",
"RC8021W-ADT",
"RC8025-ADT",
"rc8025b",
"RC8025b-ADT"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi?size=3"
},
{
"models": [
"ICAMERA1000",
"ICAMERA-1000-ADT",
"ipcam-wo",
"OC810-ADT",
"Other",
"RC8021",
"RC8021W-ADT",
"rc8025",
"RC8025-ADT",
"RC8025B",
"RC8025B-ADT"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "img/mjpeg.cgi"
},
{
"models": [
"ICAMERA-1000",
"OC810-ADT",
"OC845",
"RC8025B-ADT"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/img/video.sav"
},
{
"models": [
"NV412a",
"RC8021W",
"rc8021w-adt"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/img/video.asf"
},
{
"models": [
"NV412A-ADT"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?1"
},
{
"models": [
"NV412A-ADT",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?loginuse=[USERNAME]&loginpas=[PASSWORD]"
},
{
"models": [
"NV412A-ADT",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/snapshot.cgi?chn=[CHANNEL]&u=[USERNAME]&p=[PASSWORD]"
},
{
"models": [
"OC810-ADT",
"rc8021w",
"sc468",
"SC87C51C"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/img/video.mjpeg"
},
{
"models": [
"oc835v3"
],
"type": "MJPEG",
"protocol": "http",
"port": 80,
"url": "/img/mjpeg.cgi"
},
{
"models": [
"oc845"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/11"
},
{
"models": [
"OC845"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam4/mpeg4"
},
{
"models": [
"OC845"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/user=[USERNAME]_password=[PASSWORD]_channel=1_stream=0.sdp"
},
{
"models": [
"rc8021w"
],
"type": "MJPEG",
"protocol": "http",
"port": 80,
"url": "/img/main.cgi?"
},
{
"models": [
"RC8021W"
],
"type": "MJPEG",
"protocol": "http",
"port": 81,
"url": "videostream.cgi?rate=0&user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"rc8021w-adt"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/img/mjpeg.jpg"
},
{
"models": [
"RC8025B-ADT"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=0&subtype=1"
},
{
"models": [
"SC821C83"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/img/main.cgi?next_file=main.htm"
}
]
}

View file

@ -1,18 +0,0 @@
{
"brand": "Adv",
"brand_id": "adv",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"adv1",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videofeed"
}
]
}

View file

@ -1,220 +0,0 @@
{
"brand": "Advance",
"brand_id": "advance",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"002fvwu",
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"HVC",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]&count=0"
},
{
"models": [
"NetCam"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"NetCam"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"NetCam"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=320x240"
},
{
"models": [
"NetCam"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/videostream.cgi"
},
{
"models": [
"NetCam"
],
"type": "FFMPEG",
"protocol": "http",
"port": 82,
"url": "/videostream.asf?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"NetCam",
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf"
},
{
"models": [
"NetCam"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/"
},
{
"models": [
"Other",
"WB-IP03A"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=[WIDTH]x[HEIGHT]"
},
{
"models": [
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "ch0_0.h264"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
},
{
"models": [
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "snapshot.cgi?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/sf.cgi"
},
{
"models": [
"Other"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "img/video.mjpeg"
},
{
"models": [
"WB-IP03A",
"wp00030A"
],
"type": "FFMPEG",
"protocol": "http",
"port": 80,
"url": "/video.cgi?resolution=VGA"
},
{
"models": [
"WB-IP03A"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?resolution=8&rate=13"
},
{
"models": [
"WB-IP03A"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video.cgi?resolution=VGA"
},
{
"models": [
"WB-IP03A"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=11"
},
{
"models": [
"WB-IP03A"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?rate=0"
},
{
"models": [
"WB-IP03A"
],
"type": "VLC",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]"
},
{
"models": [
"WB-IP03A"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
}
]
}

View file

@ -1,80 +0,0 @@
{
"brand": "Advanced Home",
"brand_id": "advanced-home",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"elro"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "image.jpg"
},
{
"models": [
"ELRO"
],
"type": "FFMPEG",
"protocol": "http",
"port": 0,
"url": "videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"icam"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi"
},
{
"models": [
"lc-1140"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "videostream.cgi?user=[USERNAME]&pwd=[PASSWORD]&resolution=32&rate=0"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "http",
"port": 8081,
"url": "/videostream.asf?user=[USERNAME]&pwd=[PASSWORD]&resolution=64&rate=0"
},
{
"models": [
"Phone"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "video?submenu=mjpg"
},
{
"models": [
"RC8025B-ADT"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "img/snapshot.cgi"
},
{
"models": [
"S4X"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "mjpeg"
}
]
}

View file

@ -1,327 +0,0 @@
{
"brand": "Advidia",
"brand_id": "advidia",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"A14",
"A-15",
"A-30",
"A-34W",
"A-38-F",
"A-44-IR",
"A-49-F",
"A-54-OD",
"Other",
"vp-16"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/Streaming/Channels/1"
},
{
"models": [
"A14",
"A-34"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "MediaInput/mpeg4"
},
{
"models": [
"A-14",
"A-34W",
"A-45",
"A-46"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "ch0_0.h264"
},
{
"models": [
"A-28",
"a-35",
"vp-4"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/ch0_0.h264"
},
{
"models": [
"A-34W",
"A-37FW",
"A-47",
"M-46-FW",
"VP-16-V2"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/Streaming/Channels/101"
},
{
"models": [
"A-34W",
"A-37FW",
"A-44-IR",
"A-45"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "live/mpeg4"
},
{
"models": [
"a-35",
"A-55",
"vp-16"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Channels/103"
},
{
"models": [
"A-37fw",
"A-37-FW",
"A-47",
"Other"
],
"type": "VLC",
"protocol": "rtsp",
"port": 0,
"url": "video.mp4"
},
{
"models": [
"A-427-V",
"vp-4",
"VP-8"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/MediaInput/mpeg4"
},
{
"models": [
"A-427-V",
"VP-16-V2"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/channels/901"
},
{
"models": [
"A-427-V",
"vp-8"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=2&subtype=00&authbasic=[AUTH]"
},
{
"models": [
"A-44-IR",
"a-49-f",
"VP-16"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/live/mpeg4"
},
{
"models": [
"a-49-f"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/video.mp4"
},
{
"models": [
"a-49-f",
"E-47-V"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=1&subtype=00&authbasic=[AUTH]"
},
{
"models": [
"A-54-OD"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/0"
},
{
"models": [
"A-65",
"B-38-V"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/stream1"
},
{
"models": [
"A-88-V",
"B-31"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/"
},
{
"models": [
"B-31"
],
"type": "VLC",
"protocol": "rtsp",
"port": 7070,
"url": ""
},
{
"models": [
"B-31"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/cmd/system?GET_STREAM&USER=[USERNAME]&PWD=[PASSWORD]"
},
{
"models": [
"B-31",
"B-33",
"B5360",
"Other"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "cgi-bin/encoder?USER=[USERNAME]&PWD=[PASSWORD]&SNAPSHOT"
},
{
"models": [
"E-37-V"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "axis-cgi/mjpg/video.cgi"
},
{
"models": [
"p-25",
"vp-8"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 0,
"url": "/ONVIF/MediaInput"
},
{
"models": [
"vp-16"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/Channels/2"
},
{
"models": [
"vp-16"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 10554,
"url": "/Streaming/Channels/1103"
},
{
"models": [
"VP-16"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/Streaming/channels/902"
},
{
"models": [
"VP-16-V2"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/ch2_0.h264"
},
{
"models": [
"vp-8"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "//Streaming/Channels/2"
},
{
"models": [
"vp-8"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "//Streaming/Channels/5"
},
{
"models": [
"vp-8"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=3&subtype=00&authbasic=[AUTH]"
},
{
"models": [
"vp-8"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "/cam/realmonitor?channel=101&subtype=00&authbasic=[AUTH]"
},
{
"models": [
"VP-8"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 554,
"url": "//Streaming/Channels/1"
}
]
}

View file

@ -1,28 +0,0 @@
{
"brand": "Advisen",
"brand_id": "advisen",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"123281"
],
"type": "JPEG",
"protocol": "http",
"port": 80,
"url": "/tmpfs/auto.jpg"
},
{
"models": [
"Other",
"UNLISTED",
"Visia 7"
],
"type": "JPEG",
"protocol": "http",
"port": 0,
"url": "tmpfs/auto.jpg"
}
]
}

View file

@ -1,17 +0,0 @@
{
"brand": "Advitronics",
"brand_id": "advitronics",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"PortaVision SIP"
],
"type": "MJPEG",
"protocol": "http",
"port": 0,
"url": "?action=stream"
}
]
}

View file

@ -1,26 +0,0 @@
{
"brand": "Aecbl1",
"brand_id": "aecbl1",
"last_updated": "2025-10-17",
"source": "ispyconnect.com",
"entries": [
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/live1.264"
},
{
"models": [
"Other"
],
"type": "FFMPEG",
"protocol": "rtsp",
"port": 8554,
"url": "/live0.264"
}
]
}

Some files were not shown because too many files have changed in this diff Show more