Amazon IVS触ってみた

:::note info
viviONグループでは、DLsiteやcomipoなど、二次元コンテンツを世の中に届けるためのサービスを運営しています。
ともに働く仲間を募集していますので、興味のある方は[こちら](#一緒に二次元業界を盛り上げていきませんか)まで。
:::

## Amazon IVSとは🤔
簡単に言えばAmazonが提供している配信基盤サービス（Amazon Interactive Video Service）です。

- 特徴
    - Web, iOS, Android対応
    - 低レイテンシー
    - 映像、音声配信可能（OBS配信もOK）
    - Amazon S3 への自動録画機能あり
- 公式サイト
    - https://aws.amazon.com/jp/ivs/

## 使ってみる✍️

### 利用環境

FW：Nuxt3

言語：Typescript

### 下準備

①まずはAWSの管理画面から配信用のチャネルを作成します

![スクリーンショット 2024-10-23 12.15.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636800/819a6a60-e332-6f6c-821d-927212aaccaa.png)


②チャネルを作成すると様々な情報が表示されますが、今回配信で必要なデータは「ストリームキー」と「取り込みエンドポイント」になります

![f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636800/6165b84a-bb61-27d1-9527-d02285a1d0a2.png)


実際にアプリケーションに組み込む際は、こちらの実装をバックエンド側で実装することになるかと思います！

### Nuxt側からチャンネルに接続して配信開始

①パッケージのインストール

```bash
npm install amazon-ivs-web-broadcast
```

②とりあえずインポートしておく

```tsx
import * as IVSBroadcastClient from 'amazon-ivs-web-broadcast';
```

③インスタンスの作成

```tsx
const client = IVSBroadcastClient.create({
   streamConfig: IVSBroadcastClient.BASIC_LANDSCAPE, // チャンネル作成時に設定したチャネルタイプに合わせる
   ingestEndpoint: '*****', // ここに取り込みエンドポイントを設定
});
```

④マイクの権限許可（今回は音声配信で検証のためマイクのみ）

```tsx
let permissions = {
  audio: false,
  video: false,
};
try {
  const stream = await navigator.mediaDevices.getUserMedia({
    video: false,
    audio: true,
  });
  for (const track of stream.getTracks()) {
    track.stop();
  }
  permissions = { video: false, audio: true };
} catch (error) {
  permissions = { video: false, audio: false };
  console.error(error);
}
if (!permissions.audio) {
  console.error('マイクを使用できませんでした。');
}
```

⑤マイクの追加（今回は既定のデバイスを使用するように指定しました）


:::note warn
マイクの許可ができた上でこちらの処理が走るようにしましょう
許可できていないとエラーになります😣
:::

```tsx
const devices = await navigator.mediaDevices.enumerateDevices();
const audioDevices = devices.filter((d) => d.kind === 'audioinput');
if (audioDevices.length) {
  const microphoneStream = await navigator.mediaDevices.getUserMedia({
    audio: {
      deviceId: 'default', // 既定のデバイスを使用
    },
  });
  await this.broadcastClient.addAudioInputDevice(microphoneStream, 'microphone');
  this.isMicActive.value = true;
} else {
  console.error('マイクが見つかりませんでした。');
}
```

⑥ブロードキャストの開始

管理画面を確認すると状態がライブになっていることが確認できます🤙

```tsx
client.startBroadcast('*****'); // ここにストリームキーを設定
```

![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636800/45c11883-f43d-a771-dd35-6208b8847c20.png)


⑦マイクのミュート

```tsx
let audioStream = client.getAudioInputDevice('microphone');
audioStream.getAudioTracks()[0].enabled = false;
```

⑧マイクのミュート解除

ビデオも利用している場合はマイクと同様の方法でVideoInputDeviceでオンオフが切り替えられます🙆‍♂️

```tsx
let audioStream = client.getAudioInputDevice('microphone');
audioStream.getAudioTracks()[0].enabled = true;
```

⑨ブロードキャストの終了

```tsx
const audioStream = client.getAudioInputDevice('microphone');
if (audioStream && audioStream.getAudioTracks()[0].enabled) {
  audioStream.getAudioTracks()[0].enabled = false;
}
client.removeAudioInputDevice('microphone'); // マイクの接続を切る
client.stopBroadcast(); // ブロードキャストの終了
```

## まとめ
- Amazon IVSを使った配信の実装はドキュメントどおりに実装すればある程度スムーズに実装することが可能な見込みでした！
- 視聴に関しては視聴用のURLを利用して視聴することができるので、「.m3u8」に対応したプレイヤーを別途実装する必要があります。
  - Player SDKで実装する方法やHLS.jsを使って実装するなど方法は色々あると思います🙆‍♂️
:::note info
HLS.jsを使うとレイテンシーが高いので、Player SDKでの実装のほうがおすすめです
:::

## Appendix
- **IVS Broadcast SDK公式ドキュメント**
https://docs.aws.amazon.com/ja_jp/ivs/latest/LowLatencyUserGuide/broadcast-web.html

# 一緒に二次元業界を盛り上げていきませんか？
株式会社viviONでは、フロントエンドエンジニアを募集しています。

https://vivion.jp/recruit/

また、フロントエンドエンジニアに限らず、バックエンド・SRE・スマホアプリなど様々なエンジニア職を募集していますので、ぜひ採用情報をご覧ください。