【HLS】ウェブサイトの動画をストリーミング再生する【hls.js】

こんにちは、katori@xxbicottです。
ウェブに掲載する動画が重いときはこれまで動画本体の画質を落として軽量化して対応してきたんですが、解像度の荒さが気になる場合も。

そんな時、HLSを使ったストリーミング配信をすれば動画本体のクオリティを下げずにスムーズに再生できる!という記事を見つけたので、そちらを参考にして試しつつ、調べたこと・使い方を自分用に整理してみました。

今回特に参考にさせていただいた記事はこちらです。
HLSを使って重い動画をWEBサイトに実装する

そもそもストリーミング配信とは

ストリーミング配信 インターネット上のメディア(映像や音楽など)をすぐに再生する技術のこと。ダウンロードの対。
動画ファイルを分割して、順番に読み込みつつ再生する方法とのこと。
HLS
(HTTP Live Streaming )
Appleが定めた動画のストリーミング配信技術。
様々なOS・ブラウザで再生可能で、オンデマンド配信、ライブ配信双方対応。
HTTPストリーミング配信では最も多く利用されているプロトコルで、Abema TVなどでも使われている。

ちなみに、videoタグにmp4等の一般的なメディアファイルを読み込ませる形だと、1つの動画ファイルをダウンロードしながら再生を行うプログレッシブダウンロード方式で再生が行われます。


<video src=”sample.mp4″ controls></video>で再生。
プログレッシブダウンロード方式は一見ストリーミング再生に見えるので「疑似ストリーミング」とも。

基本的な特徴は以下の通り。

  • ストリーミング配信
    →セキュリティが高い(動画のダウンロードもできない)。ライブ配信向き
  • プログレッシブダウンロード
    →一度データのダウンロードが完了してしまえば、シークを移動しても滑らかに再生が可能。オンデマンド配信向き。

また、プログレッシブダウンロードのデメリットとして、容量が大きな動画や通信速度が遅いとキャッシュが溜まるまで動画がスムースに再生できないというものがあるようです。
そこの点を考えると、容量が重いトップの背景動画だったりダウンロードさせたくない動画などを実装するときは、ストリーミング配信が便利そう。

ウェブサイト上でHLSを使って動画を再生する方法

ウェブサイトには以下の3手順で実装できます。

  1. 動画データを分割して必要なファイルを生成
  2. 必要なファイルがそのサーバーで使えるようMIMEタイプ(.m3u8、.ts)を追加
  3. HTMLに読み込みコードを記述

HLSの標準対応ブラウザはSafari、Edge。
今回記載するhls.jsというjsライブラリをいれることで、おおよそのOS・ブラウザで対応できるようになります。
(Windows7のIE11だと、動画再生の仕様が異なり対応不可)

ファイルの生成は、ここではffmpegを用いて行います。

動画データを分割して必要なファイルを生成

まず、mp4等の動画ファイルから、インデックスファイル(.m3u8)とセグメント動画ファイル(.ts)を生成していきます。

試しに、1分ちょうどのサンプル動画(43.9MB)をvideo.mp4として、ファイルを生成するためのコマンドを実行。
(コードは参考サイトのものをそのまま使用させていただきました)

$ ffmpeg -i video.mp4 -c:v copy -c:a copy -f hls -hls_time 9 -hls_playlist_type vod -hls_segment_filename "video%3d.ts" video.m3u8

するとおおよそ9秒(-hls_time指定値)ごとにvideo.mp4が分割され、video.m3u8とvideo000.ts〜video08.tsが生成されました。


ちなみに分割したらトータルで1MB増えました

.m3u8、.tsがサーバーで使えない場合は、MIMEタイプを追加

ロリポップでは不要でしたが、.m3u8、.tsが使えないサーバーの場合はMIMEタイプを追加する必要があります。

.htaccessの場合は以下を追記。

AddType application/x-mpegURL .m3u8
AddType video/MP2T .ts

.m3u8は「AddType application/vnd.apple.mpegurl .m3u8」で行けるという記事も見かけました。

HTMLにコードを記述

ここでのファイル構成は以下の通り。

index.html
video/
– video.m3u8
– video000.ts – video013.ts

index.htmlに動画の読み込みコードを記述します。
SafariとEdgeだけならHLSに標準対応しているので、この1行だけでもHLSを使ったストリーミング再生ができます。

<video src="./video/video.m3u8" controls></video>

他のブラウザも対応するなら以下の通り。

<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="video_smaple" controls></video>

<script>
if(Hls.isSupported()) {
	var video = document.getElementById('video_smaple');
	var hls = new Hls();
	hls.loadSource('./video/video.m3u8');
	hls.attachMedia(video);
}
</script>

これで実装完了!ChromeなどでもHLSでのストリーミング配信ができるようになりました。

ちなみに、再生時のChromeのネットワークパネルはこんな感じになります。


ネットワークは重め

このように、前の.tsファイルの読み込みが完了したら次の.tsファイルの読み込みを開始、と繰り返されていることが分かります。

感想

ffmpegを使えば結構簡単に実装できるので、ダウンロードさせたくない動画を手軽に掲載する手段としてすごく便利だと思いました。

再生処理の所感としては、自分のサーバーで確認する限りプログレッシブダウンロードよりHLSの方が再生開始が少し早め。
あと通信状況が悪い時も安定して再生ができました。これに関してはプログレッシブダウンロード方式の方が安定するはずでは?という疑問が残るので、今後実践で色々試していきたいところ。
動画自体の軽量化と合わせて使っていこうと思います。

理解がまだ浅いため、誤っている内容があればご指摘いただければ幸いです!

参考