ticktakclockの日記

技術ポエムを綴ったりします。GitHub idも同じです (@ticktakclock)

Androidで動画配信アプリを作成する

こんにちはtkyです。

前回GCP上に動画配信サーバを作成しました。

今回はこの動画配信サーバにアクセスできるクライアントアプリを作成してみようと思います。

何作ったの

Androidで動画配信アプリを作成しました。言語はKotlinです。

構成は前回PCから配信していたのをAndroid端末に変更しただけで、サーバ構成は変わらずです。 f:id:ticktakclock:20180918200631p:plain

コードはGitHubRtmpClientを参照してください。

前回ストリームキーの話をしましたが、今回はandroid固定で配信することとします。 ※rtmp://xxx.xxx.xxx.xxx/live/android というURLに固定で配信、視聴することになります。

一応、動画を送信する側を「配信」、受信する側を「視聴」と呼ぶことにして進めたいと思います。

どんな感じで作ったの

実装については後述でポイントでコードを載せます。UI関連の説明はしないのでGithub見てもらえたらと思います。

技術的な話

配信側についてはRtmpPublisherライブラリを利用させていただきました。

視聴側についてはExoPlayerextension-rtmpという拡張がありましたのでこの2つのライブラリで実現できそうです。

それぞれAndroid配信⇒VLC視聴、OBS配信⇒Android視聴という流れで画面毎に確認して、最後にAndroid配信⇒Android視聴を確認して完成としたいと思います。

OBSはPCで利用できる配信ツールの事です。

VLCはPCで利用できる動画再生ソフトですが、リアルタイム動画配信の視聴ツールとしても利用できます。

画面的な話

コードはGitHub見てもらえたらですが、簡単に構成だけ。

一応、各画面はFragmentで構成して、1Activity(MainActivity)で作ってみます。(※後にはまることになるとはこの時は知る由もなかった・・・)

  • メイン画面(MainFragment) 配信ボタン、視聴ボタンを作成します。
    • 配信ボタン 配信画面に移動
    • 視聴ボタン 視聴画面に移動
  • 配信画面(PublisherFragment) 配信開始/停止ボタンを作成します。
    • 配信開始/停止ボタン 配信停止中:文言「開始」、タップ時:配信開始する 配信中:文言「停止」、タップ時:配信停止する
  • 視聴画面(PlayerFragment) 遷移したら視聴開始します。また更新ボタンを設置します。
    • 更新ボタン 視聴停止⇒視聴開始する

視聴側

視聴側についてはExoPlayerを使っていきます。

gradle

gradleでexoplayerに必要なモジュールとrtmp拡張の記述を記載します。 ExoPlayerは2.6.0を使っています。

    // ExoPlayer
    // https://github.com/google/ExoPlayer
    implementation "com.google.android.exoplayer:exoplayer-core:$EXO_PLAYER_VERSION"
    implementation "com.google.android.exoplayer:exoplayer-ui:$EXO_PLAYER_VERSION"
    implementation "com.google.android.exoplayer:extension-rtmp:$EXO_PLAYER_VERSION"

(余談)バージョンについて

バージョン情報はすべてgradle.propertiesに記述して各gradleでこの値を参照するように作成しています。 このようにすることで1つのバージョン変更でこれを使用しているライブラリバージョンは一気に変更できて楽ですね。gradleありがとうって感じです。

# libraries
GRADLE_PLUGIN_VERSION=3.1.4
APP_COMPAT_VERSION=27.1.1
CONSTRAINT_LAYOUT_VERSION=1.1.3
TIMBER_VERSION=4.5.1
BUTTERKNIFE_VERSION=8.8.1
RTMP_PUBLISHER_VERSION=1.1.2
EXO_PLAYER_VERSION=2.6.0

Kotlinコード

Kotlinに入る前にまずはXMLから。案外コード量が少ないです。

    <com.google.android.exoplayer2.ui.SimpleExoPlayerView
        android:id="@+id/fragment_player_exp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:resize_mode="fill"
        app:surface_type="texture_view"
        app:use_controller="false"
        >

Fragment側でこのViewに対して操作します。ButterKnifeを使ってちょっとだけすっきりさせます。

基本的にExoPlayerを使用するときと同じように定義して、RTMPプロトコルを使用する場合はMediaSourceインスタンスを作るときのDataSourceFactoryの指定でRtmpDataSourceFactoryを指定するだけです。

rtmp://xxx.xxx.xxx.xxx/live/stream_key url中のlivertmpサーバのアプリケーション名ですね。前回の記事をご覧ください。

    ・・・中略・・・
    @BindView(R.id.fragment_player_exp)
    lateinit var playerView: SimpleExoPlayerView
    private var player: SimpleExoPlayer? = null
    ・・・中略・・・
    /**
     * 再生を開始する
     * */
    private fun playStart() {
        // rtmp://xxx.xxx.xxx.xxx/live/stream_key
        val uri = Uri.parse("rtmp://$ipAddress/live/$streamKey")
        val player = ExoPlayerFactory.newSimpleInstance(
                DefaultRenderersFactory(context), DefaultTrackSelector(), DefaultLoadControl())
        playerView.player = player
        // rtmpプロトコルを使用する場合はRtmpDataSourceFactory()を使用する
        val mediaSource = ExtractorMediaSource(uri, RtmpDataSourceFactory(), DefaultExtractorsFactory(), null, null)
        player.prepare(mediaSource)
        player.playWhenReady = true
        this.player = player
    }
    /**
     * 再生を停止する
     * */
    private fun playStop() {
        player?.let {
            it.playWhenReady = false
            it.release()
        }
    }

ButterKnifeについて

ButterKnifeはButtonとかViewの定義をアノテーションを使って楽に定義できますって感じのライブラリです。 OnClickのイベントとかもアノテーションだけで定義するのでわざわざButton定義して、onClickListener定義して・・・ということをしなくてよくなるのは個人的に負荷が下がります。

視聴確認

OBSでrpmt://xxx.xxx.xxx.xxx/live/androidに配信してみます。 で、アプリ起動して待ち受けてみると・・・

f:id:ticktakclock:20180918194638j:plain

でた!!細長い!!! 16:9の配信に対して、スマホの画面いっぱいに拡縮して表示しようとしているのでまぁしょうがないですね 😅

こういったところを整備していくの大変そう・・・ とはいえ、視聴側は確認できました。

配信側

配信側はRtmpPublisherを使っていきます。 本当にありがたいことに使い方等がしっかりREADMEに書かれており特に不自由なく利用できました。

usageを見ると

val publisher: Publisher = Publisher.Builder(this)
  .setGlView(glView)
  .setUrl(rtmpUrl)
  .setSize(Publisher.Builder.DEFAULT_WIDTH, Publisher.Builder.DEFAULT_HEIGHT)
  .setAudioBitrate(Publisher.Builder.DEFAULT_AUDIO_BITRATE)
  .setVideoBitrate(Publisher.Builder.DEFAULT_VIDEO_BITRATE)
  .setCameraMode(Publisher.Builder.DEFAULT_MODE)
  .setListener(this)
  .build()

ということなので画面に以下のようなGLSurfaceViewを張り付けて、インスタンスPublisherに設定すればよさそうです。 あとはこのpublisherに対して、startやstop処理をしてあげます。 ライブラリではカメラプレビューの実装も入っているので本当にこれだけで実現できる仕様になっているのがうれしい限りです。

カメラ(動画)を使用するので、Manifestには以下が必要です。 で、今回パーミッションチェックの機構は実装しないので自分でパーミッション許可します・・・

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

自分でチェックしてね ✅ f:id:ticktakclock:20180918194705p:plain

Kotlinコード

こちらもKotlinに入る前にまずはXMLからいきましょう。Publisherに渡すためのGLSurfaceViewを定義します。

    <android.opengl.GLSurfaceView
        android:id="@+id/fragment_publisher_glv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

Kotlinコードは抜粋で載せますので、詳細はRtmpClientを見てください。

    /**
     * preparePublisher
     *
     * */
    private fun preparePublisher() {
        // rtmp://xxx.xxx.xxx.xxx/live/stream_key
        val url = "rtmp://$ipAddress/live/$streamKey"
        // 転送不可を下げるため動画サイズは320x240とする
        publisher = Publisher.Builder(activity as AppCompatActivity)
                .setGlView(glView)
                .setUrl(url)
                .setSize(320, 240)
                .setAudioBitrate(Publisher.Builder.DEFAULT_AUDIO_BITRATE)
                .setVideoBitrate(Publisher.Builder.DEFAULT_VIDEO_BITRATE)
                .setCameraMode(Publisher.Builder.DEFAULT_MODE)
                .setListener(this)
                .build()
    }

で、実行してメイン画面から「配信ボタン」を押してみます。

     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.hardware.Camera$Parameters com.takusemba.rtmppublisher.CameraClient.open()' on a null object reference
        at com.takusemba.rtmppublisher.RtmpPublisher.onResume(RtmpPublisher.java:100)
        at java.lang.reflect.Method.invoke(Native Method)
        at android.arch.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:218)
        at android.arch.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:193) 
        at android.arch.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:184) 
        at android.arch.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:36) 
        at android.arch.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:354) 
        at android.arch.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:180) 
        at com.takusemba.rtmppublisher.RtmpPublisher.<init>(RtmpPublisher.java:39) 
        at com.takusemba.rtmppublisher.Publisher$Builder.build(Publisher.java:158) 
        ・・・中略・・・

あれーーーー落ちるんですけどーーーー!!!

ライブラリを調べてみるとLifecycleObserver使っているようでした。さらに調べてみると、RtmpPublisherクラスのコンストラクタの初めにactivity.getLifecycle().addObserver(this);しているようですね。 これによりaddObserver(this)した瞬間に@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)アノテーションが付いているメソッドが呼ばれて、まだカメラインスタンスが作成できていないので、NPEの運びとなります。

fragmentはまだonResumeしていないのですが、ActivityはすでにResume状態なので、簡単に言うと1ActivityにしてFragmentでこれを実装しようとすると詰みということがわかりました 😇😇😇😇

ということでPublisherActivityを作成し急遽2Activity構成に変更です・・・

PublisherActivityについてはGithub参照ください。

で、ようやく配信!ちゃんと映像がでました! VLCでも確認すると、画像は非常に乱れていますが、配信出来ていることが確認できました。

f:id:ticktakclock:20180918194752g:plain

もう一台あるAndroid端末で配信、別のAndroid端末で視聴をやってみても3,4秒程度の遅延(かつ画像解像度は低い・・・)で視聴することができました。

配信時のインスタンス負荷状況

一応、配信時のGCPの負荷状況載せておきます。 GCPインスタンスについては前回記事見てください。

ネットワークの転送自体はとがったようになっているのに対して、ディスクIOはピークの後ろにも若干波がありますね。

RTMPサーバの配信データの置き場所 /usr/local/nginx/html/live/hls を確認すると何も入っていなかったことから、一定時間たつと配信データは削除されるようですね。 この一定時間(約5分?)は誰が設定して、どう処理しているのかなどは調査していません。余裕を見て調べつつサーバサイドと仲良くなれたらよいなと思います。

f:id:ticktakclock:20180918194825p:plain f:id:ticktakclock:20180918194836p:plain f:id:ticktakclock:20180918194843p:plain f:id:ticktakclock:20180918194852p:plain f:id:ticktakclock:20180918194903p:plain

まとめ

  • Androidで動画配信及び視聴クライアントを作成した
  • 今回ストリームキーはandroid固定にしたが、できればストリームキー生成はサーバ側に任せてみたい
  • 視聴側はExoPlayer使えば良いが、配信側は独自で作った方が良さそう(動画配信サービスとしてちゃんと作ろうと思った場合)
  • 想像以上に画像が荒かった。動画のサイズと通信速度かな?と思いつつどこが原因か切り分けてはいないので、余裕を見て調べてみたい。

今回作成したコードはGitHubにアップしていますのでRtmpClientを参照してください。

参考文献

様々なサイトを活用させていただきました。感謝です!!

RtmpPublisher https://github.com/TakuSemba/RtmpPublisher

ExoPlayer関連 https://qiita.com/niusounds/items/cce4ff69f5911908259b

GCP上に動画配信サーバーを作成する

はじめましてtkyです。

かねてから動画配信の仕組みに興味があったのでいろいろと調べて 理解ついでにやったことをまとめていきます。 GCPインスタンスの作り方は説明しません。

何作ったの

GCP上にUbuntu仮想マシンを構築、nginxを使用して動画配信サーバを作成しました。

図としてはこんな感じです。YouTubeLiveやニコニコ生放送のように配信者1名がいて、複数名の視聴者がいるような感じのライブ配信サービスですね。

f:id:ticktakclock:20180912202835p:plain

GCP仮想マシンを作る

GCPの12か月無料のやつを使いました。 やり方はググってください!クレカ片手にLet's try!

こんなにスペックいらないかな?と思いつつ以下の構成で作成します。

つくったらこうなります f:id:ticktakclock:20180912202932p:plain

ssh接続できるようにする

windowsの場合

C:\Users\ticktackclock\.ssh>ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\ticktackclock/.ssh/id_rsa): rtmp
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in rtmp.
Your public key has been saved in rtmp.pub.
The key fingerprint is:
SHA256:******************** ticktackclock@**************
The key's randomart image is:
+---[RSA 2048]----+
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
+----[SHA256]-----+

こんな感じでssh接続します。-i rtmpというのは先ほど作成した鍵情報を利用してssh接続しますよ、という意味ですね。

ssh xxx.xxx.xxx.xxx -i rtmp

※IPはVMの外部IPを指定します。

ssh接続時、パスワードを求められます。(sshkey-genで鍵を作成した時に指定したパスワードです)

The authenticity of host 'xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '***.***.***.***' (ECDSA) to the list of known hosts.
Enter passphrase for key 'rtmp':
Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-1018-gcp x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sun Sep  9 12:53:03 UTC 2018

  System load:  0.0               Processes:           96
  Usage of /:   2.3% of 48.29GB   Users logged in:     0
  Memory usage: 3%                IP address for ens4: ***.***.***.***
  Swap usage:   0%

 * Read about Ubuntu updates for L1 Terminal Fault Vulnerabilities
   (L1TF).

   - https://ubu.one/L1TF

 * Want to make a highly secure kiosk, smart display or touchscreen?
   Here's a step-by-step tutorial for a rainy weekend, or a startup.

   - https://bit.ly/secure-kiosk


  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

ticktackclock@rtmp-server:~$

nginxをインストールする

先ほど立てた仮想マシンにnginxをインストールしていきます。

nginxとは?

OSSのwebサーバーのこと。 1対多(アクセス)の同時処理が得意。 消費メモリが少ない。 動画配信するような1対多アクセスの構成ならnginxの方がよさそうということで採用。

インストール方法

方法はいくつかあるようですが、 rtmpモジュールがデフォルトのnginxに入っていない為、ソースからコンパイルの方法で自分でビルドする必要があるようです。

必要なもの

# 必要なものインストール
$sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev unzip zlib1g-dev

# nginxのソースコードダウンロード
$wget http://nginx.org/download/nginx-1.14.0.tar.gz

# rtmpモジュールをダウンロード
$wget https://github.com/arut/nginx-rtmp-module/archive/master.zip

# それぞれ解凍
$tar xvzf nginx-1.14.0.tar.gz
$unzip master.zip

# 解凍できたかlsで確認
$ls
master.zip  nginx-1.14.0  nginx-1.14.0.tar.gz  nginx-rtmp-module-master

# nginxソースコードディレクトリでビルド
$cd nginx-1.14.0/
$./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master
$make
$sudo make install

※私の場合、zlib1g-devをインストールしおらず、./configureするところでエラー吐きました。zlib1g-devをapt-get installしてもう一度./configureすると成功しました。

configureの結果以下のようなものが出力されます。この辺にnginxが入るんだなぁと思ってもらえれば良いかと。

Configuration summary
  + using system PCRE library
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

(超余談)公式nginxをリポジトリに追加してapt-getする方法

この項目は「そうなんだ~」で読み飛ばしてください。

ubuntuの初期リポジトリにあるnginxはバージョンが古いらしい(?)ので公式のリポジトリからインストールする必要があります。

調べてもらえれば一通り手順は出てくるのですが、備忘録のため記載しておきます。

# nginxサイトが配布するPGPキーを追加
$curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add -

# リポジトリを一覧に追加
$VCNAME=`cat /etc/lsb-release | grep DISTRIB_CODENAME | cut -d= -f2` && sudo -E sh -c "echo \"deb http://nginx.org/packages/ubuntu/ $VCNAME nginx\" >> /etc/apt/sources.list"
$VCNAME=`cat /etc/lsb-release | grep DISTRIB_CODENAME | cut -d= -f2` && sudo -E sh -c "echo \"deb-src http://nginx.org/packages/ubuntu/ $VCNAME nginx\" >> /etc/apt/sources.list"

# updateしてからnginxをインストール
$sudo apt-get update
$sudo apt-get install nginx

起動確認

余談はさておいて、nginxがinstallできたはずなので起動確認です。

# nginx起動
$sudo /usr/local/nginx/sbin/nginx

# nginxが起動しているか確認
$ps aux | grep nginx
root     14331  0.0  0.0  32876   820 ?        Ss   13:02   0:00 nginx: master process nginx
nginx    14332  0.0  0.0  37700  4388 ?        S    13:02   0:00 nginx: worker process
ticktackclock    15004  0.0  0.0  14856  1096 pts/0    R+   14:53   0:00 grep --color=auto nginx

ブラウザからも見てみましょう。

http://xxx.xxx.xxx.xxx

f:id:ticktakclock:20180912203018p:plain

/usr/local/nginx/html/

なおここで表示されているhtmlは上記のパスに入っています。 ただの静的なページを載せたいだけならこのディレクトリ直下にindex.html置けば自分のwebサイトを公開できるということですね。

GCPrtmp通信用のport:1935を開ける

rtmpTCP:1935ポートを使用して通信します。

GCPのデフォルトではこのポートはファイアウォールの設定をしておらず、rtmp通信しても為はじかれてしまうのでちゃんとポート開けましょう。

ファイアウォールルールの設定

メニューより

 ネットワーキング>VPCネットワーク>ファイアウォールルール

ルールの命名規則は以下のような感じらしいですが、ガン無視してしまいました・・・

  • 名前:allow-{{port}}
  • ターゲット:allow{{port}}-server

f:id:ticktakclock:20180912203110p:plain f:id:ticktakclock:20180912203119p:plain

作成できると以下のようにルールのリストに表示されます。

f:id:ticktakclock:20180912203141p:plain

※名前間違えると編集では変更できず、もう一度作り直しになるの地味にめんどいです

VMインスタンスにルール適用

これだけで満足しては実はいけないんですよね。

作成したルールをVMインスタンスに適用して初めて作業完了となります。

メニューより

 コンピューティング>Computing Engine>VMインスタンス

VMインスタンスの詳細からネットワークタグを編集します。

ネットワークタグはファイアウォールルールで設定したターゲットタグを指定します(今回の場合allow1935-server) f:id:ticktakclock:20180912203203p:plain

nginxにrtmpの設定をする

$sudo vim /usr/local/nginx/conf/nginx.conf
rtmp_auto_push on;

rtmp {
  server {
    listen 1935;
    chunk_size 4096;

    application live {
      live on;
      hls on;
      # 録画しないならoffとする
      record all;
      record_path /usr/local/nginx/html/record/hls;
      record_unique on;

      # hlsデータをどこに置くか
      hls_path /usr/local/nginx/html/live/hls;

      # hlsの分割単位
      hls_fragment 5s;
      hls_type live;
    }
  }
}

confで指定したディレクトリは事前に作成しておきましょう。

$sudo mkdir -p /usr/local/nginx/html/record/hls
$sudo mkdir -p /usr/local/nginx/html/live/hls

再起動する

$sudo /usr/local/nginx/sbin/nginx -s stop
$sudo /usr/local/nginx/sbin/nginx

なぜか-s reloadでは再起動してくれず、上記の方法で再起動させました。

$sudo /usr/local/nginx/sbin/nginx -s reload //この方法では再起動しなかった

※ちなみにrtmpモジュールが入っていないnginxではこのエラーがでるので、ちゃんとソースコードビルドしましょう。 nginx: [emerg] unknown directive "rtmp" in /etc/nginx/conf.d/default.conf:45

配信確認

これでサーバ側の準備が整ったことになります。自分のPCから配信してみます。

  • 配信ツールとしてOBSを使用する
  • 視聴ツールとしてVLCを使用する

ライブ配信サイトに対して使用できる無料の配信ツールです。インストールしてください。

配信サーバ単体のテストやAndroidなどのモバイル端末から配信した時の問題の切り分けなどに役立ちました。

URLとストリームキー

URLとストリームキーを設定します。

f:id:ticktakclock:20180912203233p:plain

設定出来たら配信開始!!!

  • [x] URL:rtmp://xx.xx.xx.xx/live
  • [x] ストリームキー:android

URL末尾のliveってなんぞや

nginxのconfで設定したapplication名のことです

rtmp {
・・・
    # ここで設定したliveが「rtmp://xx.xx.xx.xx/live」という配信URLになる
    application live {
      ・・・
    }
・・・
}

ストリームキーってなんぞや

ライブ配信するときの固有IDとなるもの。ユーザIDをストリームキーとかにするとAさんの配信Bさんの配信という考え方が作れそうですね。

rtmpアプリケーション単位で一意である必要があるので、ユーザIDでも良さそうですが、実際はサーバ側で一意のストリームキー(ハッシュとか)を生成して、配信者(クライアント側)でそれを使ってもらうという運用がよさそうです。

※実際にサービス運用でどうやってストリームキーを作成しているのか気になりますね。

VLCで配信出来ているか確認する

メニューからネットワークストリームを開く

メディア(M) > ネットワークストリームを開く(N)

f:id:ticktakclock:20180912203340p:plain

ネットワークURLにはOBSで設定したURLとストリームキーをくっつけたものを指定して再生!!!

rtmp://xxx.xxx.xxx.xxx/live/android

2~3秒くらいの遅延後、VLCで再生されているのが何となくわかりました。

仮想環境上の見え方

OBSで配信している間、サーバ上でどんなファイルができているのか見てみます。

$cd /usr/local/nginx/html/live/hls
$ls
android-0.ts  android-2.ts  android-1.ts  s  android.m3u8

5秒(nginxのconfでhls_fragment 5s;で設定した為)に1つずつtsが追加されていくのが確認できました。

配信時のインスタンス負荷状況

折角GCP使ってモニタリングできるので確認してみましょう。

こんな感じです。1つの配信、1つの視聴だけならCPU1%ほど。

f:id:ticktakclock:20180912203417p:plain f:id:ticktakclock:20180912203428p:plain f:id:ticktakclock:20180912203437p:plain f:id:ticktakclock:20180912203447p:plain f:id:ticktakclock:20180912203458p:plain

まとめ

  • GCPの無料枠で動画配信サーバを作成してみた
  • 新しいプロトコルの知識やサーバサイドの事を知れた
  • 何人くらいの同時配信に耐えられるのだろうか

次回はAndroidアプリからこのサーバに対して配信及び受信をしてみたいと思います!

next:Androidで動画配信アプリを作成する

参考文献

様々なサイトを活用させていただきました。感謝です!!

https://qiita.com/sparkgene/items/c3ac042f30cc5d0fe324

https://christina04.hatenablog.com/entry/2015/01/08/205438

https://centossrv.com/nginx-nginx-rtmp-module.shtml