Files
2026-07-13 12:20:06 +08:00

6.6 KiB

RTMS - Quickstart

Get started with Zoom Realtime Media Streams.

Prerequisites

  1. Node.js 20.3.0+ (24 LTS recommended)
  2. Zoom General App (for meetings/webinars), Video SDK App (for Video SDK), or approved Contact Center / RTMS integration for Zoom Contact Center Voice
  3. Webhook endpoint configured
  4. Server to handle WebSocket connections

Environment Setup

# .env file
ZOOM_CLIENT_ID=your_client_id          # From App Credentials
ZOOM_CLIENT_SECRET=your_client_secret  # From App Credentials
ZOOM_SECRET_TOKEN=your_webhook_token   # From Feature → Webhook

Clone the official samples and use RTMSManager:

git clone https://github.com/zoom/rtms-samples.git
cd rtms-samples/boilerplate/working_js
npm install
import { RTMSManager } from './library/javascript/rtmsManager/RTMSManager.js';
import express from 'express';
import crypto from 'crypto';

const app = express();
app.use(express.json());

// Initialize with credentials
await RTMSManager.init({
  credentials: {
    meeting: {
      clientId: process.env.ZOOM_CLIENT_ID,
      clientSecret: process.env.ZOOM_CLIENT_SECRET,
      secretToken: process.env.ZOOM_SECRET_TOKEN,
    }
  },
  // Use bitmask: AUDIO(1) | TRANSCRIPT(8) = 9
  mediaTypes: RTMSManager.MEDIA.AUDIO | RTMSManager.MEDIA.TRANSCRIPT,
  logging: 'info'
});

// Handle media events
RTMSManager.on('audio', ({ buffer, userName }) => {
  console.log(`Audio from ${userName}: ${buffer.length} bytes`);
});

RTMSManager.on('transcript', ({ text, userName }) => {
  console.log(`${userName}: ${text}`);
});

RTMSManager.on('chat', ({ text, userName }) => {
  console.log(`[Chat] ${userName}: ${text}`);
});

RTMSManager.on('sharescreen', ({ buffer, userName }) => {
  console.log(`Screen share from ${userName}`);
});

// CRITICAL: Respond 200 IMMEDIATELY before any processing!
app.post('/webhook', (req, res) => {
  res.status(200).send();  // FIRST!
  
  const { event, payload } = req.body;
  
  // Handle URL validation challenge
  if (event === 'endpoint.url_validation') {
    const hash = crypto
      .createHmac('sha256', process.env.ZOOM_SECRET_TOKEN)
      .update(payload.plainToken)
      .digest('hex');
    return res.json({ plainToken: payload.plainToken, encryptedToken: hash });
  }
  
  // Feed RTMS events to manager
  RTMSManager.handleEvent(event, payload);
});

await RTMSManager.start();
app.listen(3000, () => console.log('RTMS server on port 3000'));

Option 2: @zoom/rtms SDK

npm install @zoom/rtms express
import rtms from "@zoom/rtms";

const RTMS_EVENTS = ["meeting.rtms_started", "webinar.rtms_started", "session.rtms_started"];

rtms.onWebhookEvent(({ event, payload }) => {
  if (!RTMS_EVENTS.includes(event)) return;
  
  const client = new rtms.Client();
  
  client.onAudioData((data, timestamp, metadata) => {
    console.log(`Audio from ${metadata.userName}`);
  });
  
  client.onTranscriptData((data, timestamp, metadata) => {
    console.log(`${metadata.userName}: ${data}`);
  });
  
  client.onChatData((data, timestamp, metadata) => {
    console.log(`[Chat] ${metadata.userName}: ${data}`);
  });
  
  client.onScreenShareData((data, timestamp, metadata) => {
    console.log(`Screen share from ${metadata.userName}`);
  });
  
  // SDK accepts both meeting_uuid and session_id transparently
  client.join(payload);
});

Zoom App Setup Steps

For Meetings and Webinars (General App)

  1. Go to marketplace.zoom.us
  2. Click DevelopBuild App
  3. Choose General AppUser-Managed
  4. Features → Access → Enable Event Subscription
  5. Add Events → Search "rtms" → Select RTMS endpoints:
    • meeting.rtms_started
    • meeting.rtms_stopped
    • webinar.rtms_started (if using webinars)
    • webinar.rtms_stopped (if using webinars)
  6. Scopes → Add Scopes → Search "rtms" → Add:
    • meeting:read:meeting_audio
    • meeting:read:meeting_video
    • meeting:read:meeting_transcript
    • meeting:read:meeting_chat
    • webinar:read:webinar_audio (if using webinars)
    • webinar:read:webinar_video (if using webinars)
    • webinar:read:webinar_transcript (if using webinars)
    • webinar:read:webinar_chat (if using webinars)

For Video SDK (Video SDK App)

  1. Go to marketplace.zoom.us
  2. Click DevelopBuild App
  3. Choose Video SDK App
  4. Add Events:
    • session.rtms_started
    • session.rtms_stopped
  5. Use SDK Key and SDK Secret for authentication (not OAuth credentials)

How to Start RTMS

RTMS must be started for each meeting/webinar/session. Options:

Product How to Start Webhook Event
Meeting Zoom client, REST API, Zoom App SDK, or autostart (zoom.us settings) meeting.rtms_started
Webinar Zoom client, REST API, Zoom App SDK, or autostart (zoom.us settings) webinar.rtms_started
Video SDK Video SDK client or REST API session.rtms_started
Zoom Contact Center Voice Product-specific RTMS/ZCC Voice flow Product-specific RTMS/ZCC Voice events

Webinar note: Panelists have full audio/video streams. Attendee streams may not be available individually.

March 2026 note: transcript handshakes now support src_language plus enable_lid, media socket keep-alive tolerance is now about 65s, and RTMS supports one selected participant camera stream at a time via VIDEO_SINGLE_INDIVIDUAL_STREAM + VIDEO_SUBSCRIPTION_REQ.

Deployment with Reverse Proxy

When deploying behind nginx with a path prefix (e.g., /my-app/):

  1. Socket.IO path must match nginx config:
const socketPath = window.location.pathname.includes('/my-app') 
    ? '/my-app/rtms-socket' 
    : '/rtms-socket';
const socket = io({ path: socketPath });
  1. API calls must use relative paths:
const basePath = window.location.pathname.replace(/\/$/, '');
fetch(`${basePath}/api/sessions`);  // NOT fetch('/api/sessions')
  1. Nginx WebSocket proxy:
location /my-app/rtms-socket {
    proxy_pass http://YOUR_RTMS_BACKEND_HOST:3000/rtms-socket;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

Next Steps

  • Media Types - All 5 data types (audio, video, transcript, chat, screen share)
  • Connection - WebSocket protocol & message types
  • Webhooks - Event subscription details

Resources