This example demonstrates how to receive audio, video, screen share, transcript, and chat from a Zoom meeting using RTMS. It logs the received media type without printing the raw media payload.
- Python 3.7 or higher
- A Zoom account with RTMS enabled
- Zoom App credentials (Client ID and Client Secret)
- Zoom Secret Token for webhook validation
- Install the required dependencies:
pip install -r requirements.txt- Create a
.envfile in the same directory with your Zoom credentials:
ZOOM_SECRET_TOKEN=your_secret_token
ZOOM_CLIENT_ID=your_client_id
ZOOM_CLIENT_SECRET=your_client_secret
MEDIA_SOCKET_CONNECTION_MODE=split
MEDIA_TYPES_FLAG=11
MEDIA_TYPES_FLAG combines audio (1), video (2), screen share (4),
transcript (8), and chat (16). Split mode expands the mask into separate
media sockets, so 11 opens audio, video, and transcript sockets with handshake
values 1, 2, and 8.
For a single unified media socket, use:
MEDIA_SOCKET_CONNECTION_MODE=unified
MEDIA_TYPES_FLAG=32Unified mode requires 32; combined masks such as 11 must use split mode.
- Start the server:
gunicorn index:app --bind 0.0.0.0:3000- The server will start on port 3000. You'll need to expose this port to the internet using a tool like ngrok:
ngrok http 3000-
Configure your Zoom App's webhook URL to point to your exposed endpoint (e.g.,
https://your-ngrok-url/webhook) -
Start a Zoom meeting and enable RTMS. The server will receive and print the incoming audio data.
- The server listens for webhook events from Zoom
- When RTMS starts, it establishes WebSocket connections to Zoom's signaling and media servers
- Split mode opens one WebSocket for each selected media type; unified mode uses
server_urls.all - The audio/video/transcript msg type is printed to the console
- This is a basic example that checks the msg type and prints the data type received. In a production environment, you would typically process or save this data.
- The server handles both signaling and media WebSocket connections
- Keep-alive messages are automatically responded to maintain the connection
The project runs the Python webhook-based RTMS boilerplate. 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 boilerplate/working_python/Dockerfile -t rtms-boilerplate-working_python .
docker run --rm --env-file boilerplate/working_python/.env -p 3000:3000 rtms-boilerplate-working_pythonRun 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.