Zoom RTMS

Zoom RTMS allows receiving audio, video, and transcripts from a meeting without a bot!

📘

Limitations

  • Requires a properly configured Zoom App, which will need to go through Zoom's application process
  • You can only receive data (no sending messages or Output Media)
  • Zoom RTMS doesn't provide chat messages (currently)
  • Zoom RTMS doesn't support Breakout Rooms (currently)

Zoom Setup

  1. Make sure you've updated your Zoom client to the latest version

  2. Create or edit your Zoom App

  3. In the top right, click Develop -> Build App


  4. Select General App


  5. Copy your Client ID and Client Secret


  6. Click on "Basic Information" (below "Build your app")

    1. Add a OAuth Redirect URL (e.g. https://my-random-domain.ngrok-free.app/oauth-callback/zoom)

  7. Click on "Access" (below "Build your app" and "Features" on the left)

  8. Copy your Secret Token


  9. Enable "Event Subscription"

    1. Name the webhook (e.g. My Recall RTMS webhook)

      1. Choose option "Webhook"

      2. Click "Add Events"

        1. Search "RTMS" and select "Select All RTMS"

          1. In "Event notification endpoint URL"

            1. Add the URL where you want to receive a webhook for Zoom RTMS notifications
            2. To get started, we recommend using an Ngrok static domain followed by /zoom-webhook
              1. e.g. https://my-random-domain.ngrok-free.app/zoom-webhook

          2. Select "Save"

  10. Select "Scopes" (below "Build your app" on the left), then +Add Scopes

    1. Search RTMS
    2. Under "Meeting" enable all the real-time media streams scopes:
      1. meeting:read:meeting_audio
      2. meeting:read:meeting_chat
      3. meeting:read:meeting_transcript
      4. meeting:read:meeting_screenshare
      5. meeting:read:meeting_video
    3. Under "RTMS" enable:
      1. rtms:read:rtms_started
      2. rtms:read:rtms_stopped


    1. Click "Done"
  11. Click "Local Test" (below "Add your App" on the left)

    1. Click "Add App Now"


    2. You will see a confirmation prompt, click "Allow"

    3. You will get redirected, the end URL may show an error but that's OK! We now have a Zoom RTMS App!

  12. Go to your Zoom App Settings

    1. Under "Auto-start apps that access shared realtime meeting content" click "Choose an app to auto-start"
      1. In the dropdown select your new app

Your Zoom App is now setup for RTMS!

Quickstart

There are multiple ways to connect to a Zoom meeting with RTMS, but we recommend beginning with the auto-start workflow.

Once a meeting starts, Zoom will call the webhook you provided in the Event notification endpoint URL, we'll assume the path is zoom-webhook. When Zoom provides a meeting.rtms_started event at that endpoint your server must:

  • Generate an HMAC signature
  • POST the Recall /api/v1/meeting_direct_connect endpoint with:
    • The fields that Zoom provided
    • An HMAC signature from your client secret
    • Any additional options consistent with our Create Bot Endpoint
app.post('/zoom-webhook', async (req, res) => {
  const { event, payload } = req.body;

  // Handle URL validation event
  if (event === 'endpoint.url_validation' && payload?.plainToken) {
    // Generate a hash for URL validation using the plainToken and a secret token
    const hash = crypto
      .createHmac('sha256', ZOOM_SECRET_TOKEN)
      .update(payload.plainToken)
      .digest('hex');
    console.log('Responding to URL validation challenge');
    return res.json({
      plainToken: payload.plainToken,
      encryptedToken: hash,
    });
  }

  // Handle RTMS started event
  if (event === 'meeting.rtms_started') {
   await startRecordingRtms(event, payload);
  }

  // Respond with HTTP 200 status
  res.sendStatus(200);
});
async function startRecordingRtms(payload) {
  // Start the recording via Recall
  const { meeting_uuid, rtms_stream_id, server_urls } = payload;
  const response = await fetch(`https://us-east-1.recall.ai/api/v1/meeting_direct_connect`, {
    method: 'POST',
    headers: {
      'Authorization': `Token ${RECALL_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      zoom_rtms: {
        meeting_uuid,
        rtms_stream_id,
        server_urls,
        signature: generateSignature(meeting_uuid, rtms_stream_id)
      },
      // Other options (e.g. recordings, real time events, webhooks, transcriptions)
      // are consistent with https://docs.recall.ai/reference/bot_create
      recording_config: {
        video_mixed_mp4: {}
      }
    })
  });
  
  const recallRtms = await response.json();
  
  await saveRecordingToDatabase({
    recallId: recallRtms.id,
    status: recallRtms.status.code,
  });
}
function generateSignature(meetingUuid, streamId) {
  // Create a message string and generate an HMAC SHA256 signature
  const message = `${CLIENT_ID},${meetingUuid},${streamId}`;
  return crypto.createHmac('sha256', CLIENT_SECRET).update(message).digest('hex');
}

Get the Recording

To get any artifacts from the meeting, you’ll use the id received when creating the meeting_direct_connect to query the Retrieve Meeting Direct Connect endpoint to receive its current state and any artifacts of recordings or transcriptions

const meetingObj = await fetch(`https://us-east-1.recall.ai/api/v1/meeting_direct_connect/${my_mdc_id}`, {
  headers: {
    'Authorization': `Token ${RECALL_API_KEY}`
  } 		
}).then(r => r.json());

This object will contain a recordings section with pre-signed links to view your Meeting Direct Connect recordings

if (meetingObj.recordings.length == 0) {
  console.log("No recordings were made, maybe you didn’t request one?");
} else {
  var videoLink = meetingObj.recordings[0].media_shortcuts.data.download_url;
  console.log(`Your recording is ready to view at ${videoLink}`);
}

Next Steps

  • If you want a botless form factor, but without the limitations of Meeting Direct Connect, you should check out the Desktop SDK
  • If you want to be able to input chat, audio, or video data into a meeting, check out Bots