Python (seyd)
Generated from the docstrings of sdks/python/seyd. The package is a thin wrapper over
libseyd (ADR 0004): every call maps onto one C ABI function, and no protocol logic lives
in Python. See A robot in Python for the guide and
C ABI for what each call does underneath.
Seyd — hyper-low-latency P2P streaming for robots, as a Python package.
A thin wrapper over libseyd (ADR 0004): all protocol logic lives in the Rust
core, so this package and seydd and the C++/ROS 2 wrappers cannot drift.
from seyd import Agent, ChannelKind
with Agent("my-robot", "wss://signal.seyd.io/ws") as agent: video = agent.add_channel(ChannelKind.VIDEO, "main", fps=25) agent.on_command = lambda channel, payload: print(payload) agent.start() ...Exported names: ABI_VERSION, Agent, Channel, ChannelKind, Counters, Role, SeydError, SeydLibraryNotFound, SignalState, __version__.
A Seyd robot.
Configure channels, register handlers, then start(). Handlers run on
one Seyd thread, in order, and must not block — a slow handler delays
every later event. Do real work on your own thread or queue.
with Agent("my-robot", "wss://signal.example/ws") as agent: video = agent.add_channel(ChannelKind.VIDEO, "main", codec="avc1.42001f", fps=25) agent.on_command = lambda ch, data: drive(data) agent.start() for au in encoder: agent.push_frame(video, au.bytes, keyframe=au.is_idr, capture_ts_us=au.pts_us)Agent(robot_id: str, signal_url: str, *, credential_path: str | None = None, quic_port: int = 0, ipv6: bool = True, port_mapping: bool = True, host_override: str | None = None, qos_profile: str = 'balanced', max_sessions: int = 0)Handlers
Section titled “Handlers”Assign a callable; all are optional. Handlers run on one Seyd thread, in order, and must not block.
| Attribute | Type | Fires |
|---|---|---|
on_session_started |
Callable[[str, Role, str], None] | None |
Called as (session_id, role, path_label) when a pilot is admitted. |
on_session_ended |
Callable[[str, str], None] | None |
Called as (session_id, reason). Park actuators here — it fires whether the pilot said goodbye or simply vanished. |
on_command |
Callable[[int, bytes], None] | None |
Called as (channel_id, payload) for each driver command. |
on_requested_config |
Callable[[Mapping], None] | None |
Called as (config) with Seyd’s targets for the publisher — the video-config document of docs/protocol/seydd.md: maxBitrateKbps, latencyBudgetMs, maxGopMs, preferIntraRefresh, suggestedFps, reason. The one place Seyd talks to the encoder. Keyframes are on demand (ADR 0009): answer on_recovery_request and treat maxGopMs as a long ceiling, not a cadence. |
on_recovery_request |
Callable[[int, str, str], None] | None |
Called as (channel_id, kind, reason) where kind is ltr, intra_refresh or idr. |
on_signal_state |
Callable[[SignalState, str | None], None] | None |
Called as (state, detail); the robot is unreachable while down. |
on_nat_report |
Callable[[Mapping], None] | None |
Called as (report) with the NAT report each time candidates are announced. |
add_channel(kind: ChannelKind, name: str, *, codec: str | None = None, fps: int = 0) -> Channel
Section titled “add_channel(kind: ChannelKind, name: str, *, codec: str | None = None, fps: int = 0) -> Channel”Add a channel. Only valid before start().
Channels are numbered from 1 in the order they are added, and that numbering is what the pilot sees.
channels: Sequence[Channel]
Section titled “channels: Sequence[Channel]”Property.
channel(name: str) -> Channel
Section titled “channel(name: str) -> Channel”The channel added under name.
start() -> None
Section titled “start() -> None”Bind, discover, announce and start serving.
Blocks while candidates are gathered (a second or two). Handlers begin firing once this returns.
stop() -> None
Section titled “stop() -> None”Stop serving. Blocks until no further handler can run. Idempotent.
close() -> None
Section titled “close() -> None”Stop and release the agent. The object is unusable afterwards.
push_frame(channel: Channel | int, data: bytes, *, keyframe: bool, capture_ts_us: int) -> None
Section titled “push_frame(channel: Channel | int, data: bytes, *, keyframe: bool, capture_ts_us: int) -> None”Hand one encoded access unit to a video channel.
Never blocks. A frame arriving while the previous one is still going
out is dropped by admission control — keyframes never are — and counted
in frames_dropped_backlog. capture_ts_us is the source’s capture
clock; the pilot paces presentation on it (ADR 0005), so pass the
encoder’s timestamp rather than “now” whenever you have it.
push_message(channel: Channel | int, data: bytes | str | Mapping) -> None
Section titled “push_message(channel: Channel | int, data: bytes | str | Mapping) -> None”Send a message on a sensor channel. Never blocks.
dict is encoded as JSON and str as UTF-8, since that is what almost
every sensor channel carries.
set_qos_profile(name: str) -> None
Section titled “set_qos_profile(name: str) -> None”Switch the QoS ceiling (latency, balanced, quality).
set_status(status: Mapping | None) -> None
Section titled “set_status(status: Mapping | None) -> None”Publish free-form robot status to the console. None clears it.
session_count: int
Section titled “session_count: int”Property.
counters: Counters
Section titled “counters: Counters”Property.
Channel
Section titled “Channel”A configured channel. Truthy id; usable directly as a push_* target.
Channel(id: int, kind: ChannelKind, name: str, codec: str, fps: int)ChannelKind
Section titled “ChannelKind”Bases: enum.IntEnum
What a channel carries. Video is FEC-protected and whole-frame-or-nothing.
| Member | Value |
|---|---|
VIDEO |
0 |
SENSOR |
1 |
COMMAND |
2 |
Counters
Section titled “Counters”Bases: dict
Engine counters. A plain mapping, with attribute access for convenience.
Bases: enum.IntEnum
A driver may send commands; an observer’s commands are dropped by the agent.
| Member | Value |
|---|---|
DRIVER |
0 |
OBSERVER |
1 |
SeydError
Section titled “SeydError”Bases: RuntimeError
A call into libseyd failed. status is the seyd_status code.
SeydError(status: int, message: str)SeydLibraryNotFound
Section titled “SeydLibraryNotFound”Bases: RuntimeError
libseyd could not be located. Set SEYD_LIBRARY to its full path.
SignalState
Section titled “SignalState”Bases: enum.IntEnum
| Member | Value |
|---|---|
CONNECTED |
0 |
DISCONNECTED |
1 |
DENIED |
2 |
ABI_VERSION
Section titled “ABI_VERSION”The SEYD_ABI_VERSION of the header the package was generated against; compared with seyd_abi_version() of the loaded library at import.