Kinesis Video Streamsで映像・音声をストリーミング配信した時の遅延時間を検証してみた

# 1. はじめに
「ストリーム配信ってどれくらいの遅延時間が発生するのだろうか」と疑問に思ったため、
Kinesis Video Streamsを使用して、USBカメラの映像・音声をストリーム配信してみました。

目的は「遅延時間を検証すること」です。

本記事では、Kinesis Video Streamsで映像・音声をストリーム配信した際に発生する遅延時間の検証結果を紹介します。

本記事の対象読者は、
「ストリーム配信した経験はあるけどKinesis Video Streamsを使った事はないな」という方や
「Kinesis Video Streamsを使用するとどれくらい遅延時間が発生するのかを知りたい」という方です。


# 2. そもそもKinesis Video Streamsとは
Kinesis Video Streamsとは、以下を可能にするAWSのフルマネージドサービスです。

1. 様々なデバイスから取得した映像や音声などのデータをストリーム配信/アーカイブ保存する<br>ストリーム配信は、ライブ再生とオンデマンド再生の両方に対応可能
2. 他のAWSサービス（Amazon Rekognitionなど）やサードパーティーの動画分析プロバイダーと連携し、<br>リアルタイムでデータ分析が可能

今回は1の用途で使用します。

### Kinesis Video Streamsの処理の流れ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/1416db8c-c7e1-ba11-7650-8e0786394df6.png)

本記事の理解に必要な3つの用語を紹介します。

- Producer
    - Kinesis Video Streamsに保存するデータを提供するリソース（例.USBカメラ、監視カメラ）
    - 一つのProducerから複数のストリームに配信可能

- ストリーム
    - Producerから取得したデータを保存するリソース<br>ストリーム配信やデータ解析の際、Consumerにデータを提供するリソース
    - 一つのストリームに対応できるProducerは原則一つのみ

- Consumer
    - ストリームから取得したデータを再生するアプリケーション
    - Amazon Rekognition などの他のAWSサービスやサードパーティーの動画分析プロバイダーを使用して、ストリームを処理できる

さらに詳しくKinesis Video Streamsを知りたい方は以下のAWS公式サイトを参照ください。
[Amazon Kinesis ビデオストリーム とは?](https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/what-is-kinesis-video.html)

# 3. 検証準備
## 3-1. システム構成図
今回の検証で使用するツールは仮想環境、EC2、Kinesis Video Streamsの3つです。

ストリーム配信は以下の流れで実現します。
（［］内は、システム構成図にて対応するプロセス番号を表しています）
1. 仮想環境を用いてゲストOSからKinesis Video Streamsのストリームに映像・音声を送信する［①］
2. ユーザーがEC2に構築したストリーム配信サイトにアクセスする［②,③］
3. ユーザーがストリーム配信開始のアクションをすると、ブラウザで動作するJavaScriptがAWS認証情報を基にストリームのURLを取得する［④,⑤］
4. ストリームから送られてくる映像・音声をストリーム配信サイトにて配信する
（配信の際は、ストリーム配信サイトのvideoタグにストリームのURLを埋め込む）

### システム構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/78841898-2bb5-f034-19cb-d8cc642db8e4.png)

## 3-2. 検証方法
時間帯によってネットワーク速度に差があることを考慮し、検証は複数回実施します。

### 検証手順
1. USBカメラの前にIphoneのストップウォッチを置き、3分間測る
2. 3分後、ストリーム配信サイトにて表示されているストップウォッチの時間を確認する
3. 手順2にて表示されている時間と3分との差分を計算し、遅延時間を算出する
3. 手順1~3を時間帯を変えて3回繰り返す
4. 3回の平均遅延時間を測る

### 検証の例
以下の画像の場合、ストップウォッチに「2分23秒58」と表示されています。
3分との差分を計算し、遅延時間は「36秒42」となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/9f1356a4-e29d-26b4-6686-1ece98732c4e.png)

## 3-3. 検証環境の作成手順
### 手順1. 仮想環境を作成する
- 概要<br>
virtualboxを使用して仮想環境を作成する<br>
**筆者が作成した環境**
    - OS：debian10
    - メモリ：1 GB
    - プロセッサー数：4
    - ストレージ：7GB
- 参考サイト<br>
仮想環境にdebianをインストールする手順が詳細に記載しているリンク↓<br>
（REMSYSTEM TECHLOGより引用）<br>
https://www.rem-system.com/debian10-buster-install/
- はまりポイント<br>
特になし

### 手順2. 仮想環境内でUSBカメラを認識させる
- 概要<br>
USBカメラを仮想環境内にて使用できるようにする
- 参考サイト<br>
仮想環境でUSBカメラを使用する手順を記載しているリンク↓<br>
（/var/www/yatta47.logより引用）<br>
https://yatta47.hateblo.jp/entry/2019/01/12/202843
- はまりポイント<br>
    - はまった箇所<br>
仮想環境内にてUSBカメラの認識は正常にできている<br>（デバイスタブにて対象のデバイスが表示されている）が、映像を出力できない。<br>
    - 解消方法<br>
USBの設定画面にて正しいUSB規格を選択することで解消した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/31b25e30-c7b5-632c-8e0b-5d55caf25ee2.png)

### 手順3. Kinesis Video Streamsのストリームに映像・音声を送信する
- 概要<br>
Kinesis Video Streamsのストリームにデータを送信するためにAmazon Kinesis Video Streams Producer SDK C++をインストールする<br>
インストール後、データをKinesis Video Streamsに送信し、マネジメントコンソールでデータを確認する
- 参考サイト<br>
    - ストリーム配信の方法をハンズオン形式で説明しているリンク↓<br>
（AWS公式サイトより引用）<br>
https://video-streaming-and-analysis.workshop.aws/lab-1/step-3-a.html<br>
    - 映像のみだけでなく音声も送信する方法を記載しているリンク↓<br>
（kinesis Video Streams-producer-sdk-cppのGitHubより引用）<br>
https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp/blob/master/docs/linux.md#running-the-gst-launch-10-command-to-start-streaming-both-audio-and-video-in-raspberry-pi-and-ubuntu

- はまりポイント<br>
    - はまった箇所<br>
Kinesis Video Streamsにデータを送信するためのコマンドを打った際、<br>「WARNING: erroneous pipeline: エレメント "kvssink" がありません」<br>というエラーが発生した
    - 解消方法<br>
kvssinkの実体であるlibgstkvssink.soをgstreamerから参照できるようパスを指定することで解消した<br>
（amazon-kinesis-video-streams-producer-sdk-cppのGitHubより引用）<br>
以下のリンクに解決方法の記載あり↓<br>https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/b6f96f5c-abb0-e182-3c01-45de1eb02d8a.png)

### 手順4. ストリームから送られてくる映像・音声を配信するサイトを作成する
- 概要<br>
ストリームから送られてくる映像・音声を配信するサイトをEC2に構築する
- 参考サイト<br>
    - ストリーム配信するサイトの構築方法を記載しているリンク（p13~p15）<br>
（kinesis Video Streams開発者ガイドより引用）<br>
https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/kinesisvideo-dg.pdf
- はまりポイント<br>
特になし

# 4. 検証
## 4-1. phase1
項目3-3で作成した環境にて遅延時間を検証します。

### 実行コマンド
```
gst-launch-1.0 -v v4l2src device=/dev/video0 ! videoconvert ! video/x-raw,width=640,height=480,framerate=30/1,format=I420 ! x264enc  bframes=0 key-int-max=45 bitrate=500 tune=zerolatency ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink name=sink stream-name="my-stream-name" access-key="YourAccessKey" secret-key="YourSecretKey" alsasrc device=hw:1,0 ! audioconvert ! avenc_aac ! queue ! sink.
```

### 検証結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/d578940a-9e98-744f-4c6f-d35566b9fcad.png)

### 検証コメント
3回の平均遅延時間は「6秒95」でした。
3回目の検証のみ遅延時間が大きくなっているのはネットワーク速度の影響と思われます。

## 4-2. phase2
### phase1との変更点
phase1で使用した実行コマンドからAWS認証情報を削除する

### 変更理由
環境変数にてAWS認証情報を既に登録していることから、<br>実行コマンドにAWS認証情報を記載する必要がないと判断しました。
不要なパラメータを削除することで受け渡すデータ量が減少し、遅延時間を減少できるのではないかと推測しました。
### 実行コマンド
```
gst-launch-1.0 -v v4l2src device=/dev/video0 ! videoconvert ! video/x-raw,width=640,height=480,framerate=30/1,format=I420 ! x264enc  bframes=0 key-int-max=45 bitrate=500 tune=zerolatency ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink name=sink stream-name="my-stream-name" alsasrc device=hw:1,0 ! audioconvert ! avenc_aac ! queue ! sink.
```
### 検証結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/321d12a8-df1b-5d7f-28e0-484c377c94e5.png)

### 検証コメント
3回の平均遅延時間は「5秒97」でした。
phase1に比べて平均遅延時間が「0秒98」減少しています。

「0秒98」という僅かな差なので、本phaseでの変更により平均遅延時間が減少したというよりは、ネットワーク速度が影響して平均遅延時間が減少したのかと思われます。

## 4-3. phase3
### phase2との変更点
phase2で使用した実行コマンドに記載しているkey-int-maxの値を減らす
### 変更理由
key-int-maxとは最大フラグメント継続時間を指定するパラメータです。
遅延時間が長くなる要因の一つとして、
Kinesis Video Streamsに送信されるフラグメント継続時間が挙げられます。
そのため、key-int-maxの値を減らすことで遅延時間を減少できるのではないかと推測しました。

### 実行コマンド
```
gst-launch-1.0 -v v4l2src device=/dev/video0 ! videoconvert ! video/x-raw,width=640,height=480,framerate=30/1,format=I420 ! x264enc  bframes=0 key-int-max=15 bitrate=500 tune=zerolatency ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink name=sink stream-name="my-stream-name" alsasrc device=hw:1,0 ! audioconvert ! avenc_aac ! queue ! sink.
```
### 検証結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/92b02e59-aee1-ec15-ffee-8510ebedbd30.png)

### 検証コメント
3回の平均遅延時間は「4秒61」でした。
phase1に比べて平均遅延時間が「2秒34」減少しています。

本phaseでの変更によって秒単位で平均遅延時間を減少させることができました。
なので、本phaseでの変更は遅延時間の減少に影響を与えている可能性があると考えられます。

## 4-4. phase4
### phase3との変更点
phase3よりも解像度を減らす
### 変更理由
解像度を減らすことで処理するデータ量が減少し、遅延時間を減少できるのではないかと推測しました。
### 実行コマンド
```
gst-launch-1.0 -v v4l2src device=/dev/video0 ! videoconvert ! video/x-raw,width=320,height=240,framerate=30/1,format=I420 ! x264enc  bframes=0 key-int-max=15 bitrate=500 tune=zerolatency ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink name=sink stream-name="my-stream-name" alsasrc device=hw:1,0 ! audioconvert ! avenc_aac ! queue ! sink.
```
### 検証結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/2dbd1abd-7ebf-be87-987a-ae187676df83.png)

### 検証コメント
3回の平均遅延時間は「5秒23」でした。
phase1に比べて平均遅延時間が「1秒72」減少しています。

本phaseでの変更も秒単位で平均遅延時間を減少させることができました。
phase3よりも平均遅延時間が増加していますが、本phaseでの変更は遅延時間の減少に僅かな影響を与えている可能性があると考えられます。

# 5. 検証まとめ
phase1~phase4までの平均遅延時間をまとめると以下のようになりました↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905863/85afec42-1428-344a-8cbc-a420ce16450c.png)
平均遅延時間が短かったphase順に並べると以下になります↓
phase3⇒phase4⇒phase2⇒phase1

今回の検証で遅延時間の減少に最も影響を与えた要素はphase3で編集したkey-int-maxでした。

phase3で推測した通り「フラグメント継続時間の長さ」は遅延時間に影響を与えるようです。
AWS公式サイトにも遅延時間が高い時の対処法としてkey-int-maxの値を減少する方法が記載されていました。
「レイテンシーが高すぎる」の項目を参照ください↓
https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/troubleshooting.html

# 6. さいごに
今回Kinesis Video Streamsを使用してストリーム配信をした際の遅延時間を検証しました。

自分はKinesis Video Streamsを初めて使用し、遅延時間の検証も初めてでした。
普段何気なく使用しているYoutubeやZoomの仕組みに少しでも触れられた気がして楽しかったです。
また、ライブ配信サービスを快適に使えるようにするためには遅延時間の検証は必須であり、
遅延時間を抑えるために様々な工夫がされていると思うとストリーム配信への興味が増しました。

本記事の検証結果が、少しでも皆様のお役に立てれば幸いです。