mcpField
S
setup-zoom-websockets

setup-zoom-websockets

github.com/anthropics開発33.6k2.1k 回インストール1 日前に更新
リポジトリ

setup-zoom-websockets について

Zoomの永続的なイベントストリームを実装する開発者向けのリファレンススキルです。WebhooksよりWebSocketsが適する場面を示し、設定と接続管理を解説します。

主な機能

  1. 01WebSocketsとWebhooksの比較
  2. 02Server-to-Server OAuthの前提条件
  3. 03イベントサブスクリプション設定
  4. 04ハートビートと再接続の案内
  5. 05Zoomイベントのリファレンス

活用シーン

  1. 01低遅延の会議イベント受信
  2. 02公開Webhookエンドポイントの回避
  3. 03WebSocketsとWebhooksの選択
  4. 04Zoomイベント接続の維持

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/anthropics/knowledge-work-plugins --skill setup-zoom-websockets

インストール後、Claude Code で/setup-zoom-websocketsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

RUNBOOK.md
references/
connection.md
environment-variables.md
events.md
troubleshooting/
common-issues.md

詳細

/setup-zoom-websockets

永続的な Zoom イベントストリームに関する背景情報です。まずワークフローによるルーティングを優先し、WebSockets のほうが適している可能性がある場合に、このファイルを参照してください。

WebSockets と Webhooks の比較

項目WebSocketsWebhooks
接続永続的な双方向接続1 回限りの HTTP POST
遅延低い(HTTP のオーバーヘッドなし)高い(イベントごとに新しい接続)
セキュリティ直接接続のため、エンドポイントを公開しないエンドポイントの検証と IP の許可リスト登録が必要
モデルプル(Zoom に接続します)プッシュ(Zoom から接続します)
状態ステートフル(接続を維持)ステートレス(各イベントは独立)
セットアップより複雑(アクセストークンと接続が必要)より簡単(エンドポイント URL のみ)

次の場合は WebSockets を選択してください:

  • リアルタイムで低遅延の更新が重要な場合
  • セキュリティが最優先の場合(銀行、医療、金融)
  • パブリックエンドポイントを公開したくない場合
  • 双方向通信が必要な場合

次の場合は Webhooks を選択してください:

  • より簡単なセットアップを優先する場合
  • イベント通知の数が少ない場合
  • 既存の HTTP インフラストラクチャを利用する場合

前提条件

  • Zoom Marketplace の Server-to-Server OAuth アプリ
  • アカウント ID、クライアント ID、クライアントシークレット
  • イベントを有効にした WebSocket サブスクリプション

S2S OAuth についてサポートが必要ですか? 認証フローの詳細については、zoom-oauth スキルを参照してください。

すぐにトラブルシューティングを始めましょう: 詳細なデバッグを行う前に、5-Minute Runbook を使用してください。

クイックスタート

1. Server-to-Server OAuth アプリを作成する
  1. Zoom Marketplace に移動します
  2. Server-to-Server OAuth アプリを作成します
  3. アカウント ID、クライアント ID、クライアントシークレットをコピーします
2. WebSocket サブスクリプションを有効にする
  1. アプリで Feature → Event Subscriptions に移動します
  2. イベントサブスクリプションを追加します
  3. 方法の種類として WebSockets を選択します
  4. サブスクライブするイベントを選択します(例:meeting.created、meeting.started)
  5. 保存すると、エンドポイント URL が生成されます
3. WebSocket 経由で接続する
const WebSocket = require('ws');
const axios = require('axios');

// Step 1: Get access token
async function getAccessToken() {
  const credentials = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64');
  
  const response = await axios.post(
    'https://zoom.us/oauth/token',
    new URLSearchParams({
      grant_type: 'account_credentials',
      account_id: ACCOUNT_ID
    }),
    {
      headers: {
        'Authorization': `Basic ${credentials}`,
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    }
  );
  
  return response.data.access_token;
}

// Step 2: Connect to WebSocket
async function connectWebSocket() {
  const accessToken = await getAccessToken();
  
  // WebSocket URL from your subscription settings
  const wsUrl = `wss://ws.zoom.us/ws?subscriptionId=${SUBSCRIPTION_ID}&access_token=${accessToken}`;
  
  const ws = new WebSocket(wsUrl);
  
  ws.on('open', () => {
    console.log('WebSocket connection established');
  });
  
  ws.on('message', (data) => {
    const event = JSON.parse(data);
    console.log('Event received:', event.event);
    
    // Handle different event types
    switch (event.event) {
      case 'meeting.started':
        console.log(`Meeting started: ${event.payload.object.topic}`);
        break;
      case 'meeting.ended':
        console.log(`Meeting ended: ${event.payload.object.uuid}`);
        break;
      case 'meeting.participant_joined':
        console.log(`Participant joined: ${event.payload.object.participant.user_name}`);
        break;
    }
  });
  
  ws.on('close', (code, reason) => {
    console.log(`Connection closed: ${code} - ${reason}`);
    // Implement reconnection logic
  });
  
  ws.on('error', (error) => {
    console.error('WebSocket error:', error);
  });
  
  return ws;
}

connectWebSocket();

イベント形式

WebSocket 経由で受信するイベントは、Webhook イベントと同じ形式です。

{
  "event": "meeting.started",
  "event_ts": 1706123456789,
  "payload": {
    "account_id": "abcD3ojkdbjfg",
    "object": {
      "id": 1234567890,
      "uuid": "abcdefgh-1234-5678-abcd-1234567890ab",
      "host_id": "xyz789",
      "topic": "Team Standup",
      "type": 2,
      "start_time": "2024-01-25T10:00:00Z",
      "timezone": "America/Los_Angeles"
    }
  }
}

よく使われるイベント

イベント説明
meeting.createdミーティングがスケジュールされた
meeting.updatedミーティングの設定が変更された
meeting.deletedミーティングが削除された
meeting.startedミーティングが開始する
meeting.endedミーティングが終了する
meeting.participant_joined参加者がミーティングに参加する
meeting.participant_left参加者がミーティングから退出する
recording.completedクラウド録画の準備が完了した
user.created新しいユーザーが追加された
user.updatedユーザー情報が変更された

接続管理

キープアライブ

WebSocket 接続では、定期的なハートビートが必要です。Zoom はアイドル状態の接続を終了します。

// Send ping every 30 seconds
setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.ping();
  }
}, 30000);
再接続

信頼性を高めるため、自動再接続を実装してください。

function connectWithReconnect() {
  const ws = connectWebSocket();
  
  ws.on('close', () => {
    console.log('Connection lost. Reconnecting in 5 seconds...');
    setTimeout(connectWithReconnect, 5000);
  });
  
  return ws;
}
同時接続数の上限

重要: サブスクリプションごとに開ける WebSocket 接続は一度に 1 つだけです。新しい接続を開くと、既存の接続は終了します。

詳細情報

トラブルシューティング

サンプルリポジトリ

公式/コミュニティ
種類リポジトリ説明
Node.jsjust-zoomit/zoom-websocketsS2S OAuth を使用した WebSocket のサンプル

WebSockets と RTMS の違い

WebSockets と RTMS(リアルタイムメディアストリーム)を混同しないでください。

機能WebSocketsRTMS
目的イベント通知メディアストリーム
データミーティングイベント、ユーザーイベント音声、動画、文字起こし
ユースケースZoom イベントへの対応AI/ML、リアルタイム文字起こし
スキルこのスキルrtms

リアルタイムの音声/動画/文字起こしデータには、代わりに rtms スキルを使用してください。

リソース

環境変数

コメント