本記事では、FFmpegを使用して動画をHLS(HTTP Live Streaming)形式に変換し、video.jsで再生する方法を記載します。
HLSとは?
AppleによってiOSとSafari向けに開発された、HTTPベースの動画ストリーミングプロトコルです。
単一ファイルで容量が大きかった動画ファイルを小さなセグメント(.tsファイル)に分割して、配信がしやすい形式にしたものになります。
上記に加え、HLSに変換する際に複数のビットレートに変換することで、視聴者の環境に応じて画質を変化させて最適な視聴をさせることができるのが特徴です。
※今回の記事では単一ビットレートでの例を説明します。
他にもDASHやSmoothStreamingなどもありますが、Webの動画配信では、HLSが業界のデファクトスタンダードとなっています。
利用する動画
定番のBBB(Big Buck Bunny)を利用します。
- 利用ファイル:bbb_sunflower_1080p_60fps_normal.mp4
- ダウンロードサイト
※355.9MB程あります。
FFMPEGのインストール
brew install ffmpeg
- 参考ページ
https://formulae.brew.sh/formula/ffmpeg#default
容量が大きいので、時間がかかります。
- バージョン確認コマンド
ffmpeg -version
# 出力例: ffmpeg version 7.1 Copyright (c) 2000-2024 the FFmpeg developers
HLSに変換
コマンド前にTips!
ファイルを変換するときは、コーデックを確認することが大事です。
以下のコマンドでHLS(m3u8とts)を作成することはできますが、音声が再生されません。
ffmpeg -i bbb_sunflower_1080p_60fps_normal.mp4 \
-c:v copy \
-c:a copy \
-f hls \
-hls_time 9 \
-hls_playlist_type vod \
-hls_segment_filename "bbb_sunflower_1080p_60fps_normal%3d.ts" \
bbb_sunflower_1080p_60fps_normal.m3u8
理由としては、コーデックがAC-3(Dolby Digital)となっており、これだとブラウザでの再生ができないためです。
- 参考issue
https://github.com/videojs/video.js/issues/7206
以下のコマンドを叩くことで、コーデックが確認できます。
ffprobe -v quiet -show_streams -select_streams a bbb_sunflower_1080p_60fps_normal.mp4
出力結果内の[STREAM]index=2に、codec_name=ac3
の記載があります。
これへの対応として、AACに変換する必要があります。
利用するコマンド
以下のコマンドを実行することにより、コーデックがAACでVOD用のHLSファイルを生成することができます。
生成されるファイル数が多いので、outputというディレクトリを作成して格納するようにします。
※71ファイルほど生成されます。
mkdir -p output && ffmpeg -i bbb_sunflower_1080p_60fps_normal.mp4 \
-c:v copy \
-c:a aac \
-b:a 192k \
-ac 2 \
-f hls \
-hls_time 9 \
-hls_playlist_type vod \
-hls_segment_filename "output/bbb_sunflower_1080p_60fps_normal%03d.ts" \
output/bbb_sunflower_1080p_60fps_normal.m3u8
各オプションの説明
-c:v copy
→映像コーデックはそのまま使用
-c:a aac
→音声コーデックをAACに変換
-b:a 192k
→音声ビットレート指定
-ac 2
→ステレオ音声(2チャンネル)
-f hls
→出力フォーマットをHLSに指定
-hls_time 9
→セグメントの長さを設定(VODなので品質とバッファリングのバランスがよい9秒にしています。)
-hls_playlist_type vod
→ビデオオンデマンド用の設定で、完全なプレイリストを生成
-hls_segment_filenameの%03d
→001から始まる3桁の連番でセグメントファイルを生成(こうしないと生成と再生の順序がズレる)
再生用のHTML
video.jsはCDN経由で参照します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HLS Player - Video.js</title>
<!-- Video.js -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/8.10.0/video-js.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/8.10.0/video.min.js"></script>
<style>
.video-container {
max-width: 1000px;
margin: 30px auto;
}
.video-js {
width: 100%;
height: 0;
/* 16:9のアスペクト比 */
padding-top: 56.25%;
}
</style>
</head>
<body>
<div class="video-container">
<video id="my-video" class="video-js vjs-default-skin vjs-big-play-button vjs-fluid" controls preload="auto"
data-setup='{"fluid": true}'>
<source src="output/bbb_sunflower_1080p_60fps_normal.m3u8" type="application/x-mpegURL">
</video>
</div>
</body>
</html>
確認画像
上記のコードをローカルサーバーで動かし開発者ツールのネットワークタブを見ると、動画の再生中はtsファイルをダウンロードし再生していることがわかります。

またまたTips!
videojs8を利用していますので、デフォルトでHLSを再生できます。
6までは再生用のプラグインを入れる必要がありましたが、今はコミコミになりました。
- 参考ドキュメント
https://videojs.github.io/videojs-contrib-hls/
最後に
FFmpegを触ったことがなかったので、やっていて結構勉強になりました。
動画は扱う要素が多いので、学ぶ事項が多いですね。
以上、どなたかのお役に立てば幸いです。