
Amazon Chime SDK で 1 対 1 のビデオ通話を作り、通話後に会議が消えるまでを GetMeeting と CloudTrail で確認してみた
はじめに
テクニカルサポートの 片方 です。
最近 Amazon Chime SDK を学習・検証する機会があったので紹介します。
Amazon Chime SDK で 1 対 1 のビデオ通話を作るときは、予約ごとに会議(meeting)を 1 つ作り、2 人の参加者(attendee)を入れます。参加者を作ると、その参加者として会議に入るための JoinToken が返ります。通話が終わった後に会議が残っていると、配った JoinToken で入り直せてしまうのではないかと考えました。
JoinToken は、会議が終わるか、DeleteAttendee で参加者を消すと失効します。失効した後は、その参加者として会議に入れません。
An Amazon Chime SDK meeting attendee. Includes a unique
AttendeeIdandJoinToken. TheJoinTokenallows a client to authenticate and join as the specified attendee. TheJoinTokenexpires 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 のスクリプトです。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 字の英数字・
-・_です。
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 から約 5 秒後には、2 つのブラウザとも MeetingEnded で止まっていました。状態の isTerminal() は true を返しました。DeleteMeeting は、すべての参加者を消してクライアントを切断し、新しいクライアントが入れないようにする操作です。
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 分 1 秒後の GetMeeting では残っていて、5 分 32 秒後には NotFoundException でした。誰も入らなかった会議も、作ってから 5 分 1 秒後には残っていて、5 分 31 秒後には消えていました。非レプリカ会議では、接続している参加者がいない状態が 5 分続くと、会議は自動で終わります。
非レプリカ会議で、5 分間連続して接続している参加者がいない場合。
会議時間が 24 時間を超えた場合も、会議は自動で終わります。自動で終わるまでの 5 分余りの間は、GetMeeting で会議が残っていることを確認しました。会議が続いている間は、JoinToken も失効していません。通話を終えた後に入り直されたくない場合は、自動の終了を待たずに DeleteMeeting を呼ぶ方が確実です。
CloudTrail で、残っていないことを確認する
CloudTrail の記録を、会議ごとに並べました。画像の A はサーバーから削除した会議、B は 2 人が抜けた会議、C は誰も入らなかった会議です。記録は 13:41 ごろに取り出したもので、C の 13:40:34 の GetMeeting は入っていません。

CreateMeeting は、同じ予約で 2 回呼ぶと 2 回とも記録されていました。DeleteMeeting の記録は、サーバーから削除した会議にだけあり、自動で終わった 2 つには、終わったことを示す記録がありません。DeleteMeeting の記録が無い会議は、自動で終わったと見なせます。
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 には画面の部品が含まれないので、カウントダウンタイマーや設定ボタンなどは、アプリの側で作ります。下の画像は、この検証とは別に、画面の部品を付けて作ってみたものです。



本ブログが誰かの参考になれば幸いです。
参考資料
- Amazon Chime SDK に関するよくある質問 - Amazon Chime SDK
- Attendee - Amazon Chime SDK
- DeleteMeeting - Amazon Chime SDK
- CreateMeeting - Amazon Chime SDK
- CreateAttendee - Amazon Chime SDK
- CloudTrail イベント履歴の操作 - AWS CloudTrail
- smithy-typescript/packages/core/src/submodules/retry/service-error-classification/constants.ts at @smithy/core@3.36.0
クラスメソッドオペレーションズ株式会社について
クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイト をぜひご覧ください。※2026年1月 アノテーション㈱から社名変更しました









