This Node.js example demonstrates how to receive real-time audio, video, screen share, transcript, and chat data from a Zoom session using the Video SDK service. The nodejs server side code connects to Zoom's Video SDK infrastructure via WebSocket, handles webhook events
- Node.js v18 or higher
- Zoom Video SDK credentials (SDK Key and Secret)
- Install dependencies:
npm install- Create a
.envfile in the root directory with the following content: Refer to .env.example for reference
ZOOM_SECRET_TOKEN=your_secret_token
ZOOM_CLIENT_ID=your_client_id
ZOOM_CLIENT_SECRET=your_client_secret
PORT=3000
WEBHOOK_PATH=/webhook
- Start the server:
node index.js- Expose your local server using a tool like ngrok:
ngrok http 3000- Set your Video SDK app's webhook URL to point to your ngrok endpoint, e.g.:
https://<your-ngrok-subdomain>.ngrok.io/webhook
- Start a Video SDK session and begin streaming.
.
├── index.js # Main entry point that handles webhook events, WebSocket connections, and media processing
├── .env # Secrets and config variables (not committed)
├── .env.example # Template for environment variables
├── package.json # Dependencies and scripts
├── package-lock.json # Dependency lock file
├── .gitignore # Git ignore rules
├── logs/ # Folder for log files
├── node_modules/ # Dependencies (not committed)
└── recordings/ # Folder to store media files (auto-created)
This sample is implemented as a single index.js file that contains all the functionality:
- Environment Configuration - Loads settings from .env file
- HTTP Server - Express server handling webhook endpoints
- WebSocket Management - Handles signaling and media connections to Zoom
- Media Processing - Processes incoming audio, video, and transcript data
System Communication
┌──────────────┐
│ Zoom SDK │ ─────► HTTP Webhooks
└──────────────┘ (session events)
│
▼
┌──────────────┐
│ index.js │◄────────── WebSocket connections
└──────────────┘ (signaling + media streams)
│
▼
┌──────────────┐
│ Client Apps │ ◄───────── Real-time data
└──────────────┘ (processed media streams)
- This example focuses on processing Video SDK events and saving data based on message types.
- Handshakes and keep-alive messages are handled automatically for both signaling and media connections.
- Ensure your Video SDK app is configured to send the appropriate webhook events.
- Video SDK must be enabled for your account.
- The server listens for Video SDK webhook events from Zoom (
/webhookendpoint). - On receiving a
session.sdk_startedevent, it connects to Zoom's signaling server via WebSocket. - Upon successful handshake, it connects to the media WebSocket server.
- The server listens for and processes incoming media messages
- msg_type 14: Audio
- msg_type 15: Video
- msg_type 16: Screen Share (Image/Video formats)
- msg_type 17: Transcript
- msg_type 18: Chat
Chat data is a UTF-8 JSON object inside content.data; the handler logs its
message, operation, session, sender, receiver, file, and deletion metadata.
The signaling subscription also includes chat-group events 10 through 14.
The project runs the JavaScript Video SDK RTMS sample. Its multi-stage Dockerfile keeps build tooling out of the final runtime image and does not hard-code a CPU architecture.
Build and run it from the rtms-samples repository root:
docker build -f video-sdk/vsdk_working_js/Dockerfile -t rtms-video-sdk-vsdk_working_js .
docker run --rm --env-file video-sdk/vsdk_working_js/.env -p 3000:3000 rtms-video-sdk-vsdk_working_jsRun the build from the repository root because the Dockerfile uses repository-relative paths. Runtime secrets are supplied with --env-file and are excluded from the image build context.
Normal Zoom webhook deliveries are verified against the exact raw request body using
x-zm-signature and x-zm-request-timestamp. Configure ZOOM_SECRET_TOKEN with the
Marketplace app's webhook Secret Token. Requests with missing, invalid, or stale
signatures are rejected; the default replay window is 300 seconds and can be changed
with WEBHOOK_TIMESTAMP_TOLERANCE_SECONDS.