Amazon Chime SDK で 1 対 1 のビデオ通話を作り、通話後に会議が消えるまでを GetMeeting と CloudTrail で確認してみた

Amazon Chime SDK で 1 対 1 のビデオ通話を作り、通話後に会議が消えるまでを GetMeeting と CloudTrail で確認してみた

Amazon Chime SDK で 1 対 1 のビデオ通話を作る際、通話終了後に JoinToken で入り直されないようにするには、会議をしっかり終わらせる必要があります。DeleteMeeting を呼ぶ方法と自動終了を待つ方法を、実際に検証してみました。
2026.10.25

はじめに

テクニカルサポートの 片方 です。
最近 Amazon Chime SDK を学習・検証する機会があったので紹介します。
Amazon Chime SDK で 1 対 1 のビデオ通話を作るときは、予約ごとに会議(meeting)を 1 つ作り、2 人の参加者(attendee)を入れます。参加者を作ると、その参加者として会議に入るための JoinToken が返ります。通話が終わった後に会議が残っていると、配った JoinToken で入り直せてしまうのではないかと考えました。

JoinToken は、会議が終わるか、DeleteAttendee で参加者を消すと失効します。失効した後は、その参加者として会議に入れません。

https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_meeting-chime_Attendee.html

An Amazon Chime SDK meeting attendee. Includes a unique AttendeeId and JoinToken. The JoinToken allows a client to authenticate and join as the specified attendee. The JoinToken expires when the meeting ends, or when DeleteAttendee is called. After that, the attendee is unable to join the meeting.

つまり、入り直しを防げるかは、会議が本当に終わったかで決まります。ここでは、入り直せるかどうかそのものではなく、会議が残っていないことを GetMeeting と CloudTrail で確認します。
本ブログで試す終わらせ方は 2 つです。

  • サーバーから DeleteMeeting を呼ぶ方法
  • 参加者がいなくなった後に自動で終わるのを待つ方法

どちらの方法でも会議が残らないことと、残っていないことを後から確認できることを、東京リージョンで試しました。
この記事では、たとえば予約制のオンライン相談のように、通話の時間が決まっていて、終わった後に入り直されては困る場面を想定しています。

構成

構成の図。サーバー役の Node.js が会議と参加者を作り、2 つのブラウザが Chime SDK の会議に入る。確認は GetMeeting と CloudTrail

サーバー役は、手元の Node.js のスクリプトです。Amazon Chime SDK Meetings の API で、会議を作り、2 人の参加者を作り、会議を終わらせます。
会議は予約ごとに 1 つにするため、CreateMeeting の ClientRequestToken に予約の ID を入れました。会議が続いている間に、同じ予約でもう 1 度呼ぶと、同じ会議が返りました(冪等。何度呼んでも結果が同じになる性質です)。

参加者は、ExternalUserId に会員の ID を入れて作り、その会員の参加者の情報だけを、本人のブラウザに渡します。
ブラウザの側は、Amazon Chime SDK for JavaScript(amazon-chime-sdk-js)3.32.0 を使い、渡された情報で会議に入ります。会議の状態の変化(相手の参加、映像の受信、停止)を記録し、Playwright から読み出します。

先に結論から

  • 通話中に DeleteMeeting を呼ぶと、約 5 秒後に 2 つのブラウザとも MeetingEnded で止まりました。GetMeeting は NotFoundException でした。
  • サーバーが何もしなくても、会議は自動で消えました。消えたのは、2 人が抜けた会議では抜けてから 5 分 1 秒〜5 分 32 秒の間でした。誰も入らなかった会議では、作ってから 5 分 1 秒〜5 分 31 秒の間です(30 秒おきの GetMeeting で確認)。消えるまでの 5 分余りは、GetMeeting で会議が残っていました。
  • CloudTrail には、自動で終わった会議の DeleteMeeting の記録が残りませんでした。ListMeetings もないので、CloudTrail のイベント履歴(リージョンごと、過去 90 日)の CreateMeeting から会議の ID を集めました。7 件とも残っていないことを、GetMeeting で確認しました。

やってみた

1. サーバー役を書く

会議と参加者を作り、終わらせる部分です。再試行は、SDK の standard モード(指数バックオフとジッター。試すのは初回を含めて最大 5 回)に任せています。

DeleteMeeting は、もうない会議(NotFoundException)を「終わらせ済み」として扱い、何度呼んでも同じ結果にしました。CreateAttendee も、ExternalUserId が冪等のトークンなので、再試行しても同じ参加者が返ります。

// サーバーの側:会議と参加者を作り、終わらせる(Amazon Chime SDK Meetings の API)。
// - 会議は予約ごとに 1 つ。ClientRequestToken に予約の ID を使うので、会議が続いている間は、同じ予約で何度呼んでも同じ会議が返った(冪等)。
// - 参加者は ExternalUserId に会員の ID を入れて作り、その会員の参加者の情報(JoinToken を含む)だけを返す。
//   ほかの会員の JoinToken は、この関数からは返らない。
// - 終わらせるのは DeleteMeeting。もう無い会議(NotFoundException)は、終わらせ済みとして扱う(何度呼んでも同じ)。
// - 再試行は SDK の standard モード(指数バックオフとジッター、最大 5 回)。
import {
  ChimeSDKMeetingsClient, CreateAttendeeCommand, CreateMeetingCommand, DeleteMeetingCommand, GetMeetingCommand,
} from '@aws-sdk/client-chime-sdk-meetings';

const chime = new ChimeSDKMeetingsClient({ region: 'ap-northeast-1', maxAttempts: 5, retryMode: 'standard' });

export async function createMeeting(reservationId, tag) {
  const r = await chime.send(new CreateMeetingCommand({
    ClientRequestToken: reservationId,
    ExternalMeetingId: reservationId,
    MediaRegion: 'ap-northeast-1',
    Tags: [{ Key: 'blog-yattemita', Value: tag }],
  }));
  return r.Meeting;
}

export async function joinInfoFor(meeting, memberId) {
  const r = await chime.send(new CreateAttendeeCommand({ MeetingId: meeting.MeetingId, ExternalUserId: memberId }));
  return { Meeting: meeting, Attendee: r.Attendee };
}

export async function endMeeting(meetingId) {
  try {
    await chime.send(new DeleteMeetingCommand({ MeetingId: meetingId }));
    return 'deleted';
  } catch (e) {
    if (e.name === 'NotFoundException') return 'already-ended';
    throw e;
  }
}

export async function meetingExists(meetingId) {
  try {
    await chime.send(new GetMeetingCommand({ MeetingId: meetingId }));
    return true;
  } catch (e) {
    if (e.name === 'NotFoundException') return false;
    throw e;
  }
}

本番で使う場合は、次の 3 点に気を付けます。

  • joinInfoFor に渡す会員の ID は、ログインした本人の ID だけにします。今回は、サーバー役のスクリプトが 2 人分を作って、それぞれのブラウザに渡しています。
  • 同じ要求が同時に 2 回呼ばれると、CreateMeeting は ConflictException(409)になることがあります(CreateMeeting の API リファレンス)。本ブログで使った SDK の standard モードが再試行するエラーの一覧にも、ConflictException と 409 は入っていません。本ブログのコードでは、この呼び直しは入れていません。本番で使う場合は、ジッター付きで少し待ってから、同じ ClientRequestToken で回数に上限を付けて呼び直します。
  • ClientRequestToken に使えるのは、2〜64 字の英数字・-・_ です。

https://github.com/smithy-lang/smithy-typescript/blob/%40smithy%2Fcore%403.36.0/packages/core/src/submodules/retry/service-error-classification/constants.ts#L24-L49

2. ブラウザの側をまとめる

esbuild で amazon-chime-sdk-js をブラウザ用の 1 ファイルにまとめようとすると、2 つのエラーで止まりました。1 つ目は、Node.js の組み込みのモジュール(node:https など)が見つからないというエラーです。amazon-chime-sdk-js が依存している @aws-sdk/client-chime-sdk-messaging が原因だったので、空のモジュールに差し替えました。2 つ目の global is not defined は、global を globalThis に置き換えて直しました。

npx esbuild client.js --bundle --format=iife --platform=browser --minify --define:global=globalThis \
  --alias:@aws-sdk/client-chime-sdk-messaging=./shim-messaging.js --outfile=page/bundle.js

Chromium は、疑似のカメラとマイクを使う起動の引数を付けて動かしました。

const browser = await chromium.launch({ args: ['--use-fake-device-for-media-stream', '--use-fake-ui-for-media-stream'] });

確認してみた

サーバーから DeleteMeeting したとき

2 人が入って相手の映像を受け取った後に、DeleteMeeting を呼びました。時刻はすべて UTC です。

DeleteMeeting の後、2 つのブラウザが MeetingEnded で止まり、GetMeeting が NotFoundException になった記録

DeleteMeeting から約 5 秒後には、2 つのブラウザとも MeetingEnded で止まっていました。状態の isTerminal() は true を返しました。DeleteMeeting は、すべての参加者を消してクライアントを切断し、新しいクライアントが入れないようにする操作です。

https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_meeting-chime_DeleteMeeting.html

The operation deletes all attendees, disconnects all clients, and prevents new clients from joining the meeting.

※ 古い JoinToken で入り直せるかは、試していません。

削除の 6 秒後にもう 1 度 DeleteMeeting を呼ぶと、NotFoundException ではなく成功(deleted)が返りました。少なくとも削除の直後は、DeleteMeeting の結果では「もうない」ことを見分けられません。残っているかどうかは、GetMeeting で確認しました。コードの already-ended の分岐は、この確認では通っていません。

2 人が自分で抜けたときと、誰も入らなかったとき

サーバーが何もしない場合を 2 つ試しました。2 人が入った後に 2 人とも自分で抜けた会議と、作っただけで誰も入らなかった会議です。どちらも、30 秒おきに GetMeeting を呼びました。

2 人が抜けた会議と、誰も入らなかった会議。どちらも 5 分余り後に GetMeeting が NotFoundException になった

2 人が抜けた会議は、抜けてから 5 分 1 秒後の GetMeeting では残っていて、5 分 32 秒後には NotFoundException でした。誰も入らなかった会議も、作ってから 5 分 1 秒後には残っていて、5 分 31 秒後には消えていました。非レプリカ会議では、接続している参加者がいない状態が 5 分続くと、会議は自動で終わります。

https://docs.aws.amazon.com/ja_jp/chime-sdk/latest/dg/chime-sdk-faq.html

非レプリカ会議で、5 分間連続して接続している参加者がいない場合。

会議時間が 24 時間を超えた場合も、会議は自動で終わります。自動で終わるまでの 5 分余りの間は、GetMeeting で会議が残っていることを確認しました。会議が続いている間は、JoinToken も失効していません。通話を終えた後に入り直されたくない場合は、自動の終了を待たずに DeleteMeeting を呼ぶ方が確実です。

CloudTrail で、残っていないことを確認する

CloudTrail の記録を、会議ごとに並べました。画像の A はサーバーから削除した会議、B は 2 人が抜けた会議、C は誰も入らなかった会議です。記録は 13:41 ごろに取り出したもので、C の 13:40:34 の GetMeeting は入っていません。

CloudTrail の記録。DeleteMeeting は、サーバーから削除した会議にだけある

CreateMeeting は、同じ予約で 2 回呼ぶと 2 回とも記録されていました。DeleteMeeting の記録は、サーバーから削除した会議にだけあり、自動で終わった 2 つには、終わったことを示す記録がありません。DeleteMeeting の記録が無い会議は、自動で終わったと見なせます。

https://docs.aws.amazon.com/ja_jp/chime-sdk/latest/dg/chime-sdk-faq.html

DeleteMeeting API の Cloud Trail または EventBridge エントリがない場合は、会議が自動的に終了したと仮定できます。

Chime SDK Meetings には、会議の一覧を取る API(ListMeetings)がありません。2026 年 10 月時点の API リファレンスでは、操作は CreateMeeting・GetMeeting などの 16 個です。そこで、CloudTrail の CreateMeeting の記録の応答から会議の ID を集め、1 つずつ GetMeeting を呼びました。重なりを除いて集めた会議の ID は 7 件でした。

CloudTrail の CreateMeeting で作った会議: 7 件 / いまも残っている会議: 0 件

7 件のうち 3 件がこの記事の確認の会議で、3 件は同じ時間帯に別の確認で作った会議です。残りの 1 件は、この記事の確認と同じタグで、最初の会議の 13 秒前に作った会議です(CloudTrail の CreateMeeting の記録で確認)。

まとめ

はじめに気になったとおり、サーバーが何もしないと、通話の後も会議は 5 分余り残っていました。その間は JoinToken も失効していません。入り直されたくないなら、通話を終えたらサーバーから DeleteMeeting を呼ぶのが確実かと思います。
もう 1 つ手間がかかったのが、残っている会議の確認です。会議の一覧を取る API がないので、今回は CloudTrail の CreateMeeting の記録から会議の ID を拾い集めました。会議を作るときに、会議の ID を予約の記録と一緒に残しておけば、この手間はかかりません。

余談ですが、Chime SDK には画面の部品が含まれないので、カウントダウンタイマーや設定ボタンなどは、アプリの側で作ります。下の画像は、この検証とは別に、画面の部品を付けて作ってみたものです。

カウントダウンタイマーと設定ボタンを付けたビデオ通話の画面
ビデオ通話の画面の例
ビデオ通話の画面の例

本ブログが誰かの参考になれば幸いです。

参考資料

クラスメソッドオペレーションズ株式会社について

クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイト をぜひご覧ください。※2026年1月 アノテーション㈱から社名変更しました

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事