mp4を変換してhlsストリーミング再生を実装してみる
目次
Web ページに動画を埋め込む際、YouTube などを使わず、ストリーミング再生を実装したい場合に色々調べて実装することができたので、メモします。
こんな方向け
- 動画の形式のことはよくわからない
- とりあえずストリーミングを実装したい
- mp4 ファイルだけはある
- YouTube などは利用しない(自サーバーに動画を UP する)
動画変換の話
ストリーミング再生対応形式について
- MPEG-dash
- 主に windows 系が対応している
- hls
- 主に apple 系が対応している
の2種類が主流の模様ようで、ブラウザではなく、OSレベルの話で対応が変わるので注意。
https://lealog.hateblo.jp/entry/2016/12/21/112805
2 つの形式に変換するのは面倒
それぞれのデバイス用に動画ファイルの作成と js での振り分けをすると面倒なので、何か便利なものはないのかと検索すると、hls.jsというものがヒットします。
https://github.com/video-dev/hls.js/
hls 非対応のブラウザを対応させる JS ライブラリで、対応しているブラウザは、そのまま hls を利用する。
if (Hls.isSupported()) {
var video = document.getElementById('video');
var hls = new Hls();
hls.loadSource('https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function () {
video.play();
});
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8';
video.addEventListener('canplay', function () {
video.play();
});
}
mp4 ファイルを ffmpeg を使って hls 形式に変換
素の mp4 ではできないため、FFmpeg というソフトを使い、hls 形式(m3u8 ファイルと ts ファイル)に変換します。
諸々試したところ、以下を参考にコマンドを入れるとうまく動作する模様。
https://engineer-world.duckdns.org/2018/03/07/post-1423/
セグメント(ts ファイル)の長さは 10 秒が推奨とのことです。
コマンドは以下の通りです。
ffmpeg -i [input file path] .mp4 -codec copy -map 0 -f segment -vbsf h264_mp4toannexb -segment_format mpegts -segment_time 10 -segment_list [output file path] .m3u8 [output file name] -%03d.ts
実際入力する際は、以下のような感じです。
ffmpeg -i video\video.mp4 -codec copy -map 0 -f segment -vbsf h264_mp4toannexb -segment_format mpegts -segment_time 10 -segment_list video\video.m3u8 video\video-%03d.ts
以下のようなファイルが出力されれば成功です。
video
├video.m3u8
├video-000.ts
├video-001.ts
├video-002.ts
├video-003.ts
├video-004.ts
├video-005.ts
├video.mp4(最初から入っているファイルです。)
実装
諸々イベントがあると便利なので、デフォルトの video は利用せずplyr.jsを利用する。
実装コード
コード全体は以下のような感じです。
<!DOCTYPE html>
<html lang="ja">
<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>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/plyr/3.4.3/plyr.css"
/>
<style>
.video-content {
width: 1000px;
margin: 20px auto;
}
.video-content video {
width: 100%;
}
</style>
</head>
<body>
<div class="video-content">
<video
id="player"
playsinline="playsinline"
poster="./images/poster.jpg"
></video>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hls.js/0.10.1/hls.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/plyr/3.4.3/plyr.min.js"></script>
<script>
const video = document.querySelector('#player');
const videoSrc = './video/video.m3u8';
const hlsCheck = Hls.isSupported();
const player = new Plyr(video);
if (hlsCheck) {
var hls = new Hls();
hls.loadSource(videoSrc);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function () {});
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = videoSrc;
video.addEventListener('loadedmetadata', function () {});
}
</script>
</body>
</html>
まとめ
- youtube や vimeo など、利用しなくともストリーミング配信は可能。
- ffmpeg のコマンドは難しい。
- hls.js の存在はありがたい。
- plyr.js はイベント取得が容易
参考サイト
以下サイトを参考にさせていただきました。
- https://qiita.com/niusounds/items/6e81e79f722df16fb895
- http://backham.me/blog/2016/11/04/hls%E3%82%92%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E9%96%A2%E4%BF%82%E3%81%AA%E3%81%8F%E4%B8%80%E7%99%BA%E5%86%8D%E7%94%9F%E3%81%99%E3%82%8B-hls-js/
- https://engineer-world.duckdns.org/2018/03/07/post-1423/
- http://technical.live-on.net/archives/4295
- http://nico-lab.net/hls_muxer_with_ffmpeg/
- https://github.com/dailymotion/hls.js
- https://github.com/sampotts/plyr#options