Choose a form factor
Every form factor is the same Rust core with a different host around it. The question that picks one is simple: where are your encoded frames?
The four options
Section titled “The four options”| Form factor | Your frames are | You write | Status |
|---|---|---|---|
The daemon, seydd |
On a socket: the camera publishes RTSP or RTP | A TOML file. No code | Built |
Python SDK, seyd |
In your own Python process, as access units | A few lines: Agent, add_channel, push_frame |
Built, cffi over libseyd |
C ABI, seyd.h |
In your own process, in any language that can call C | Against the header, or a wrapper of your own | Built at ABI 1. C++ and ROS 2 wrappers are planned, not built |
Rust, seyd_core::Agent |
In your own Rust program | A host of your own, the way seydd and seyd-ffi are hosts |
Built |
When each one is right
Section titled “When each one is right”Run seydd when the robot’s camera already publishes RTP or RTSP on a
socket. The daemon owns the depacketization, reads UDP sockets for sensors,
writes commands to a UDP socket, and tells your publisher what to change on
another. Enrolment is built in, and an install is one binary, one config file
and a systemd unit. Most IP cameras and most existing robot software
stacks land here. Start at Integrate the daemon.
Use the Python SDK when your process already holds encoded frames and
going through a socket would be a copy and a hop for nothing: an encoder you
drive yourself, a GStreamer or FFmpeg pipeline you already own, a research
stack. The SDK reads its declarations out of seyd.h, so it cannot drift
from the ABI. Start at A robot in Python.
Use the C ABI when the language is not Python: C, C++, Go, anything with a foreign-function interface. The header is cbindgen output from the Rust crate and is checked in, so a consumer needs no Rust toolchain. The ABI is versioned; additions are appended and never reordered until the version is bumped. Start at A robot in C and the C reference.
Use the Rust crate when you are writing the robot’s program in Rust and
want the same type the daemon is built on. A host supplies media, consumes
AgentEvent, and owns nothing of the lifecycle. Start at
A robot in Rust and the
rustdoc.
What every form factor shares
Section titled “What every form factor shares”One Rust core carries all the protocol logic: the wire format, FEC, NAT traversal, QoS, signalling and the agent lifecycle. The daemon, the Python SDK and the C header are thin hosts of it with no protocol logic of their own, so they cannot drift apart and one conformance suite covers them all. That is the decision in ADR 0004.
The rules are the same everywhere too:
- Seyd is handed encoded bytes and relays them. It never decodes, re-encodes or inspects payloads.
- Callbacks run on one Seyd thread and must not block. A slow handler delays every later event. Queue the work and return.
- Pushing a frame or a message never blocks. A frame that arrives while the previous one is still going out is dropped by admission control, and counted; keyframes never are.
- Pass the encoder’s own capture timestamp. The pilot paces presentation on it; passing “now” adds jitter the pilot cannot remove.
- Answer the publisher requests. A bitrate ceiling, a latency budget, a
GOP bound and recovery requests reach your encoder through
on_requested_configandon_recovery_request(the daemon’s publisher-control port). Ignoring them means Seyd cannot act on a congested link. See The publisher contract. - Park actuators when a session ends. The event fires whether the pilot said goodbye or simply vanished.
One gap to know about
Section titled “One gap to know about”The C ABI at version 1 has no enrolment call, so an SDK robot cannot redeem an
enrolment token itself. Enrol its key file with seydd enrol against the same
credential path, then start the SDK robot. Enrolment is planned as an append
to the ABI, not a break. Details in Enrolment and access.