Skip to main content
A Track is a named media stream declared by the model. Direction is from the client’s perspective: RECVONLY receives from the model, and SENDONLY sends to it. TrackKind is VIDEO or AUDIO. The API reference lists every operation. The snippets below assume a connected Reactor reactor and imports from inc.reactor.sdk.android.

Find a track

Look up a known name after connecting, or filter the declared tracks:
tracks is empty before the session declares its tracks and after disconnecting. It is a List<Track>, so you can iterate or filter it like any list. track(name) throws InvalidStateException if that name has not been declared, including before connecting, and the message lists the names that were. one() requires exactly one match. A track exposes name, kind, direction, and an optional mid.

Receive frames

Register a handler on a receiving track. Name the parameter type: onFrame is overloaded for video and audio, so an untyped lambda is ambiguous.
Call removeHandlers() on the track when you no longer need it. Registering a video handler on an audio track, or any frame handler on a sending track, throws ReactorException.
Frame memory is valid only while the handler runs. The native layer frees it as soon as the handler returns. To keep pixels or samples, call VideoFrame.copyPixels() or AudioFrame.copySamples() inside the handler.
Frame handlers run inline on the SDK’s media delivery thread, not on the control-event dispatcher. Blocking there is the backpressure: while a video handler runs, only the newest frame is kept, so a slow handler drops frames instead of building a queue. Convert or draw the frame inside the handler, and post only the result to the UI. VideoRenderer in the media module draws frames on a SurfaceView. A video’s timestampUs uses the sender’s clock, so compare it only with timestamps from that same sender. userData is a copy of the sender’s tag and can outlive the handler.

Send frames

Choose a sending track and call publish() before pushing data. Track names depend on the model; this example finds its single video input:
Video input must be a direct ByteBuffer with exactly width * height * 4 bytes remaining, in B, G, R, A order. An optional userData tag follows the dimensions. CameraCapture in the media module produces frames in this format. For audio, call pushFrame(pcm, samplesPerChannel, sampleRate, channels) on a published audio input. pcm is a direct ByteBuffer of interleaved signed 16-bit samples, with exactly samplesPerChannel * channels * 2 bytes remaining. Supported rates are 8,000, 16,000, 24,000, 32,000, 44,100, and 48,000 Hz, with one or two channels. published reports whether a sender is ready. publishState is UNPUBLISHED, PUBLISHING, or PUBLISHED. Pushing before publication completes, after unpublishing, to an undeclared track, or to a receiving track throws, naming the fix. Publication does not survive reconnect: call publish() again before sending more frames.

Pause and resume

pause() and resume() are suspend functions on a receiving track; paused reports the current state. Nothing is generated for a paused track. On a sending track, publish() and unpublish() start and stop sending instead. The base SDK does not capture or play device media. The optional reactor-sdk-android-media module adds camera, microphone, speaker, and rendering helpers.