Skip to content

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:

  1. Signaling handshake — connects to the serverUrl from the meeting.rtms_started webhook and sends SIGNALING_HAND_SHAKE_REQ (msg_type 1) signed with hex(HMAC-SHA256("clientId,meetingUuid,rtmsStreamId", clientSecret)).
  2. Media handshake — connects to the audio media server URL from the signaling response (server_urls.audio, falling back to server_urls.all) and sends DATA_HAND_SHAKE_REQ (msg_type 3) requesting raw L16 PCM audio.
  3. Client ready — acknowledges with CLIENT_READY_ACK (msg_type 7) on the signaling socket, after which MEDIA_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

Implements

Constructors

Constructor

new ZoomRtmsInput(config): ZoomRtmsInput;

Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:549

Creates a new ZoomRtmsInput instance.

Parameters

ParameterTypeDescription
configZoomRtmsInputConfigProvider 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

PropertyModifierTypeDefault valueDescriptionDefined in
rolesreadonlyreadonly ProviderRole[]undefinedPipeline 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
typereadonlyProviderType'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

ParameterTypeDescription
sessionPartial<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

ParameterTypeDescription
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:

  1. Opens the signaling WebSocket and sends SIGNALING_HAND_SHAKE_REQ (msg_type 1) with the HMAC-SHA256 signature.
  2. On success, opens the media WebSocket to server_urls.audio (or server_urls.all) and sends DATA_HAND_SHAKE_REQ (msg_type 3) requesting raw L16 audio.
  3. On success, sends CLIENT_READY_ACK (msg_type 7) on the signaling socket — Zoom then starts pushing MEDIA_DATA_AUDIO messages.

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

AudioInputProvider.dispose


getMetadata()

getMetadata(): AudioMetadata;

Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:726

Get the audio format metadata for the meeting audio.

Returns

AudioMetadata

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

AudioInputProvider.initialize


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

AudioInputProvider.isActive


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

AudioInputProvider.isReady


onAudio()

onAudio(callback): void;

Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:711

Register a callback to receive audio chunks.

Parameters

ParameterTypeDescription
callback(chunk) => voidFunction 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

AudioInputProvider.onAudio


onSpeakerAudio()

onSpeakerAudio(callback): void;

Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:960

Register a callback for per-participant audio.

Parameters

ParameterTypeDescription
callback(userId, userName, chunk) => voidInvoked 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

AudioInputProvider.pause


resume()

resume(): void;

Defined in: src/providers/io/zoom/ZoomRtmsInput.ts:683

Resume audio emission after a pause.

Returns

void

See

pause

Implementation of

AudioInputProvider.resume


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

AudioInputProvider.start


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.

Implementation of

AudioInputProvider.stop

© 2026 CompositeVoice. All rights reserved.

Font size
Contrast
Motion
Transparency