はじめに
わけあってビデオチャットを作る方法を調べてみようと思ったので、今回はAmazon Chime SDKを使って見ることにしました。
Amazon Chimeとは
Amazon ChimeはAmazonが提供するビデオチャットのサービスです。AWSのセミナーなどでたまに使われているのを見ますね(そらそうか)。このAmazon Chimeそのものは単なるビデオチャットチャットのアプリケーションであるのですが、Amazon Chime SDKを使うとAmazon Chimeの機能を盛り込んだアプリを作ることができます。
このSDKは、Android、iOS、JavaScriptそれぞれが公開されています。今回は、Androidで作成するのでAndroid向けのSDKを使用します。このSDKを用いることで、WebRTCなどの通信周りのことを意識せずにビデオチャットアプリケーションを実装することができます。基本的に今回の実装は公式のデモアプリをベースに行っています。
サーバーの構築
まずはサーバーを構築します。ここで構築するサーバーの役割は、WebRTCとは別で主にはルームの作成・削除や参加者の登録・解除などの管理を行うためのシステムを実装します。
構築したのは↑のようなサーバーです。ソースコードはこちらで公開しています。公式のサンプルから、ルームの作成と削除を行うAPIを実装したものをaws-cdkを使って構築してみました。joinというlambdaでルームの作成を行って、leaveというlambdaでルームの削除を行っています。このAPIを使って以下の2つの情報を登録します。
-
title
:ルームのID -
name
:参加者名
APIの実装
コードはこんな感じです。
import { APIGatewayEvent } from 'aws-lambda'
import * as aws from 'aws-sdk'
import { v4 as uuidv4 } from 'uuid'
const dynamo = new aws.DynamoDB()
const chime = new aws.Chime()
const tableName = process.env.TABLE_NAME ?? ''
type JoinEvent = {
title: string
name: String
}
type LeaveEvent = {
title: string
}
export const join = async ({ body }: APIGatewayEvent) => {
const { title, name }: JoinEvent = JSON.parse(body ?? '{}')
if (!title || !name) {
return response(400, 'application/json', JSON.stringify({ error: 'Need parameters: title, name, region' }))
}
let meeting = await getMeeting(title)
if (!meeting) {
meeting = await chime.createMeeting({
ClientRequestToken: uuidv4(),
ExternalMeetingId: title.substring(0, 64),
}).promise()
await putMeeting(title, meeting)
}
const attendee = (await chime.createAttendee({
MeetingId: meeting.Meeting.MeetingId,
ExternalUserId: `${uuidv4().substring(0, 8)}#${name}`.substring(0, 64),
}).promise())
return response(200, 'application/json', JSON.stringify({
JoinInfo: {
Meeting: meeting,
Attendee: attendee,
},
}, null, 2))
}
export const leave = async ({ body }: APIGatewayEvent) => {
const { title }: LeaveEvent = JSON.parse(body ?? '{}')
const meeting = await getMeeting(title)
await chime.deleteMeeting({ MeetingId: meeting.Meeting.MeetingId }).promise()
await dynamo.deleteItem({
TableName: tableName,
Key: {
title: {
S: title,
},
},
}).promise()
return response(200, 'application/json', JSON.stringify({}))
}
const getMeeting = async (title: string) => {
const result = await dynamo.getItem({
TableName: tableName,
Key: {
title: {
S: title,
},
},
}).promise()
return result.Item ? JSON.parse(result.Item?.data?.S ?? '{}') : null
}
// Stores the meeting in the table using the meeting title as the key
const putMeeting = async (title: string, meeting: any) => {
await dynamo.putItem({
TableName: tableName,
Item: {
title: { S: title },
data: { S: JSON.stringify(meeting) },
ttl: {
N: `${Math.floor(Date.now() / 1000) + 60 * 60 * 24}`,
},
},
}).promise()
}
const response = (statusCode: number, contentType: string, body: any) => {
return {
statusCode: statusCode,
headers: {
'Content-Type': contentType,
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
},
body: body,
isBase64Encoded: false,
}
}
aws-sdkを用いて実装しています。chime.createMeeting()
でルームの作成を行って、chime.createAttendee()
でルームにユーザーを登録します。
同じルームIDのものを作成しないために、DynamoDBを用いて各ルームIDの情報を一時保存しています。
さいごに
ここまでがサーバーの構築です。次からはアプリの実装について説明していきます。