HTML5 Videoタグで簡単HTTPストリーミング組込み忘備録:キャッシュも併用してセキュア・低遅延なHLSライブ配信ができぬものかーヽ(*´∀`)ノ


簡単組込み、セキュア、低遅延なHTTP HLSライブ配信を目指す

コロナ禍で最近依頼内容として多いのが、朝礼ライブ配信とか、遠隔ライブ監視とかをZOOMとかオンライン会議ソフト使わずに、サクッとライブ配信としてWEBサイト内に埋め込んで欲しいと言うご要望でございまして。。。
サクッと埋め込むにも実現までに必要な構成もありますし、他でも再生できてしまってはマズイのでそれなりにセキュアさも保ってなど、色々と勘案しないといけない事もあり思い悩んでました。。。が、結構簡単に組込みが出来るやり方があったので忘備録です。

<目次>
-ライブ配信に必要な構成
-エンコーダの用意
-ストリーミングサーバ側の設定&低遅延を目指す
-セキュア配信の設定
-HTMLへVideoタグで簡単組込みする

ライブ配信に必要な構成

何はともあれ、ストリーミングのフォーマットを決めなければいけません。
一般的にはライブ配信といえば低遅延のRTMPでしたが(それでも5秒ぐらい遅延しますが)、ストリーミングサーバ側のサポート終了問題や、視聴プレーヤ側の組込みが面倒かもなので、やはり今流行りのHTTPプロトコルを利用したHLSのHTTPストリーミングで行ってみたいと思います。

■HTTPストリーミングの特徴は以下の3点です。
1. 汎用性の高いHTTPプロトコルを利用
2. 大規模配信にも対応
3. マルチデバイス対応

■HLS(HTTP Live Streaming)ストリーミングの特徴
macOSやiPhoneで知られるAppleが開発したHTTPストリーミングです。
同社のMac、iPhone(iPAD)に加えAndroid端末でも再生することができます。Windows環境で再生するにはFlashPlayerベースのプレイヤーが必要となることが多かったのですが、現在はHTML5+JavaScriptのプレイヤーが公開されているためプラグイン無しで再生することが可能です。非常に高いシェアを持ち、HTTPストリーミングの代表格となっています。

HTTPストリーミングはたしかCDNETWORKS CDN側で変換できるストリーミングサーバサービスがあったはずなのでそれを使えば構築の手間が一個減るので活用しようかと、しかもHTTPストリーミングなら、動画をキャッシュしても映像再生は可能なので、HTTPのキャッシュシステムを主力とするCDNととても相性のよい技術かと。あとはエンコーダとフロントエンドを用意するだけなのでせっかくなので活用してみました。
多数のユーザが視聴する大規模配信、安定した配信環境が必要なコーポレートサイトの動画などさまざまな場面で活用できそう。

■今回の構成
1. エンコーダ
  カメラ付きのノートPCにWirecastというエンコーダソフトを入れてもらってストリーミングをしようと思います。
2. ストーミングサーバ
  一番重要な根幹ですが、構築めんどくさいのでCDNプラットフォームにあるストリーミングサーバを使います
3. 視聴ページ
  プレーヤ等購入なしで簡単に導入したいのでHTML5 Videoタグで現行ページにサクッと埋め込みたいと思います

エンコーダの用意

ライブエンコーダは、Webカメラの映像や動画ファイルの映像などをストリーミングサーバへ送信するソフトウェアまたはハードウェアです。今回はソフトウェアのライブエンコーダとしてよく知られるWirecastを利用します。配信元お客様のノートパソコンに入れてもらいました。

■ Wirecastのインストール
Wirecastは有償のソフトウェアです。WirecastのWebサイトでライセンスの取得(購入)が必要となります。デモモードで動作する無償トライアルも可能です。今回はライセンスの取得、Wirecastのインストール、アクティベーションが完了していることを前提に進めます。

■ 配信の設定
上部メニューの「配信」から「配信の設定」を押します。

■ 出力先の選択
配信先を「RTMPサーバ」に設定してから「OK」を押します。

■ 出力先の詳細設定
ライブエンコーダがストリーミングサーバへ映像データを送信する際の詳細設定を行います。これは次項のストリーミングサーバ設定で作成したストリーミングサーバアドレスが必要ですので一旦ここで止めておきます。

ストリーミングサーバ側の設定&低遅延を目指す

CDNETWORKSカスタマーポータルで”Products → Media Acceleration → Configuration"にアクセスします。

ここでエンコーダからの出力受けとしてPUSHアドレスの設定、並びに配信側になるPULLアドレスの設定を行います。利用する際は何かしらのドメインアドレスが必要ですのでDNSの設定権限があるドメインを利用します。
今回は下記の様に設定してみます。

PUSH(エンコーダ→ストリーミングサーバ): live-hoge-push.hogehoge.net
PULL(ストリーミングサーバ→視聴ユーザ): live-hoge-pull.hogehoge.net

設定するとCNAME先が表示されるので、DNSレコードのCNAMEでそれぞれストリーミングサーバに向く様に設定を行っておきます。

■PUSH側設定
PUSH側とPULL側をつなぐアプリケーションネームが必要になりますので下記の通り”Live Streaming Function→Release Point”にてユニークなリリースポイント(アプリケーションネーム)名を記入します。
*PUSH側とPULL側両方同じ値を入れます。

この場合エンコードサーバに設定するストリーム先アドレスは:

RTMP
rtmp://live-hoge-push.hogehoge.net/warplive

になります。

■PULL側設定
次に、PUSH側と同様に配信側であるPULL側にもアプリケーションネームが必要になりますので下記の通り”Live Streaming Function→Release Point”にてPUSH側とPULL側両方同じリリースポイント(アプリケーションネーム)名を記入します。

併せて今回はHLSで配信をおこなうので設定します。

・Slicing interval: 細切れの動画ファイルである.tsファイルの細切れ秒数を指定します。この秒数が短ければ短いほど動画の遅延は短くなります。今回は低遅延を目指しているので1秒で指定した所、現実時間との遅延差は7-8秒になりました。(1-60秒で指定できます)

・TS quantity of the first M3U8: 初回リクエスト時のマニュフェストファイル内に記載される.tsファイルの行数を指定します。これを増大した場合バッファが大きくなり再生開始までの時間が延びる可能性がありますが安定性は増します。(1-3行で指定)

・TS quantity of stable M3U8: 初回リクエスト以降のマニュフェストファイル内に記載される.tsファイルの行数を指定します。(3-20行で指定)

この場合動画として配信する参考ストリームURLは以下になります:(エンコーダでストリーム名をmyStreamとした場合)
http://ドメイン名/アプリケーション名/ストリーム名/playlist.m3u8

HLS
http://live-hoge-pull.hogehoge.net/warplive/myStream/playlist.m3u8

セキュア配信の設定

ここでHTML5 Videoタグで簡単に組み込もうとした際に心配になるのが、一般的に上記で作成したストリームURLがタグの中で丸見えになるという点です。

VideoTagHLS
<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>HTTP Live Streaming Test</title>
  </head>
  <body>
      <h1>HTTP Live Streaming Test</h1>
      <video width="640" 
             height="360" 
             src="http://live-hoge-pull.hogehoge.net/warplive/myStream/playlist.m3u8" 
             preload="none" 
             onclick="this.play()" 
          controls />
  </body>
</html>

気にしない(誰にでも見てほしい)コンテンツであれば特に問題ないのですが、朝礼用で社員専用サイトに埋め込みたい、等の場合では外部流出しないように気を付ける必要が出てきます。

そこでCDNETWORKS社のストリーミングサーバ機能でAnti Leechという使い捨てURLによる視聴制限機能があるらしいのでこれを活用してみたいと思います!

■Anti Leech機能の設定
これはストリームURLの.m3u8wをリクエストする際にmd5化されたハッシュクエリを付与することで、リクエスト認証及び当該ハッシュ付きURLの有効時間を指定できる機能です。

CDNETWORKSポータル側で認証のクエリ名や有効時間クエリ名、ハッシュ化する際のパスKEY等を設定します。ちなみにハッシュ化クエリの生成コードサンプルはCDNETWORKSのサポートに聞いたらくれたので簡単に作成できました。

あとは視聴ページ側でVideoタグ内の箇所に認証クエリを付与してやるだけです。 例えばsrc=の箇所はこんな感じになります:

VideoTagHLS
<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>HTTP Live Streaming Test</title>
  </head>
  <body>
      <h1>HTTP Live Streaming Test</h1>
      <video width="640" 
             height="360" 
             src="http://live-hoge-pull.hogehoge.net/warplive/myStream/playlist.m3u8?wsSecret=ad4c1416545d06971314c0d165e0fe45&wsABSTime=1597803201" 
             preload="none" 
             onclick="this.play()" 
          controls />
  </body>
</html>

もちろんplaylist.m3u8にクエリ付与が無い場合や、指定期限が過ぎたストリームURLはアク禁になり配信されません。
これであれば簡単にVdeoタグで動画組込みが出来て、気兼ねなくストリームURLを堂々と晒せそうです。

HTMLへVideoタグで簡単組込みする

映像再生するには視聴ページとなるHTMLファイルにHTML5 VideoまたはHTML5 Video+JavaScriptの記述が必要になります。

iOSのSafariはHLSに対応していますがMSE未対応のためHTML5 Video+JavaScriptのPlayerを利用することができません。そのため、PC向けはHTML5+JavaScript、スマートフォン向けはHTML5 Videoのみ利用するようにします。

■PC向け(macOS含む)
今回はGitHubで公開されている「hls.js」を利用します。映像ソースとして配信URLを指定する部分が2ヶ所あるのでここに認証クエリ生成付与したストリームURLを渡します。

PCブラウザ向けにはhls.js(GitHub)https://github.com/video-dev/hls.js 
などのHLS再生のためのモジュールが必要になります。これは外部リンクとしてひっぱってくる必要があります。
また、hls.jsはJavaScriptベースのPlayerなのでSame Origin Policyの制限を受けます。視聴ページ配置サーバとストリームURLのドメインが異なる場合、視聴者はストリームサーバからHLSの映像データを取得することができません。CORS設定としてCDNETWORKSストリーミングサーバ側でヘッダにAccess-Control-Allow-Origin: * 記述を入れておくことでHLSの映像データを取得することができますので確認しましょう。

VideoTagHLSforPC
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video height="300" id="video" controls></video>
<script>
if(Hls.isSupported()) {
var video = document.getElementById('video');
var hls = new Hls();
hls.loadSource('.$url.//ここに認証クエリ生成付与したストリームURLを渡します//');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function() {
video.play();
});
}
// hls.js is not supported on platforms that do not have Media Source Extensions (MSE) enabled.
// When the browser has built-in HLS support (check using `canPlayType`), we can provide an HLS manifest (i.e. .m3u8 URL) directly to the video element throught the `src` property.
// This is using the built-in support of the plain video element, without using hls.js.
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = '.$url.//ここに認証クエリ生成付与したストリームURLを渡します//';
video.addEventListener('canplay',function() {
video.play();
});
}
</script>

■Mobile向け(iOS,Android)
一般的なHTML5 Videoの記述です。必要に応じて他の属性を追加しますがこちらはPCブラウザと違い簡単ですねー

VideoTagHLSforMobile
<video src=".$url.//ここに認証クエリ生成付与したストリームURLを渡します//" controls></video>

まとめ

HTML5 Videoタグだと簡単に動画が組み込めるんですが、ストリームURLが晒されるのが今まで気になっていたんですが、これであれば堂々と晒しながら簡単に組込みができました!

しかもHTTPストリーミングはCDNと親和性が高いので配信規模を気にする事無く気軽にストリーミング提供が可能かと思います。