Generated banner for Zoom Rtms
Generated logo for Zoom Rtms

Zoom Rtms

OpenAIOfficialCreated by ZoomDistributed by OpenAI

  • Skill
  • Tool integration
  • Automation and integrations
  • MIT
  • No issues found

From the author

Use when using RTMS.
— the description by Zoom

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The zoom-rtms skill provides the necessary protocols and architectural guidance for integrating Zoom Realtime Media Streams. It covers the WebSocket-based connection lifecycle, including signaling and media handshakes, heartbeat management, and reconnection strategies. The skill supports processing various media types such as audio, video, screen sharing, transcripts, and chat, while providing reference data for message types and event enums.

What it does

  • Establishes WebSocket connections for signaling and media streams.
  • Handles media handshake requests for audio, video, screen share, transcript, and chat data.
  • Provides reference tables for RTMS message types and event enums.
  • Defines mandatory heartbeat and reconnection logic for stream stability.
  • Supports configuration for transcript language identification.
  • Outlines the process for extracting stream IDs and generating HMAC-SHA256 signatures.

When to use it

  • When you need to ingest raw meeting or contact center media into a backend pipeline.
  • When building services for transcription, AI analysis, or recording of Zoom sessions.
  • When you need to subscribe to specific meeting events or participant media streams.
  • When you require programmatic access to media data without a visible participant bot.

Advantages

  • Provides a structured approach to managing the complex WebSocket lifecycle.
  • Includes comprehensive references for message types and event handling.
  • Offers clear guidance on signature generation and security requirements.
  • Enables granular control over media subscription and transcript settings.

Usage examples

“How do I initiate a connection to an RTMS stream?”
The agent will guide you through receiving the rtms_started webhook, generating an HMAC-SHA256 signature, and performing the signaling and media handshakes.
“What is the correct way to handle heartbeats in RTMS?”
The agent will explain that you must respond to msg_type 12 (Keep Alive Request) with msg_type 13 (Keep Alive Response) to maintain the connection.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/openai/zoom-rtms/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip zoom-rtms.zip -d .agents/skills

Documentation by Zoom

Zoom Realtime Media Streams

Use this skill when the integration needs real-time meeting or contact-center media as a backend stream. If the workflow needs a visible participant bot, compare against build-zoom-bot and zoom-meeting-sdk-linux before choosing RTMS.

Workflow

  1. Confirm the source surface: Meetings RTMS, Contact Center voice media, or another documented RTMS stream.

  2. Decide whether RTMS is sufficient or whether a Meeting SDK bot is required for participant identity, meeting controls, or UI-visible behavior.

  3. Implement the WebSocket lifecycle first: event subscription, connection validation, media start, heartbeat, reconnect, and shutdown.

  4. Process media types intentionally: audio, video, screen share, chat, live transcript, and metadata have different payload and timing constraints.

  5. Design downstream pipelines for buffering, transcription, AI analysis, recording, or tool invocation.

  6. Debug by isolating app setup, webhook/event delivery, stream authorization, network connectivity, and media payload decoding.

References

Files

references/quickstart.md

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 Develop → Build App

  3. Choose General App → User-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 Develop → Build 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:

ProductHow to StartWebhook Event
MeetingZoom client, REST API, Zoom App SDK, or autostart (zoom.us settings)meeting.rtms_started
WebinarZoom client, REST API, Zoom App SDK, or autostart (zoom.us settings)webinar.rtms_started
Video SDKVideo SDK client or REST APIsession.rtms_started
Zoom Contact Center VoiceProduct-specific RTMS/ZCC Voice flowProduct-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

Requirements and compatibility

Written for: OpenAI Codex

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Zoom
Publisher
OpenAI (Official)
Distributed by
OpenAI
Source
openai/plugins · plugins/zoom/skills/rtms · commit d420d13
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from plugins/zoom/LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Zoom or OpenAI.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download zoom-rtms.zip