ZoomRtmsInput
Zoom Realtime Media Streams (RTMS) input provider — streams live meeting audio into the CompositeVoice pipeline.
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:461
Zoom Realtime Media Streams (RTMS) input provider — streams live meeting audio into the CompositeVoice pipeline.
Remarks
ZoomRtmsInput is a single-role ('input'), receive-only, server-side provider. It implements the RTMS WebSocket protocol directly with zero peer dependencies:
- Signaling handshake — connects to the
serverUrlfrom themeeting.rtms_startedwebhook and sendsSIGNALING_HAND_SHAKE_REQ(msg_type 1) signed withhex(HMAC-SHA256("clientId,meetingUuid,rtmsStreamId", clientSecret)). - Media handshake — connects to the audio media server URL from the signaling response (
server_urls.audio, falling back toserver_urls.all) and sendsDATA_HAND_SHAKE_REQ(msg_type 3) requesting raw L16 PCM audio. - Client ready — acknowledges with
CLIENT_READY_ACK(msg_type 7) on the signaling socket, after whichMEDIA_DATA_AUDIO(msg_type 14) messages flow on the media socket.
Keep-alive requests (msg_type 12) on either socket are answered automatically (msg_type 13, echoing the timestamp). Stream/session state updates (msg_type 8/9) are tracked; when the stream terminates or the session stops, both sockets are closed (media first, then signaling).
Because RTMS cannot play audio into the meeting, pair this provider with NullOutput — or a platform output of your choice — for the 'output' role.
Data-flow diagram:
meeting.rtms_started ──▶ connect() ──▶ signaling WS ──▶ media WS
│
MEDIA_DATA_AUDIO (base64 L16) │
▼
active && !paused ──▶ callback(AudioChunk) ──▶ STT
│
no: drop
Example
import { ZoomRtmsInput } from 'composite-voice';
const zoom = new ZoomRtmsInput({
clientId: process.env.ZOOM_CLIENT_ID!,
clientSecret: process.env.ZOOM_CLIENT_SECRET!,
dataOpt: 'per-participant',
});
await zoom.initialize();
zoom.onAudio((chunk) => console.log(`audio: ${chunk.data.byteLength} bytes`));
zoom.onSpeakerAudio((userId, userName) => console.log(`${userName} is speaking`));
zoom.start();
// From the meeting.rtms_started webhook:
await zoom.connect({ meetingUuid, rtmsStreamId, serverUrl });
See
- ZoomRtmsInputConfig for configuration options
- ZoomRtmsSession for the webhook-derived session parameters
- ZOOM_RTMS_STATUS_CODES for handshake status-code names
Implements
Constructors
Constructor
new ZoomRtmsInput(config): ZoomRtmsInput;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:549
Creates a new ZoomRtmsInput instance.
Parameters
| Parameter | Type | Description |
|---|---|---|
config | ZoomRtmsInputConfig | Provider configuration. clientId and clientSecret are required (validated in initialize()). |
Returns
ZoomRtmsInput
Remarks
The constructor only stores configuration; no network activity happens until connect() is called.
Example
const zoom = new ZoomRtmsInput({
clientId: process.env.ZOOM_CLIENT_ID!,
clientSecret: process.env.ZOOM_CLIENT_SECRET!,
sampleRate: 16000,
});
Properties
| Property | Modifier | Type | Default value | Description | Defined in |
|---|---|---|---|---|---|
roles | readonly | readonly ProviderRole[] | undefined | Pipeline roles covered by this provider. Remarks ZoomRtmsInput covers only the 'input' slot. RTMS is receive-only, so a separate output provider (e.g. NullOutput) is required. | src/providers/io/zoom/ZoomRtmsInput.ts:478 |
type | readonly | ProviderType | 'websocket' | Communication type for this provider. Remarks 'websocket' — the provider holds two persistent WebSocket connections (signaling and media) for the lifetime of the stream. | src/providers/io/zoom/ZoomRtmsInput.ts:469 |
Methods
attach()
attach(session): Promise<void>;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:758
Attach the RTMS session for a started stream — alias for connect().
Parameters
| Parameter | Type | Description |
|---|---|---|
session | Partial<ZoomRtmsSession> | Session parameters from the meeting.rtms_started webhook (meetingUuid, rtmsStreamId, serverUrl). |
Returns
Promise<void>
Remarks
Implements the AttachableInputProvider contract so the session parameters from a meeting.rtms_started webhook can be passed straight to CompositeVoice.startListening(session).
Example
await voice.startListening({
meetingUuid: payload.object.meeting_uuid,
rtmsStreamId: payload.object.rtms_stream_id,
serverUrl: payload.object.server_urls,
});
connect()
connect(session?): Promise<void>;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:798
Connect to an RTMS stream and start receiving meeting audio.
Parameters
| Parameter | Type | Description |
|---|---|---|
session? | Partial<ZoomRtmsSession> | Session parameters from the meeting.rtms_started webhook. Falls back to meetingUuid/rtmsStreamId/serverUrl from the constructor config when omitted. |
Returns
Promise<void>
Remarks
Performs the full RTMS connection flow:
- Opens the signaling WebSocket and sends
SIGNALING_HAND_SHAKE_REQ(msg_type 1) with the HMAC-SHA256 signature. - On success, opens the media WebSocket to
server_urls.audio(orserver_urls.all) and sendsDATA_HAND_SHAKE_REQ(msg_type 3) requesting raw L16 audio. - On success, sends
CLIENT_READY_ACK(msg_type 7) on the signaling socket — Zoom then starts pushingMEDIA_DATA_AUDIOmessages.
May be called before or after start(); audio is only emitted while the provider is active.
Throws
ProviderConnectionError Thrown when the provider is not initialized, session parameters are missing, either WebSocket fails to connect, or a handshake returns a non-zero status_code (the message includes the symbolic name from ZOOM_RTMS_STATUS_CODES).
Example
await zoom.connect({
meetingUuid: payload.object.meeting_uuid,
rtmsStreamId: payload.object.rtms_stream_id,
serverUrl: payload.object.server_urls,
});
disconnect()
disconnect(): Promise<void>;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:926
Gracefully disconnect from the RTMS stream.
Returns
Promise<void>
Remarks
Closes the media socket first, then the signaling socket, mirroring the order Zoom recommends for a clean shutdown. Safe to call when not connected (no-op). Typically invoked from the meeting.rtms_stopped webhook handler or on application shutdown.
dispose()
dispose(): Promise<void>;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:611
Dispose of the provider and release all resources.
Returns
Promise<void>
Remarks
Disconnects both WebSockets (media first, then signaling), clears all callbacks, and resets internal state. The instance can be re-initialized afterwards with initialize().
Implementation of
getMetadata()
getMetadata(): AudioMetadata;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:726
Get the audio format metadata for the meeting audio.
Returns
AudioMetadata describing linear16 mono audio at the configured sample rate (default 16000 Hz).
Remarks
RTMS delivers raw L16 PCM (16-bit signed little-endian), mono, at the configured sample rate. Used by the pipeline to auto-configure the downstream STT provider.
Implementation of
AudioInputProvider.getMetadata
getSessionState()
getSessionState(): number | null;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:990
Get the last session state reported by Zoom.
Returns
number | null
The numeric session state, or null if none received yet.
Remarks
Updated from SESSION_STATE_UPDATE (msg_type 9) messages. Values: 0 = INACTIVE, 1 = INITIALIZE, 2 = STARTED, 3 = PAUSED, 4 = RESUMED, 5 = STOPPED.
getStreamState()
getStreamState(): number | null;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:976
Get the last stream state reported by Zoom.
Returns
number | null
The numeric stream state, or null if none received yet.
Remarks
Updated from STREAM_STATE_UPDATE (msg_type 8) messages. Values: 0 = INACTIVE, 1 = ACTIVE, 2 = INTERRUPTED, 3 = TERMINATING, 4 = TERMINATED, 5 = PAUSED, 6 = RESUMED.
initialize()
initialize(): Promise<void>;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:576
Initialize the provider and validate the configuration.
Returns
Promise<void>
Remarks
Validates that clientId and clientSecret are present — they are needed to sign every handshake. No network connection is made here; call connect() when the meeting.rtms_started webhook arrives.
Throws
ProviderInitializationError Thrown when clientId or clientSecret is missing, or when the configured sampleRate is not one of 8000/16000/32000/48000.
Implementation of
isActive()
isActive(): boolean;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:694
Check whether the provider is actively emitting audio.
Returns
boolean
true when started and not paused.
Implementation of
isConnected()
isConnected(): boolean;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:935
Check whether the provider is connected to an RTMS stream.
Returns
boolean
true when both handshakes completed and the sockets are open.
isReady()
isReady(): boolean;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:631
Check whether the provider has been initialized.
Returns
boolean
true when initialize has completed and dispose has not yet been called.
Implementation of
onAudio()
onAudio(callback): void;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:711
Register a callback to receive audio chunks.
Parameters
| Parameter | Type | Description |
|---|---|---|
callback | (chunk) => void | Function invoked with each AudioChunk while the provider is active. |
Returns
void
Remarks
Only one callback can be registered at a time; subsequent calls replace the previous callback. With dataOpt: 'per-participant', chunks from different speakers interleave on this callback — use onSpeakerAudio() to attribute chunks to participants.
Implementation of
onSpeakerAudio()
onSpeakerAudio(callback): void;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:960
Register a callback for per-participant audio.
Parameters
| Parameter | Type | Description |
|---|---|---|
callback | (userId, userName, chunk) => void | Invoked with the Zoom user_id, user_name, and the AudioChunk for each audio message. |
Returns
void
Remarks
Invoked alongside the main onAudio() callback with the participant attribution carried by each MEDIA_DATA_AUDIO message. Most useful with dataOpt: 'per-participant', where each chunk belongs to exactly one speaker; with the default mixed stream, Zoom reports the mixed source. Emission follows the same active/paused gating as onAudio().
Example
zoom.onSpeakerAudio((userId, userName, chunk) => {
console.log(`${userName ?? userId}: ${chunk.data.byteLength} bytes`);
});
pause()
pause(): void;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:672
Temporarily pause audio emission without stopping the provider.
Returns
void
Remarks
Audio received while paused is silently dropped. Resume with resume().
Implementation of
resume()
resume(): void;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:683
Resume audio emission after a pause.
Returns
void
See
Implementation of
start()
start(): void;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:646
Start emitting audio chunks to the registered callback.
Returns
void
Remarks
start() only gates emission — it does not open the RTMS connection. Call connect() (before or after start()) to establish the stream. Audio received while stopped is silently dropped.
Implementation of
stop()
stop(): void;
Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:660
Stop emitting audio chunks.
Returns
void
Remarks
The RTMS sockets stay open — audio received while stopped is silently dropped, and emission can be resumed with start(). Use disconnect() to close the stream.