hls.jsを使ってストリーミング再生を試みます。
mp4からHLSに変換するところは前回の記事をご覧ください。
この記事ではHLS形式の動画をブラウザからhls.jsを使って再生する部分を書きます。
条件
・AWS S3のバケット上にhls形式の動画がある。
・ブラウザはChromeを使用。
・ビデオを再生するフロント部分はfirebaseでデプロイ。
さっそく
hls.jsのread.meに書いてある通りなのですが(本当にすっごく親切に書いてあります)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
</head>
<body>
<video id="video" style="display: none;"></video>
<button id="button">play video</button>
<script>
if (Hls.isSupported()) {
let video = document.getElementById('video');
let hls = new Hls();
// bind them together
hls.attachMedia(video);
hls.on(Hls.Events.MEDIA_ATTACHED, function () {
console.log("video and hls.js are now bound together !");
hls.loadSource("動画が保存されているS3バケット/hls_sample/hls_400k_.m3u8");
hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
console.log(data)
console.log("manifest loaded, found " + data.levels.length + " quality level");
let fragments = data.levels[0].details.fragments
let play_time = 0
for(let i in fragments) {
console.log(fragments[i]);
play_time += fragments[i].duration
}
console.log("play_time : ",play_time)
play_time = Math.floor((play_time*1000)+1000)
console.log(play_time)
button.addEventListener('click', function() {
video.style.display="block"
video.muted = false;
video.play();
setTimeout(function(){console.log("end")}, play_time);
});
})
})
}
</script>
</body>
</html>
こんな感じです。
これをfirebaseにあげました。
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
今回はcdnでhls.jsを読み込みました。
<video id="video" style="display: none;"></video>
<button id="button">play video</button>
videoタグで動画を再生する場所を確保し、
ボタンが押されたら動画を再生するようにしました。
(理由は後述します)
hls.loadSource("動画が保存されているS3バケット/hls_sample/hls_400k_.m3u8");
ここでHLSのプレイリストファイル(.m3u8)を読み込み、
button.addEventListener('click', function() {
video.style.display="block"
video.muted = false;
video.play();
setTimeout(function(){console.log("end")}, play_time);
});
ボタンが押された時にvideo.play()で再生しています。
play_timeの時間でタイムアウトを設定しているのは、ちょっと事情があって、動画の再生が終了したことを知りたかったからです・・・
はまったところ
Chromeブラウザでautoplayができない・・・?
はじめ、動画は再生されるのに音声が全く再生されず、なんでや・・・?と悩みました。
調べてみたところ、Chromeのバージョン66以上では、音声付き動画について、videoタグのautoplay属性が無効になるとのこと・・・
確かに、video.mutedをtrueにして、videoタグにautoplayを指定していると、音声なしで再生されます。
FirefoxやIEではこのような問題は起こっていないようなので、Chromeブラウザを使う場合は注意が必要です。
今回はページを読み込んだタイミングでビデオを再生するのではなく、任意のタイミング(ボタンを押した時)に再生したかったので、ボタンを押したタイミングで再生されるようにしました。
CORSで引っかかる・・・?
(もはやHLSの話ではないので手短に・・・)
S3とfirebaseの両方でCORSの設定が必要でした。
当たり前すぎてこんなことに躓いた自分が恥ずかしい・・・
S3のCORSの設定
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
AllowedOriginはワイルドカード(*)ではなく、許可したいものだけ(今回の場合はfirebaseのエンドポイント)にすると良いと思います・・・
firebaseは
"headers": [ {
"source" : "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
"headers" : [ {
"key" : "Access-Control-Allow-Origin",
"value" : "*"
} ]
}],
これを追記します。
headerにCORSの設定を追加します。
感想
hls.jsは本当に分かりやすくて使い勝手がいいと思いました。
ドキュメントがとても丁寧
Chromeでautoplayが使えないのは知らなかったので、勉強になりました・・・