Amazon Chime SDKをPHPとJavaScriptでサクッと動かす

Amazon Chime SDKを最短で動かしてみる。
1対1でのビデオ通話ができるまで。

# 準備

AWSアカウントで、`AmazonChimeFullAccess`, `AmazonChimeSDK`の権限を付与したcredentialsを作成。

[AWS SDK for PHP](https://aws.amazon.com/jp/sdk-for-php/) をインストール

# ソースコード

## ミーティング参加

```php
<?php

require_once './vendor/autoload.php';

use Aws\Chime\ChimeClient;

$options = [
    'version'     => 'latest',
    'region'      => 'ap-northeast-1',
];
$client = new ChimeClient($options);

// ミーティングルームを検索
$result = $client->listMeetings([]);
if (count($result['Meetings']) == 0) {
    // ない場合は作成
    $options = [
        'ClientRequestToken' => date('Ymd_His') . '_' . uniqid(),
        'MediaRegion' => 'ap-northeast-1',
    ];
    $result = $client->createMeeting($options);
    $meeting = $result['Meeting'];
} else {
    $meeting = $result['Meetings'][0];
}

// ミーティングに参加
$options = [
    'ExternalUserId' => date('Ymd_His') . '_attendee0_' . uniqid(),
    'MeetingId' => $meeting['MeetingId'],
];
$result = $client->createAttendee($options);
$attendee = $result['Attendee'];
```

## ページ

```php
<html lang="ja">
<head>
    <script src="./scripts/amazon-chime-sdk.min.js"></script>
    <script>
        (async () => {
            const logger = new ChimeSDK.ConsoleLogger('MyLogger', ChimeSDK.LogLevel.ERROR);
            const deviceController = new ChimeSDK.DefaultDeviceController(logger);

            const meetingResponse = {"Meeting":<?php echo json_encode($meeting) ?>};
            const attendeeResponse = {"Attendee":<?php echo json_encode($attendee) ?>};

            const configuration = new ChimeSDK.MeetingSessionConfiguration(meetingResponse, attendeeResponse);
            const meetingSession = new ChimeSDK.DefaultMeetingSession(configuration, logger, deviceController);

            const audioInputDevices = await meetingSession.audioVideo.listAudioInputDevices();
            const audioOutputDevices = await meetingSession.audioVideo.listAudioOutputDevices();
            const videoInputDevices = await meetingSession.audioVideo.listVideoInputDevices();

            meetingSession.audioVideo.chooseVideoInputQuality(1280,720,3,1000);
            await meetingSession.audioVideo.chooseVideoInputDevice(videoInputDevices[0].deviceId);
            await meetingSession.audioVideo.chooseAudioInputDevice(audioInputDevices[0].deviceId);
            if (audioOutputDevices[0]) {
                await meetingSession.audioVideo.chooseAudioOutputDevice(audioOutputDevices[0].deviceId);
            }

            const audioElement = document.getElementById('audio-preview');
            meetingSession.audioVideo.bindAudioElement(audioElement);

            const videoElement = document.getElementById('video-preview');

            const observer = {
                audioVideoDidStart: () => {
                    console.log('Started');
                },
                videoTileDidUpdate: tileState => {
                    if (!tileState.boundAttendeeId || tileState.localTile || tileState.isContent) {
                        return;
                    }

                    console.log('Start video');
                    meetingSession.audioVideo.bindVideoElement(tileState.tileId, videoElement);
                }
            };

            meetingSession.audioVideo.addObserver(observer);
            meetingSession.audioVideo.start();
            meetingSession.audioVideo.startLocalVideoTile();
        }) ();
    </script>
</head>
<body>
<div>
    video test<br>
    <?php echo $meeting['MeetingId'] ?><br>
    <?php echo $attendee['AttendeeId'] ?>
</div>
<video id="video-preview" style="width:100%; height: 500px"></video>
<audio id="audio-preview"></audio>
</body>
</html>
```