HTTP Live Streaming (HLS)実装ログ1

HTTP Live Streaming (HLS)実装ログ1

デジタル図書館の開発の際に起きた問題と解決を覚書 (または検索で辿り着いた迷えるエンジニアさん向けの内容です。)記事はMacユーザー向けです。

記事の流れ

HTTPLiveStreamingToolsのインストール

FFMPEGのインストール

tsとm3u8の作成

マスターm3u8の作成

FTPにアップロード

 

なぜHLSが必要になったか

この図書館で動画を配信しようとしたところ、数十MB以上ある動画の再生遅延が発生しました。

そこでストリーミングができるサーバーを探してみても、どこもとても高額(ひと月で数10万円〜♾️)なため、Appleが開発したストリーミングプロトコル (HTTP Live Streaming)を使用することで、一般的な静的サーバーでもストリーミング動画再生ができることが分かりテストを兼ねて実装したみた記録です。

自分用が主ですので、見返して分かりやすく記録することにしました。実装でお困りの方の参考にもなれば幸いです。

 

ストリーミング形式とは

tsとm3u8の図解

ストリーミング形式とは、MP4を素材に、細かい秒数の動画(.ts)に分割をして、ひとつひとつのファイルサイズを小さくしたものを.m3u8という設計図で繋げる技術です。上図をご参照ください。

.tsというバラバラの動画があるとします。このバラバラの動画の途中をユーザーさんがクリックすれば、そのクリックした動画のローディングが優先されて再生されるわけです。さらに素晴らしいことは、通常、MP4をWebサイトにアップロードした場合、MP4ファイルが持っている容量をすべてキャッシュに保存されてしまいますが、ストリーミングでキャッシュを使用しないために、エンドユーザーさんのデバイスに負担がかかりません。

つまりストリーミング形式でない動画を見た場合、ユーザーさんが、ブラウザのキャッシュを自分でクリアする知識がなければ、どんどんとデータが貯まりスマホが重くなったりする訳です。

ストリーミング形式は2つあります

[アダプティブ / VOD] 

ラーニングやオンデマンド配信などで、事前にアップロードしておいた動画をほぼ遅延なく見れる方式です。この図書館はこの配信となります。

[ライブ /EVENT] 

リアルタイムでユーザーさんが再生ができる方式です。

どちらもHTTP Live Streaming(以下HLS)で作れますが、今回はアダプティブについての記事となります。

HLSツールはApple Developer Program(年間:99ドル)に加入している方だけがダウンロードできるプロトコルです。

iOSやMacのアプリの開発をしている方でしたらおまけで付いてくるわけですが、そうでない方は1年間だけプログラムに加入するか「MPEG-DASH」という別のプロトコルを使う必要があります。ちなみに、MPEG-DASHはiOSでの再生に対応していないようなので注意が必要です。

 

[HLSツールとは]

MP4を.tsファイルという数秒単位に細かく刻んだ動画と、その動画の繋げる順番を記述した設計図.m3u8を作れるプロトコルです。(アップルの推奨秒数は.tsあたり10秒です。)

ダウンロードはこちらから

https://developer.apple.com/streaming/

サイト内の”View downloads”をクリックすると下記の選択が表示されます。今回はMacでの開発作業ですのでmacOSをクリックしてダウンロードします。

以下のソフトウェアが含まれています。

・Media File Segmenter
・Media Subtitle Segmenter
・Media Stream Segmenter
・Variant Playlist Creator
・Media Stream Validator
・HLS Report
・ID3 Tag Generator
・TS Recompressor

通常のソフトやアプリは、クリックできるアイコンがありますが、このプロトコルは目に見えるアイコンがありません。ではどうやって使うかと言いますと”ターミナル”で作業します。

ターミナルは、”システムの”アプリケーションフォルダの下の方にある、”ユーティリティ”フォルダの中にあります。(ユーザー>アプリケーションではなく、PhotoShopとかが入ってる方のフォルダです。)

まずは、HTTPLiveStreamingTools-〇〇.dmgをダウンロードしてみてください。

するとXcodeにインストールするので、Xcodeのダウンロードも催促されると思いまます。

Xcodeがまだ入っていない場合、Xcodeは容量が大きいのでダウンロードに時間がかかる場合があります。完了したらターミナルを起動します。

ターミナルを起動

[はじめに]

ターミナルの命令文は2種類あります。bachとzshです。

bachは昔ながらのものらしく、今回はzshを使って作業を進めます。

ターミナルを起動した時にテキストボックスの上部にbachと書かれていた場合は、zshに変えます。zshはターミナル内ではxshrcで会話します。bachに慣れている方は、この記事の内容のzshをbachに読み替えて進めてください。どちらが良いとか悪いとかは無いようです。

[命令文の変え方]

ターミナルを起動>シェル>新規ウィンドウ

ターミナルに下記を記述

chsh -s /bin/zsh

成功したらターミナルを閉じて、再度、新規ウィンドウを開くとテキストボックスの上部に”フォルダマーク ユーザー名 ー-zshー80×24”が表示されます。ここまでできたら次のステップに進みます。ffmpegというツールをインストールする作業です。

 

FFMPEG

ややこしいのですが、HLSを作るためには、ffmpegという実際に”動画や音声”を変換するためのコマンドラインツールも必要になります。

※このffmpegは無料でダウンロードできます。

ダウンロード

https://ffmpeg.org/download.html#build-mac

アップルマークにカーソルを乗せると、下に”macOS” “Static builds for macOS 64-bit”というリンクが表示されるので、一番上の新しいものをダウンロードします。ダウンロードしたら、そのファイルをダブルクリックするとインストールされます。

黒いアイコンが表示されてインストールが完了したら、お好みの場所に置きます。

ちなみにこの記事では、システムのアプリケーションフォルダにインストールしています。完了したらターミナルを起動してパスを通します。

ffmpeg-のダウンロードサイト

PATHを通す

[パスを通すとは]

パスを通すとは、インストールしたソフトウェアやプロトコルの場所をコンピューターに教えてあげる作業です。

[パスを通す]

ffmpegの場所を指定します。(以下はMac>ユーザーのアプリケーションフォルダにffmpegをインストールした場合)

ターミナルに次のコマンドを記述します。

echo 'export PATH=$PATH:/Applications' >> ~/.zshrc

パスが通ったかの確認方法は下記のコマンドを入力すると..

echo $PATH

下のようなコマンドが表示されれば成功です。

Username@MacBook-Pro ~ % echo $PATH
/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/ImageMagick/bin:/Applications:/Applications

今回はユーザーのアプリケーションにパスを通しました。最後の部分に今回、通した”Applications:/Applications”パスが表示されています。

FFMPEGもインストールされたMacでtsとm3u8の作りかた

ファイルの見た目

m3u8-tsの図解

ファイルの構造

ffmpeg -i /Users/〇〇/Applications/v.mp4 -bsf:v h264_mp4toannexb -c copy -f segment -segment_format mpegs -hls_time 10 -segment_list video.m3u8 segment_%04d.ts

例えば、上記のコマンドをターミナルに記述すると.ts と.m3u8が自動的に書き出せます。ただしこれは、書き出しの基本形で、最高画質でのみ書き出せれてしまいます。

つまり低速環境では、このようなHLS化されたプロトコルでも、遅延が発生しますから、低くする調整が必要です。今回のmp4の名称はvにしてありますので、適宜変更します。(v.mp4)

[オプションの解説]

このコマンドに何が書かれているかは下記の通りです。

-c:v
-cオプションはエンコーダーの指定で、コーデックを指定します(入力元ファイルの前で使うとデコーダーの指定になる)。
-c:vはビデオのエンコードを意味します。
入力・出力ともmp4でコーデックを変換する必要はないので、その場合、copyを指定すると再エンコードを実施せずに済み、処理を無駄に増やしません。

-c:a
オーディオのコーデック指定です。
上と同様、copyで大丈夫です。

-f
出力ファイルのフォーマットを指定します。
hlsを指定します。

-his_time
ファイル分割の際の長さを秒単位で指定します。
省略した場合、2秒がデフォルト値になります。

-hls_playlist_type
EVENTまたはVODを指定します。
ライブ配信の場合はEVENT、オンデマンドならVODを指定するようです。
(※ライブ配信の場合、サーバー側でプレイリストファイルの行追加が行われるので、その場合はEVENTを指定する)
今回は、VODで問題ありません。

-hls_segment_filename
分割するファイル(.ts)の名称を指定します。
%03dは、3桁の連番が入ることを意味します。

動画の遅延を無くしたい場合は、下のコマンドを入力します。

例として、ビットレートを小さい順に4つ用意しました。これはそれぞれ別の.m3u8ファイルになります。

下記の1Mbpsは、ビットレードが小さく画質が荒くボヤけますが必ず作るようにしましょう。理由は回線速度は6Mbpsあったとして、1Mbpsが採用されることが多いためです。

おそらくは、数個の.tsファイルの合計が何Mbpsかで判断している様子があるためです。

//1Mbpsの動画を生成(遅いデバイス環境向け)
ffmpeg -i /Users/〇〇/Applications/v.mp4 -b:v 1M -c:a copy -f hls -hls_playlist_type vod -hls_time 5 -g 24 -hls_segment_filename "v-1m%3d.ts" v-1.m3u8
//5Mbpsの動画を生成(まあまあのデバイス環境向け)
ffmpeg -i /Users/〇〇/Applications/v.mp4 -b:v 5M -c:a copy -f hls -hls_playlist_type vod -hls_time 5 -g 24 -hls_segment_filename "v-5m%3d.ts" v-5.m3u8
//10Mbpsの動画を生成(早いデバイス環境向け)
ffmpeg -i /Users/〇〇/Applications/v.mp4 -b:v 10M -c:a copy -f hls -hls_playlist_type vod -hls_time 5 -g 24 -hls_segment_filename "v-10m%3d.ts" v-10.m3u8
//20Mbpsの動画を生成(すごい早いデバイス環境向け)
ffmpeg -i /Users/〇〇/Applications/v.mp4 -b:v 20M -c:a copy -f hls -hls_playlist_type vod -hls_time 5 -g 24 -hls_segment_filename "v-20m%3d.ts" v-20.m3u8 

上記は太字の部分が違いです。〇〇の部分をあなたのPCのユーザー名に変えます。(ログインユーザー名ではなく、”Mac>ユーザ>〇〇“の名称です。)これをそれぞれ別にターミナルに記述します。例えば1Mbps用の動画は'”1m”というファイルを作って入れます。

他にも”5m”、“10m”、“20m”と合計4つのフォルダを作って書き出しましょう。

この4つのフォルダにはそれぞれ.tsファイルが複数と”m3u8″ファイルが1つ書き出されているはずですので、対象のMbpsのフォルダに入れてください。

それぞれのフォルダに.ts(複数ファイル)と.m3u8ファイルが入っていますね。(要確認)

次に、“1m”、5m、“10m”、“20m”ファイルのうち、どのファイルをブラウザで表示するか、指定する必要があります。そこで、それぞれのm3u8ファイルがどこにあるのかが書かれたマスター.m3u8ファイル(親のm3u8)を作ることで、ユーザーさんの回線速度に合わせた子のm3u8ファイルを自動で選んでくれるようになります。

 FTPソフトに移動して、これらのファイルをindex.htmlより下の階層、またはwordpressの場合は、wp-contents/uploads/より下の階層に、下図のように、動画を格納する新しいフォルダを作り、そこにアップロードします。(フォルダ名は英数字であれば何でも大丈夫です。)ここでは”hls-movie”としました。

次に”hls-movie”の中に“master.m3u8″のテキストページを作成し下記の記述します。

m3u8-tsの図解

master.m3u8のテキストの内容は下記のとおりです。「1Mbps用のm3u8ファイルは、1Mbpsフォルダの中にありますよ」とmaster.m3u8に記述しています。ちなみにローカルでは、”.”が先頭に付くファイルはデスクトップでは作れませんので、FTP上で行います。ターミナルも使えませんので、手書きで書きます。PATHをユーザー>アプリケーションにした方以外は、適時パスを修正してください。

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1000000
1m/v-1.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=5000000
5m/v-5.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=10000000
10m/v-10.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=20000000
20m/v-20.m3u8

ファイルの記述に間違いがなければ “master.m3u8″に“1m”、5m、“10m”、“20m”の4つの子にあたるm3u8が紐付きました。

上の表のうち、”BANDWIDTH=〇〇”はビットレートを表しています。例えば1Mbpsの場合、Kbpsで換算しますとKは1,000ですので「1Mbpsは1秒間に1000,000ビット(bit)のデータ量」という記述になります。

また上から2行目の”1m/v-1.m3u8‘の部分の/の後ろは子にあたるm3u8ファイルの名称をそのまま記述します。(ここを間違うと再生できません。)

これで“master.m3u8″をhtmlで指定すれば、ユーザーさんのwifi環境に合わせた動画が配信される準備ができました。

具体的には転送速度1Mbps以下のユーザーさんのデバイスには、“1Mbps”を表示してね。と指令を出しています。当然1Mbpsでは画質は落ちます。

youtubeなどでよく体験する回線の環境が悪いと画質が下がるけど、動画が途切れたり遅延したりしにくい動画ってありますね、これがストリーミング再生です。普通のMP4をアップロードしただけの場合は、動画が固まったりしますが、それを軽減してくれます。

デメリットとしましては、単純にMP4でアップロードするよりも、これだけたくさんのビットレートファイルをサーバーに上げている訳ですから、サーバーのSSDスペースが、元のMP4より、1.5倍くらい多く必要になります。

ビットレートを30Mbpsなどにした大きなファイルは元のファイルよりも大きくなりますので、注意が必要です。

この点はみなさん側で、どのビットレートを指定するか決めていただく必要があります。

これでiOSやSafariでストリーミング再生ができるようになりました。

では早速見てみましょう。

 

HLSストリーミング再生を実装している動画(スムーズな再生)

WordPressで再生する場合は、プレイヤーをHLSに対応させます。

何もせずにMP4を設置した動画(遅延する・飛ばし見がしづらい)

如何でしょうか。HLSはローディングが済んでいない再生箇所をクリックしても、ここからに変更ですね、と対応してくれます。対してMP4の方は低速の接続環境の場合、ローディングが追いつくのを待つ必要があり、ストレスが溜まり、離サイト率が高まります

高速回線でご覧の方は、低速の環境に変えてご覧頂くと顕著に違いが現れます。ベースは同じ1080×1960pxのファイルです。

これがHLSです。年間100万円以上の高いストリーミングレンタルサーバーも借りずに済むすぐれものです。

 次回はChromeでHLS動画が表示されない問題、[CORSエラー]の対策についてと、サーバー選びについて解説する予定です。