ライブ配信の配信環境の振り返り

# はじめに

こんにちは @SAMUKEI です！
[Diverse Advent Calendar 2019](https://qiita.com/advent-calendar/2019/diverse) 8日目の記事です。

前日は @python_spameggs さんの本当は「[MySQLのアップグレードをしたかっただけだったのに](https://qiita.com/python_spameggs/items/e3ce2b2ffd72146d6b54)」でした。
実際に起きた事例の紹介で運用においての監視の大切さがわかりますね！

さて、この記事では副業として行っているライブ配信事業の配信環境の遍歴をお話します。

# 事業立ち上げ時の配信環境

事業立ち上げ時に限られた資金で事業運営が必要になり、ある程度の妥協が必要と判断しました。
その判断から[nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module)を用いた構成にすることを検討しました。

## 構成

![nginx-rtmp-module](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80840/315e0f31-6ff6-5901-73c6-ab81886bb262.png)


説明すると、
1. 配信環境の[OBS](https://obsproject.com/ja)からRTMP配信する
2. EC2上のnginx([nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module))でRTMPを受け、HLS変換を行う
3. [video.js](https://github.com/videojs)でHLS配信を再生させる
という構成です。
この構成にしたことで、ライブ配信を安価でかつ簡単に行うことが出来ました。

しかしながら、

* 遅延10〜30秒程度を大きく、配信者と視聴者とのコミュニケーションでのストレスが高くなってしまう
* マネージドサービスでないため、メンテナンスコストが高い
* チューニングの試行錯誤で別の改善施策に手がつけられない

という課題がつきまとってきました。

この課題を解決したいと考え、事業が安定化した段階で試行錯誤をはじめました。

# WebRTCの試み
まず目をつけたのはリアルタイムな超低遅延配信としてのWebRTCでした。
こちらは以前から知っていたこともあり、挑戦したいと考えていたので、導入を進めました。

## 構成

![WebRTC](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80840/6baed801-7b76-4b75-255f-2358477747ef.png)

説明すると、
1. 配信側でブラウザからWebRTC SFUに映像を配信する
2. EC2上のWebRTC SFU[^1]で受けてWebRTC配信し、視聴者がブラウザでWebRTCを視聴する
という構成です。

[^1]: [WebRTC SFU](https://gist.github.com/voluntas/4d2bd3e878965bdd747a#id8)に関しては時雨堂さんがわかりやすくまとめてくれているので参照ください。

この構成で開発環境で試したところ、遅延が1sec程度とリアルタイム性に優れ画質も期待値に近いものだったため、本番環境でトライしました。

しかしながら、

* 視聴環境によっては映像の途切れ、視聴に不備が発生してしまった
* スマホ視聴の方の端末が熱くなってしまう
* 動いた場合のブロックノイズが想定よりも大きかった
* 結局マネージドサービスを選定しなかったので、メンテナンスコストが変わらない
* [OBS](https://obsproject.com/ja)が使えなかった

このように、WebRTCの仕組み上どうしてもHLSの配信に比べ視聴環境を選んでしまう問題が起きてしまいました。
リアルタイム性のメリットが高いので非常に残念でしたが、当初の構成に戻すことが余儀なくされました。

# ImageFlux Live Streaming(現在の配信環境)
WebRTCの選定の際に、見つけたWebRTC + HLS配信のハイブリッドのサービスです。
マネージドサービスという点や視聴環境に応じて解像度などを自動で調整してくれる点などが魅力的に感じて利用しました。

## 構成

![ImageFlux Live Streaming](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80840/a12a1555-f75d-bc78-b38a-e5f735f058de.png)

説明すると、
1. 配信側でブラウザからWebRTCを[ImageFlux Live Streaming](https://www.sakura.ad.jp/services/imageflux/livestreaming/)に配信する
2. [ImageFlux Live Streaming](https://www.sakura.ad.jp/services/imageflux/livestreaming/)でWebRTCからHLSに**高速変換**し、HLSを配信する[^2]
3. [hls.js](https://github.com/video-dev/hls.js)でHLS配信を再生させる
という構成です。

[^2]: 自前でも用意できんじゃん？と思った方もいると思いますが、パフォーマンス問題で諦めました。[こちらの記事](https://medium.com/@voluntas/imageflux-live-ad802e3a8352)のように**専用チップを利用し高速変換**されているので[ImageFlux Live Streaming](https://www.sakura.ad.jp/services/imageflux/livestreaming/)は高いパフォーマンスを出せるみたいです。すごい！

こちらの構成に切り替えた際に、流れてくるHLSの音源がaacでなく、mp3だったため、[video.js](https://github.com/videojs)(mp3サポートなし)から[hls.js](https://github.com/video-dev/hls.js)への実装変更が必要になりました。
また、WebRTCで配信するため[OBS](https://obsproject.com/ja)が利用出来ず、配信画面は実装する必要があります。

遅延が5sec程度と小さく、画質も問題ありませんでした。
マネージドサービスのため、細かいチューニングやバージョン管理などのメンテナンスコストから開放されました。
「[OBS](https://obsproject.com/ja)が使えない」という課題が引き続きありますが、運用のコストや視聴者の利便性を考えると**オススメ**できるサービスです！

# おわりに
今回は、「[ImageFlux Live Streaming](https://www.sakura.ad.jp/services/imageflux/livestreaming/)」がオススメ！と提灯記事みたいになってしまいました。
個人的には、この状況で満足せず**リアルタイム性が高く安定した配信環境**を目指したいと考えているので、現在の構成に縛られずに新しいサービスが技術をキャッチアップして改善していきたいと思っています。
本業も副業もユーザーファーストでやっていき :muscle: 

明日の9日目は @kiy0p0n さんです！