19
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ドワンゴAdvent Calendar 2020

Day 5

Google Stadiaライクなリアルタイム映像配信を試す

Last updated at Posted at 2020-12-05

TL;DR
Vulkan と WebRTC を使ってリアルタイム映像配信にチャレンジしました。
https://github.com/ogukei/rigel

免責事項

筆者はクラウドゲーミング開発の専門家ではないです。

Google Stadiaなどのサービスでは大規模なスケールを可能にするための様々な工夫が施されていますがここでは特に取り扱いません。

はじめに

こんにちは。@ogukei_t です。社内ではiOSアプリを開発しています。

本記事は業務と関係が薄いです。iOS開発からは離れた内容となってしまいました。1年ほど前に社内LTで個人的に発表した内容のまとめになります。

何をつくるか

ユーザーがコントローラーを操作するとそれに応じてサーバーが映像を作成し、瞬時にその映像がユーザーの元に届くシステムをつくります。イメージは以下の図のとおりです。

  1. ユーザーが操作
  2. サーバーが映像を作成
  3. ユーザーへ映像を配信

01-overview.png

モチベーション

主に以下の3点があります。Google Stadiaの雰囲気をちょっとでも体験したいというのがモチベーションになります。リアルタイム映像配信の面白さを少しでも感じていただければ幸いです。

  • 色々な環境でリアルタイム映像をヌルヌル動かしたい
  • クラウドゲーミングで使われている技術がとても興味深い
  • おま国

Google Stadiaとは

2019年のGDCでGoogleによってGoogle Stadiaが発表されました1。Google Stadiaはクラウドゲーミングサービスのひとつで、YouTubeを活用して瞬時にゲームを起動・共有したりモバイル端末からでもAAAタイトルのゲームをプレイできる特徴があります2

02-stadia.png

YouTube: Google GDC 2019 Gaming Announcement

クラウドゲーミングサービスには様々な種類があり、他にはAmazon LunaやProject xCloud, Nvidia GeForce Nowなどがあります。

2020年現在、Google Stadiaはまだ日本では残念ながらサービスが開始されていません。ちなみに筆者はかなり期待3しているのですが、やはり結構ハードルがあるのでしょうか。

使われている技術(ざっくり)

Google Stadiaのベースになっている技術をざっくり追ってみます。解説についてはGoogle IO 2019で興味深いセッションがありました4。Google Stadiaの主なコンセプトについて解説されていて参考になります。

YouTube - Stadia Streaming Tech: A Deep Dive (Google I/O'19)

冒頭は特にリアルタイム性が求められるという話です。例えば一般的な動画配信ではオフラインエンコードが可能でキャッシュをCDNに持つことができます。しかしクラウドゲーミングはユーザーの入力を得て初めて映像をつくり出すため、キャッシュしたいところですがそうはいきません。

cloud-gaming-diff.png

続いてネットワークの課題の話です。一貫した体験を大きなスケールであらゆる環境のユーザーへ届けるのは困難を伴います。ユーザーへデータが届くまでにいくつもの地点を経由します。バッファが特に大きい地点があるとそこでパケットが詰まって再送・パケットロスが発生するケースがあります。そのため再送・輻輳制御が重要です5

congestion.png

実装に向けて

リアルタイム性を保つために遅延を最小限にします。TCPによる送受信だけではオーバーヘッドが大きいため大部分のデータの送受信にはUDPを使います。

しかしサーバーからクライアントへの経路において単にUDPのパケットを送りつけるだけではNATを超えられない問題があり、その解決にはNAT traversal, UDP hole punchingといったテクニックが有効です。ただし1から実装するととても大変なため既存プロトコルの Interactive Connectivity Establishment (ICE) を用いるとよいです。

接続が確立すると今度は操作入力や映像といったデータを送受信します。TCPに比べるとUDPはステートレスで高速ですがパケットロスが問題になる場合があります。様々な環境で安定して動作させるためには再送・輻輳制御が重要になります。

ここでWebRTCが登場します。SCTPやRTP(SRTP)を活用することで順序保証や再送・輻輳制御をやってくれます。

上記の理由かは定かではありませんが、Google StadiaはWebRTCを使用しているようです678。WebRTCには上記の例以外にもふんだんに技術が詰め込まれています。

さらにゆくゆくはGoogle StadiaはWebTransportを使用する予定があるようです89。WebTrasportはQUICを用い到達を保証しながらもリアルタイム双方向通信を実現します101112。本記事ではWebTransportは紹介に留めて実装にはWebRTCを用います。

既存ライブラリの紹介

国内のネイティブWebRTCクライアントといえば、時雨堂さんの WebRTC Native Client Momo が有名です。またWebRTCに関する知見がまとまった資料がMediumで多数公開されています613

Medium - 時雨堂の WebRTC に関する取り組み

実装

主な処理の流れは以下のようになります。入力はユーザーによる、例えばコントローラーやマウスなどの何かしらの操作で、出力はその入力を元にレンダリングされた映像です。

03-process.png

それぞれ以下のプロトコル・ライブラリを使用します。

機能 プロトコル・ライブラリ
入力 WebRTC data channels over SCTP
描画 Vulkan
エンコード CUDA NVENC
配信 WebRTC media channels H.264

Ubuntu 18.04 LTS上でネイティブアプリケーションとして動きます。

WebRTCの実装はGoogle謹製のChromiumにも搭載されているlibwebrtcを使います。本実装の開発言語はC++14です。最適化がしやすい点とChromium等ライブラリとの互換性が高い点があるためです。

Docker上でビルドして動かせます。描画とエンコードにGPUが必要ですが Nvidia Container Toolkit を使うことでコンテナ内部でNvidiaのGPUを利用することができます。

全コードはGitHubに公開しています。

Rigel
Stadia-like realtime graphics streaming software using WebRTC and Vulkan
https://github.com/ogukei/rigel

基本的な工夫

以下の2点に重きを置いています。

  • コピーを最小限にする
  • とにかくシンプルにする

コピーを最小限にする

処理の流れは上記でも触れましたが、ユーザーの操作を受信した後はできる限り遅延を少なくして映像をユーザーの元に返したいです。オーバーヘッドをできるだけ少なくする努力をしました。実装上でオーバーヘッドを少なくする代表的な手段のひとつはデータの無駄なコピーを避けることです。

描画はVulkanを使ってGPU上で行います。描画結果はGPUのメモリに保持されますが、この後のエンコードもGPU上で行うため、描画結果をそのまま使うことができます。こうしてCPUとGPU間のデータのやり取りを最小限にすることで高速化を図ります。

具体的にはVulkanのVK_KHR_external_memory extensionとCUDAのgraphics interoperability functionsを組み合わせて実現します14

とにかくシンプルにする

描画機能はオフスクリーンへの描画だけ必要で、モニターへ実際に表示する必要はありません。Vulkanはheadless renderingが可能です。Swap chainなどの使わない拡張機能を削ぎ落として使用します。

デモ

映像はFull HD 60fpsに設定しました。奥のデスクトップPC(見えない)から手前のiPhone, iPad, MacBookの3台へ同時に配信しています。iPhoneは4G回線で接続しています。iPadとMacBookはローカルネットワーク内にあります。

ラグを感じさせない程度に反応してくれます。

デスクトップPCの動作環境です。

動作環境
OS Ubuntu 18.04 LTS
CPU Intel Core i7-3930K @ 3.20GHz
GPU Nvidia RTX 2070

まとめ

リアルタイム映像配信の基本部分をつくりました。WebRTCはとても強力で偉大な技術が詰め込まれているという認識を新たにしました。

遅延との戦いは果てしないのですが、Webページやスマートフォンアプリでも通用する話かと思います。最適化を行う上での考え方に役立てていきます。

  1. YouTube - Google GDC 2019 Gaming Announcement

  2. Engadget - 速報:Google Stadiaは月9.99ドル、日本含まぬ14か国で11月開始。初期タイトル発表

  3. 当時のTwitterの様子
    https://twitter.com/ogukei_t/status/1108057981604683778?s=20
    https://twitter.com/ogukei_t/status/1108065742392422400?s=20
    https://twitter.com/ogukei_t/status/1108064603047510016?s=20
    https://twitter.com/ogukei_t/status/1108066208589340672?s=20

  4. Qiita - Stadiaのリアルタイムストリーミングを実現する技術(Google I/O 2019の発表まとめ)

  5. Cloud-gaming:Analysis of Google Stadia traffic

  6. Medium - リアルタイム映像配信サーバ開発者からみた STADIA 2

  7. YouTube - Google WebRTC project update & Stadia review

  8. WebRTC by Dr Alex - #WebRTC in Google Stadia – Redefining RealTime streaming at scale 2

  9. WebRTC unbundling: the beginning of the end for WebRTC?

  10. web.dev - Experimenting with WebTransport

  11. WebTransportを用いてブラウザ上からUDP/QUICによるリアルタイム双方向通信を行う

  12. WebTransport と WebCodecs そして Web はどこまで “ゲーム化” するか

  13. Medium - 時雨堂の WebRTC に関する取り組み

  14. Vulkan CUDA interopのコード

19
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?