reactor::Reactor is one session, and the tracks and commands on it. It speaks raw JSON over the
wire: open a session, send commands by name, receive generic message events. It works against any
model — for the commands and events a specific one accepts, see the
Model API Reference, or ask the running model itself with
request_schema().
std::future<T>, and failures arrive as exceptions from .get() — the same
typed hierarchy a synchronous call throws. See
ReactorError.
Movable, not copyable — a session has one owner. Destroying a connected client releases the native
handle, but a creator that goes away without
disconnect() leaves the session orphaned, and the
next run cannot start until it clears.Constructors
Signature
ApiKey and Jwt are distinct one-field structs rather than two std::string parameters, so the
credential you meant is the credential that is used:
Example
reactor::fetch_jwt() mints that token without a client or a session, so a backend can hand one to
somebody else. FetchJwtOptions scopes it: models (unset with sessions, it mints an unscoped
token), max_sessions and max_session_duration_seconds for what the holder may open, and
expires_after for how long the token lives. sessions binds the token to sessions that already
exist, by id. Without models and max_sessions, that token acts only on those sessions and cannot
create new ones.
Example
Options
Definition
Executor
Signature
Example
Futures do not go through the executor. A promise is settled on the library’s own completion
thread, so
connect().get() on the same thread that would have run the executor cannot deadlock
against it.Connecting
connect()
Creates — or adopts — a session and brings up the transport. Resolves when the session is
Ready.
Signature
Definition
Throws the typed failure:
UnauthorizedError for a token problem, ConflictError for a session a
previous run left orphaned.
Example
reconnect()
Cycles the connection without ending the session — after a transient failure, or deliberately from
Ready.
Signature
disconnect() first — and doing so
would end the very session this is about to reuse. Throws when there is no session to reconnect to.
RecvOnly tracks resume automatically unless auto_resume_tracks is false.
SendOnly tracks do not: a track published before the reconnect is not published after it, so
publish again for anything you were sending.
Track::published() says which side of that you are on, and
push_frame() throws rather than pushing into a slot with
nothing behind it.disconnect()
Ends the session server-side and tears down the transport.
Signature
reconnect(). Only ends sessions this client
created; one adopted via session_id is left running for its owner.
status()
Signature
Status. Readable before
connect() — a client that never connected reports Disconnected rather than nothing.
session_id()
Signature
Commands and uploads
send_command()
Sends a command to the model and waits for its correlated reply.
Signature
The SDK carries a payload over 256 KiB, up to 64 MiB, when the runtime accepts data-channel
chunking. A runtime that does not accept it keeps the 256 KiB limit, and a larger payload fails with
MESSAGE_TOO_LARGE.
The reply is {type, data}, or empty when the handler ran and acknowledged the command without
returning a message, as an auto-generated set_<field> setter does. Empty is not a failure and is
not folded into one:
Example
.get() later — or drop
it, which sends the command all the same. These futures are settled by a promise rather than by
std::async, so dropping one neither blocks nor cancels; it only means a failure has nowhere to be
thrown.
upload_file()
Uploads a local file and returns a FileRef to pass into a
command.
Signature
Needs a
Ready session — the upload is created against it. Throws NotFoundError when the path
does not exist.
Example
A parameter that takes one file is passed separately rather than embedded in
args. The
Python SDK finds a FileRef sitting in the arguments and pulls it out; C++ has no way to
recognise one inside a Json, so it is named in the third parameter instead. Explicit costs a few
characters and cannot silently miss one.A parameter that takes several has no named slot. Put the references in args instead: a
FileRef converts to Json as the upload reference the model reads.upload_bytes()
The same result as upload_file(), for a caller who has the bytes rather than a
path — a frame just rendered, a buffer just decoded.
Signature
data is borrowed for the call only.
Example
request_schema()
Signature
Recordings
request_clip()
Asks for a clip covering the last duration_seconds of the session.
Signature
Resolves when the platform has accepted the request, which is not the same as the clip being
ready —
Clip::download() is what waits for that.
Example
request_recording()
Signature
Tracks
track()
The track called name, as a Track — the only way to push frames into
one, receive its frames, or pause it.
Signature
Example
NotFoundError, listing what the session does declare, for a name that is not among them.
Before the session has declared anything, any name is allowed: there is nothing yet to contradict,
and the refusals that matter happen when a handler is registered or a frame is pushed.
tracks()
Every track the session declared, as a TrackList — for
discovery, and for a caller who would rather not hardcode a name.
Signature
Example
connect().
set_bitrate()
Bounds what the whole connection may allocate, in bits per second.
Signature
Definition
Throws on a session that is not
Ready. The bounds outlive a reconnect.
get_stats()
A snapshot of the live connection: RTT, jitter, packet loss, bitrates, the transport ICE selected,
and the WebRTC engine’s own per-stream counters.
Signature
ConnectionStats. Throws on a session that is
not Ready.
Example
Events
Each method takes onehandler callback. Its argument type is listed in the table below.
Every on_* returns a Subscription: an RAII token that
unregisters the handler when it goes out of scope.
Signature
connect() to catch the first capabilities and the first
session id. Capabilities are delivered after the declared tracks are refreshed, so
tracks() is already current inside that handler.
Example
on_message never has to filter the platform’s out of it.
There is no client-wide frame event. Media is delivered per track, through
Track::on_frame() — a single handler fed every incoming
track of a kind at once could not tell them apart.on_error hands you a ReactorError, the same type a failed call throws. Match on code(), or
branch on recoverable() when the specific code does not matter. See
ReactorError.time_micros()
The engine’s monotonic clock, in microseconds — the epoch a frame’s capture time is read in.
Signature
Example