OpenCamInterop turns sanitized Frigate and ONVIF event quirks into deterministic, offline compatibility tests. Its EventLab CLI can inspect one native payload, verify every case in a versioned fixture corpus, and replay normalized CloudEvents 1.0 as streaming NDJSON.
The project opens no network connections, discovers no devices, stores no credentials, and processes no camera images or video. Contributors can reproduce an interoperability behavior without owning the original hardware or sharing a raw private capture.
Download and extract the archive for your platform from
v0.1.0-alpha.1.
Each self-contained bundle includes EventLab, the synthetic fixture corpus, schemas,
license, and notices. Compare the archive's SHA-256 digest with the digest shown on
the GitHub release before extracting it.
From an extracted Windows x64 bundle:
.\opencaminterop.exe verify --manifest fixtures\v1\manifest.json
.\opencaminterop.exe replay --manifest fixtures\v1\manifest.json --no-waitFrom an extracted Linux x64 or ARM64 bundle:
chmod +x ./opencaminterop
./opencaminterop verify --manifest fixtures/v1/manifest.json
./opencaminterop replay --manifest fixtures/v1/manifest.json --no-waitThe verified alpha corpus produces three normalized events from four synthetic cases. A successful run is evidence that the bundled cases behave deterministically on that platform, not evidence of compatibility with a physical camera or private installation.
Requirements: .NET 10 SDK.
git clone https://github.com/KalyteraSystems/OpenCamInterop.git
cd OpenCamInterop
dotnet restore OpenCamInterop.sln --locked-mode
dotnet run --project tools/OpenCamInterop.Tool -- verify --manifest fixtures/v1/manifest.json
dotnet run --project tools/OpenCamInterop.Tool -- replay --manifest fixtures/v1/manifest.json --no-waitverify checks strict manifest parsing, complete fixture registration, expected event types or diagnostics, deterministic (source, id) pairs, and the generated compatibility matrix. replay preflights the corpus and emits one structured CloudEvent per stdout line; omit --no-wait to honor relative receivedAt offsets. Human diagnostics stay on stderr.
Inspect one payload without adding it to the corpus:
dotnet run --project tools/OpenCamInterop.Tool -- inspect \
--adapter frigate \
--input fixtures/v1/frigate/object-new.json \
--source urn:opencaminterop:local:inspectUse --help for the complete command and exit-code contract. The EventLab guide documents output and safety limits.
The most valuable contribution is one previously uncovered behavior reduced to a small synthetic payload and an executable expectation. Namespace variation, reconnect duplication, unusual ordering, missing fields, property operations, and bounded vendor extensions are all useful when they produce a distinct tested result.
You do not need to write code or publish a payload to start. Use the fixture-behavior form to describe a Frigate or ONVIF quirk safely. If the event family is not supported, use the input-family proposal to identify its public documentation, smallest useful scope, and a behavior that would distinguish it from the current adapters.
Never submit a raw device export. Remove credentials, routable addresses, serial numbers, people, faces, plates, snapshots, thumbnails, installation URLs, and local paths before opening a pull request. Start with the fixture guide and contribution guide.
A model name or compatibility-table row is not evidence by itself. The generated matrix reports fixture behavior only; it is not device certification, vendor support, or ONVIF conformance.
The transport-free .NET 10 library accepts caller-owned bytes and returns validated CloudEvents:
using System.Text;
using OpenCamInterop;
using OpenCamInterop.Adapters;
using OpenCamInterop.Adapters.Frigate;
var adapter = new FrigateEventAdapter(new Uri("urn:camera:lab-nvr"));
var result = adapter.Adapt(new AdapterMessage(
"frigate/events",
Encoding.UTF8.GetBytes(json),
"application/json",
DateTimeOffset.UtcNow));
if (result.IsSuccess)
{
ReadOnlyMemory<byte> batch = StructuredCloudEventJson.SerializeBatch(result.Events);
}Inputs are capped at 1 MiB. Structured CloudEvents JSON is capped at 4 MiB and batches at 256 events. Frigate output uses an explicit field allowlist, while generic ONVIF values are redacted. Retained identifiers and caller-provided source values are not automatically anonymous; use opaque URNs and synthetic identifiers in shared fixtures. See the event contract and privacy boundary.
The checked-in baseline is intentionally small:
| Measure | Current evidence |
|---|---|
| Executable cases | 4 synthetic cases |
| Payloads | 3 synthetic payloads |
| Input adapters | 2 (Frigate and ONVIF) |
| Externally derived behavior cases | 0 |
| Independent downstream consumers | 0 |
| Non-maintainer behavior contributions | 0 |
| First-party consumers | 1 (IPCamLapse) |
The project does not count stars, generated matrix rows, mechanically split fixtures, or maintainer work as external adoption. The north-star measure is a distinct externally reported behavior merged as a sanitized fixture plus an executable expected result. See project status.
OpenCamInterop is not an NVR, camera viewer, MQTT bridge, ONVIF client, discovery tool, conformance suite, or certification program. Frigate and ONVIF names identify input formats and do not imply endorsement.
The API and fixture manifest are pre-1.0 and may change with documented migration notes. No NuGet package has been published; source and GitHub release archives are the supported alpha delivery paths.
dotnet restore OpenCamInterop.sln --locked-mode
dotnet build OpenCamInterop.sln --configuration Release --no-restore
dotnet test OpenCamInterop.sln --configuration Release --no-build
dotnet format OpenCamInterop.sln --verify-no-changes --no-restore
dotnet list OpenCamInterop.sln package --vulnerable --include-transitiveCI runs on Windows and Ubuntu. Security issues should be reported privately as described in SECURITY.md. The project history records the verified extraction point and the original IPCamLapse pull requests.