Mirrativ tech blog

株式会社ミラティブの開発者(サーバサイドエンジニア,iOSエンジニア,Androidエンジニア,機械学習エンジニア,インフラエンジニア, etc...)によるブログです

機械学習で配信中の映像からゲームを推定する機能を開発しています🎮

おはようございます、機械学習エンジニアのハヤシです。

本稿では現在テスト中の配信中の映像からゲームを自動で設定する機能についてご紹介します。

背景

Mirrativには「マイアプリ」や「おすすめ」といったタブがあり、そのタブにいろいろな配信が表示されています。視聴者さんはこれらのタブから自分の見たい配信をタップして、視聴を開始します。

また、配信者さん向けの機能として「現在遊んでいるアプリを設定する」という機能があります。配信開始時や配信中にアプリ名を選択し、「いまこのゲームの配信をしているよ」と表明する機能です。(以下「アプリ設定をする」と表現します)

「マイアプリ」や「おすすめ」にどの配信が表示するか判断するロジックに、このアプリ設定の情報を使用しています。つまり、アプリ設定がされている配信は、上記のタブで紹介される確率が高まり、視聴者さんが来やすくなり、コメントも付きやすくなります。

f:id:namagon:20190307080955p:plain
アプリ選択画面。

一方でアプリ設定をしていない配信者さんはアプリ設定をしている配信者さんより配信への入室率や1回以上コメントが送られる割合が下がる傾向にあります。それゆえ配信を続けるモチベーションを保つのが難しく、次回以降の配信の継続率が下がってしまう事象が観測されていました。

コメントがない配信、喋る内容がわからなくなりがちです。私も経験があります……配信してるのに……無言でゲームしてしまいます……つらい……

視聴者さんと配信者さんの適切なアプリのマッチング(見たい・コメントしたい・配信したい)をすることで配信体験の UX を向上させたいと思いました。

Mirrativ は配信プラットフォームであると共にSNSです。配信者さんと視聴者さん共に Mirrativ のプラットフォーム上で配信を通じたコミュニケーションを通じてわかりあってもらうことを願っております。

ゆえに、配信を続けてもらえる配信者さんを少しでも増やすことを目的として当機能を開発することにしました。

しかしながら、iOS/Android ともに OS の仕様上、バックグラウンドで動いている Mirrativ のプロセスから実際にフォアグラウンドで動いているアプリ情報を取得するのは非常に難しいです。

ですが、配信のキャプチャ画像をクラス分類することである程度の精度が出せそうなため、機械学習による配信中のゲームの自動推定機能を開発するに至りました。

f:id:namagon:20190311191922p:plain
イメージ図

対象タイトル

まずは全ゲーム配信中、約70%を占めるゲームにのみに適用して検証して結果が良ければ対象タイトルを拡大していきます。

仕様検討

画像分類で解く以上アプリ推定の精度が100%になることはまずありえません。それゆえはじめは確からしいアプリが推定された際にプレイ中のゲームは hogehoge ですか? [はい] [いいえ] という通知ダイアログを出してユーザーに選ばせる仕様で想定していました。

ところで、ゲームの内容とは無関係の通知ダイアログが出てきたとしてタップしますか?少なくとも僕はしません

配信者さんから見て自動でアプリが設定されることにネガティブな感情を持つことはほぼ無い上、仮にアプリ設定が間違ったとしても重大な問題につながる可能性は非常に低いと判断したため、アプリ未設定の場合はメッセージを出した上で自動で設定することにしました。

プロトタイプ

現在配信者さんが選択しているアプリと画像から推定されたアプリが異なる場合、slack に推定結果を画像つきで投稿するプロトタイプのbotを*1作りました。

f:id:namagon:20190311235832p:plain
ユーザーが設定したアプリと推定したアプリが違うとき投稿されるチャンネル
f:id:namagon:20190307053943p:plain
沸き立つ社内slack

現状のモデルで精度十分でしたが、1枚あたりの推定処理が遅いという課題を抱えていました。

パフォーマンス要件

アプリ未設定の配信者さんに対し可能な限り早く正確な推定をしたいため、現在放送されている全配信の画面キャプチャを1分ごとに画像認識モデルに通すスケジュールバッチを実装することにしました。

この段階でバッチ処理の単位時間と処理件数が算出できたため、あとは実際に運用するインフラの選定に移れます。

今回、モデルの学習処理には Google Compute Engine の GPU インスタンスを利用しています。

しかし、GPU インスタンスを本番運用するとなると CPU インスタンスと比較して利用料金が非常に高価である上リソース監視にGPUも入れる必要があります。ゲーム推定機能は単位時間あたりの処理件数が膨大な量ではなく、モデルの精度もある程度妥協できるため*2 CPU インスタンスの並列処理で対応可能と判断しました。

本番運用するにあたるモデルアルゴリズムの選定

いくつかのモデルを検証したところ、軽量な MobileNet をベースにしたモデルだと精度・処理速度ともにパフォーマンス要件を満たせる可能性が高いと判断しました。

実際にゲーム自動で設定する対象については Confidence *3 の閾値を高めにすることでアプリ設定の正答率を担保するようにしています。

プロトタイプで採用していた VGG16 のモデルと LeNet-5 のモデルと比較してみました。

モデル 設定対象の割合 正答率*4 1枚あたりの処理時間
VGG16 49.7% 98.5% 0.2 sec
LeNet5 55.4% 93% 0.05 sec
MobileNet 63.3% 98% 0.065 sec

精度と処理時間のバランスが最も取れていた MobileNet ベースのモデルを仮採用

試験用の仕組みにデプロイしたところ教師データに Mirrativ の エモモの画像を学習させていなかったため、ゲームとして誤認識してしまう事象が散見されました。

f:id:namagon:20190312000028p:plain
エモモをゲームと認識してしまうミス、かわいいけどこれではだめ、かわいいけど。

それを解決すべく、ゲーム以外の画像を その他 と分類するモデルを作り、自動設定の対象外としました。

f:id:namagon:20190312000054p:plain
その他クラスと認識されるエモモ、これは正しい。そしてかわいい。

モデル 設定対象の割合 正答率 1枚あたりの処理時間
21クラス MobileNet 81.67% 99.2% 0.066 sec

パフォーマンスをほぼ犠牲にすることなく、モデルの精度が更に良くなったのでこれでいきましょう。

配信してみた

アプリ未設定のまま対象タイトルを配信しているとこんな感じでアプリが自動設定されます。

f:id:namagon:20190311182204p:plain
画面は開発中のものです。

今後の展開

現在試験中の機能ですが、ユーザーさんから頂いたフィードバックや自動設定された配信の数値指標から見えてきた今後の展開などを次回の記事で書こうと思います。

追記

書きました!

tech.mirrativ.stream

We are hiring!

Mirrativ では一緒に開発してくれるエンジニアを募集しています!

体験入社や副業も大歓迎です。お気軽にどうぞ!

www.mirrativ.co.jp

*1:私が join する前に副業メンバーに作っていただきました🙇 Mirrativ では副業メンバーも絶賛募集中です

*2:もちろん高ければ高いほどよい

*3:推定結果の確からしさ

*4:Confidence の閾値を超えている画像を対象とした正答率

Mirrativにおける低遅延配信への取り組みについて【開発中】

こんにちは ハタ です。
Mirrativで開発中の低遅延配信機能について、ある程度形がまとまってきて、開発段階から品質チェック段階になりましたのでちょっとだけどんな感じになるか紹介させていただきたいなと思います。

なお、今回紹介するのは開発中のものからピックアップさせていただくので
実際にサービスにリリースされるものとは異なりますのでご留意お願いします。

言葉の定義

まず先に、世の中には「低遅延」という言葉の意味が沢山あるのですが
僕らのいう「低遅延」配信とはざっくり一言でいうと

「配信中の画面がインターネットを超えて視聴画面に見えるようになるまでの早さが短いもの」
としています。
つまり配信画面に映ってるものが視聴端末にすぐ(1秒未満)に再生されるようにする事が目標となっています。

配信した時刻にどれだけ近いか、を示す言葉として低遅延と呼んでいます

まずはどんなものを作っているのか

開発段階のデモシーンを一部ご紹介

f:id:octu0:20190301164722g:plain
デモをスマホで撮影したため縦画面です(この手は赤川)

この映像は弊社の開発環境で、実際にインターネット経由でどの程度の遅延になるかをデモした時の映像です。
左側のAndroid端末でエモモが手を振っているのを右側のiPhone端末で視聴のデモとなっています。
(何度も言いますが開発中のデモとなっているため実際にリリースされるものとは異なることがあります)

低遅延配信を実現するために取り組んでいる事をいくつか紹介できたらいいなと思っています。

目標の設定

現行環境では配信の遅延が概ね 2000ms(2秒) 程度に収まるように実装してあるのですが、これをもっと短く出来ないかというのを松竹梅形式で検討しました。

    • 目標遅延時間:1300ms
    • 配信サーバ・視聴プレーヤの再実装(各レイヤでのバッファリングを最小化する)
    • 目標遅延時間:500ms+
    • 配信側の修正(配信の方法から変えてしまう)
    • 目標遅延時間:300ms - 500ms
    • 配信プロトコルの変更(配信・視聴どちらもライブラリの更新は必要)

突然目標遅延時間が出てきたのですが、
これは「推測するな、計測せよ」のポリシーに則り、どの部分で遅延が発生する要因となっているかを調査し、だいたいこのあたりを改善すればこれくらいになるのではないかなと目星をつけた数値です。

推測するな、計測せよ

「推測するな、計測せよ」は僕自身が自戒の意味も込めてよく使う言葉です
元ネタは Unix哲学 です、まずは計測するところから始めました。

まず、僕らの配信サーバの構成は Origin / Edge 構成と呼ばれる構成になっていて、
配信された映像は Origin サーバに届き、その後 Edge サーバへ送られ、配信データを視聴できるようになっています。

f:id:octu0:20190301210514p:plain
映像データの流れ

ここでOriginサーバ側に届いた映像をEdgeサーバを介さず直接レンダリングするようにして、どれくらいの遅延が発生しているのかを調べることにしました(サーバの構成を変える必要があるのかも含め調査)。

ちょうどいい画面のスクショがなかったため当時記録用に残していた画面からの抜粋になってしまうのですが レンダリングを行ってみたところ下記のようになりました

f:id:octu0:20190301205051p:plain
左が配信画面で右がレンダリングした画像

ここで分かったこととして、Edgeサーバを経由させない場合に 680ms ほどの遅延となっているようです。
また、この方式だと映像が安定するまでに時間を要するということもわかりました

f:id:octu0:20190301211544g:plain
録画用に記録ていた僕のコンソールの様子

コンソールの様子なので分かりづらいのですが、どうやら Edge サーバではこういった映像を安定させるために、ある程度のまとまったデータのバッファを持ってくれているようです。
Edge サーバは Origin サーバの offloading を行っているため、即座にEdgeサーバを無くすことは現実的ではないのですが、このバッファをある程度減らすことは有効そうだということがわかりました。

視聴画面起動までの時間を短くする

次に取り掛かったのは、配信プレーヤ側です
実際に 680ms 程度の遅延が実現できるのか を検証してみたのですが、どうやらそうもいきませんでした。

f:id:octu0:20190301215737g:plain
プロトタイプ開発中のPlaygroundの画面

こちらも開発中の画面からの抜粋で申し訳ないのですが、このPlaygroundで試した時に黒い画面が表示されるまでに時間がかかり、680msとは程遠い時間です。
映像が始まるまでの時刻が遅れている時点では、せっかく Edge サーバの遅延を取り除いてもここが遅いのはもったいないです。

どうして遅いのかを調べるためログを仕込みつつどこか探していたところ、どうやら下記のように(ざっくり)見つけることができました。

2018-27-11 21:52:35.055 [Debug] [Mirrativ] // SPS が届いた時刻
2018-27-11 21:52:35.056 [Debug] [Mirrativ] // VTDecompressionSession 待機
:
2018-27-11 21:52:37.041 [Debug] [Mirrativ] // VTDecompressionSession 待機
2018-27-11 21:52:37.095 [Debug] [Mirrativ] // ここで描画

H.264(AVC)における SPS / PPS については今回はいったん省略しますが、チューニングの余地がありそうでした
特に SPS / PPS と直近の IDR のフレームは一刻も早く プレーヤに届けてあげれば起動までの時間が短くなりそうです
簡易的なサーバ実装をし、Playground で実装してみると

f:id:octu0:20190301221112g:plain
簡易サーバを通した後のPlayground

このように起動が早くなることが確認できました。
ただ直前の IDR フレームも送ってしまっているため、よく見ると再生後時刻が飛んでいる事がわかります。

ここで分かったこととして、現在の Edgeサーバとはちょっと違った Edge サーバの実装が必要そうであるということ、映像の並びを正しくしないと映像が飛んでしまうということが分かりました。

低遅延サーバの実装へ

(低遅延サーバの詳細な実装についてはいつか書きたいと思いますが)既存の配信すべてを置き換えるのは非常に大変なので、既存の配信はそのままに、低遅延に特化させたサーバプロセス(ミドルウェア)を作成することにしました

f:id:octu0:20190302220322p:plain
Originサーバ内のプロセスの様子

これによって、Originサーバからは 1つのストリームから複数のストリーム(既存のストリームと低遅延用のストリーム)が出るようにしました
既存の配信データをそのまま使うことで、iOS/Androidのアプリの改修を極力減らしつつ低遅延配信を実現する事ができるようにするためです。

また、この低遅延サーバが行っていることは、大量の映像フレームをほとんどバッファせずに、なるべく早く映像フレームをプレーヤまで届けるように設計しています。
ちなみに実装は、最近僕がよく使う Go言語を使ってサーバ(ミドルウェア)の実装をしています。

せっかく低遅延サーバを作成したので、既存のプロトコルでは実現できなかった下記のようなものも実現できるようにプロトコルから再実装しました。

  • 映像・音声以外のデータも扱えるようにしたい(例えば APNG のような動く画像をストリームに混ぜたい)
  • AVC 以外の映像コーデックの切り替えをできるようにしたい(コンテナの切り替えが容易であるようにしたい)
  • エモモとリップシンクした情報も送りたい
  • チャットもストリームの一種とみなして扱えるようにしたい
  • なるべくシンプルなパケットにしたい

当初はデコーダに最適化したサーバ実装の予定でしたが、作っていくとやりたいことが沢山あったのでそれを実現できるようにするための実装としました

Mirrativ アプリへ実装

低遅延サーバの実装ができたので、iOS アプリへ低遅延配信のデータを受け取れるように実装しました。
プロトコルの定義や配信サーバの実装も僕が行ったので、iOSの実装(プレーヤとライブラリの実装)も一緒に僕が実装を作りました。

その結果、エミュレータでの実行ですが下記のような状態にまで持ってくる事ができました

f:id:octu0:20190301153804g:plain
少し分かりづらいですがタップしてから映像が再生されるまでの時間が短くなっています

上記の映像は配信一覧画面から視聴したい配信に入るときの動作を新実装と旧実装で比べてみたものです。 映像を何度も見比べていただくのも大変だと思いますので、フレームごとに並べてみました

f:id:octu0:20190301160554p:plain
細かすぎて伝わりづらいかも...。

どうでしょうか、映像フレームでいくと100フレームほど改善したようです。

この時点で当初目標としていた、梅プランと松プランが合わさったような実装が出来上がっていました。

実機での実行

実際問題として実機でも実現できるのか分からないので、実機での実行とエミュレータ上ではない現実のネットワークを通じて低遅延が実現できているのか試してみました

f:id:octu0:20190301234139g:plain
真ん中が低遅延での視聴です

無事に実機でも実現できていることがわかりました
実際にこの時点のデータを計測してみたところ下記のようになりました

f:id:octu0:20190301234416j:plain
一番左が配信・真ん中が低遅延視聴・右が既存の視聴

この時点で160ms ほどの遅延が実現できました。

映像品質の問題

映像の遅延が少なくなったと同時に他の問題も出てきました
それはちょっとしたネットワークの品質の変化が起きると映像も同時に悪くなる事や、フレームレートが揃わないときの映像品質の劣化です。

f:id:octu0:20190301235827g:plain
ネットワーク品質が劣化したときの瞬間

このようにカクつきや映像の乱れがよく発生するようになりました。
低遅延だけを実現することはそう難しくないのですが、低遅延によってこうした今まで目に見えてこなかったネットワークの品質の影響をもろに受けるということがよくわかりました。

f:id:octu0:20190302000243p:plain
僕のエモモがこんなにノイジーな映像になるなんて...。

現在は QA を交えて、品質の劣化が起きても映像に影響がでないようにチューニングを行っています。
チューニングを行っている中でここまでに紹介した遅延時間ではなくなるかとは思いますが、なるべく高品質な状態でお届けできるように鋭意開発中です!

f:id:mirrativ:20190302214619g:plain
QAさんが色んな端末で沢山テストしてくれて、日々レポート沢山上がってきてます...!

低遅延配信の実現へ向けて

以上が低遅延配信への取り組みについて紹介させていただきました
まだリリースもしていないのと、QAによる品質向上のためにまだ開発段階であるものの、「こんな事やってるよ」くらいに思っていただければ幸いです。

また、今回は取り組んでいる事の紹介で、細かなところが紹介できなかったので折を見て細かなところを紹介したいなと思っています

例えば

  • 実は大変、低遅延とバッファリングのせめぎ合い(ジャギる・カクつく・止まる)
  • ネットワークのjitter処理と映像の綺麗さの悩ましい関係(回線品質ディテクションの挑戦)
  • 可変ビットレートと可変フレームレートと低遅延の実現の難しさ
  • (今回省略した内容)
  • (そもそもの低遅延サーバの実装)

などなど、QAを通して分かったことや品質を上げるために苦労したところなど、いつか書きたいなと思います。


We are hiring!
低遅延配信を一緒に開発してくれるエンジニアを募集中です! 体験入社というのもあるのでお気軽にどうぞ!

www.mirrativ.co.jp