コフス技術ブログ

FV動画をHLS形式で実装した時の備忘録

この記事はにメンテナンスが行われています。

ファーストビューに設置するメインビジュアル動画(FV動画)の実装の際に、HTTP Live Streaming(HLS形式)で再生をした時の備忘録です。

以下の様な実装における制限がある場合で単純に動画ファイルの圧縮率の調整だけでは解消しづらい時、初期セグメントのサイズ調整が可能でページ読み込み速度を抑えられるHLS形式でライブストリーミング再生させると色々と丸く収まる場合があります。

  • 再生動画の長さが割と長くファイルサイズが大きい
  • ある程度の解像度が求められる
  • 動画実装前と同等のFCPスコア維持が必要
  • ページ読み込み速度も犠牲に出来ない

動画の変換

HLS形式でライブストリーミングをするためには.m3u8形式への変換が必要です。
ffmpegを用いて変換を行います。

ffmpeg -i input.mp4 -c:v copy -f hls -hls_init_time 0.5 -hls_time 2 -hls_playlist_type vod -hls_segment_filename "output%3d.ts" output.m3u8

指定している各オプションは以下の意味を持ちます。

  • -i input.mp4:元のファイル。
  • -c:v copy:コーデックの指定。copyとすると元のファイルと同じコーデックになります。
  • -f hls:フォーマットの指定。
  • -hls_init_time 0.5:分割する際の初期セグメントの間隔(秒)指定。
  • -hls_time 2:分割する際の間隔(秒)指定。
  • -hls_playlist_type vod:hlsのタイプ指定。
  • -hls_segment_filename "output%3d.ts":各セグメントのファイル名指定。

hls_init_timehls_timeより小さくすると初期セグメントのファイルサイズを大きく下げる事ができます。ページ読み込み速度を落とせない時や、FCPスコアの維持に少しだけ期待ができそうです。

実装

HTMLはsrc属性無しのvideoタグを設置します。

index.html
<video id="video" preload="metadata" muted playsinline loop></video>

MIMEタイプ追加

サーバーの設定で.m3u8.tsファイルが使えない場合はMIMEタイプの追加を行います。

Apacheの場合の例

AddType application/vnd.apple.mpegurl .m3u8
AddType video/mp2t .ts

nginxの場合の例

types {
  application/vnd.apple.mpegurl m3u8;
  video/mp2t ts;
}

hls.jsのインストール

Apple系のブラウザ(Safari / iOS Safari / iPadOS Safari)と旧Edge(EdgeHTML版)では標準でHLS形式の再生が可能ですが、未対応のブラウザも多いです。
その為モダンブラウザ(IE11含む)で再生できるようhls.jsをインストールします。

yarn add hls.js

JavaScriptの実装例

Basicな実装が以下です。

main.js
import Hls from 'hls.js'

const video = document.querySelector("#video");
const videoSrc = 'sample.m3u8';

const play = () => {
  video.play();
};

if (Hls.isSupported()) {
  const hls = new Hls();
  hls.loadSource(videoSrc);
  hls.attachMedia(video);

  video.addEventListener("canplaythrough", play);
  video.load();
} else if (video.canPlayType("application/vnd.apple.mpegurl")) {
  video.src = videoSrc;

  video.addEventListener("canplaythrough", play);
  video.load();
}

大まかな実装としては、Hls.isSupported()MediaSource Extensionsへのサポートを判定し、サポートしている場合はnew Hls()を実行しhls.jsでHLS再生を可能にします。
未サポートの場合はcanPlayTypeを用い、デフォルトでHLS再生が可能か判定します。デフォルト再生ができる場合は単純にsrcにurlをセットします。主にiOS Safariの場合で機能します。

MediaSource Extensionsに未対応且つ、canPlayTypeでデフォルトHLS再生ができない環境では動画再生ができないということになりますが、モダンブラウザではその様な事はないので無視できそうです。

参考:Can I Use MediaSource Extensions

プログレッシブダウンロードとライブストリーミングの特徴

プログレッシブダウンロードの特徴

MP4などの単一動画ファイルを読み込むタイプ。

  • ファイル全体のデータをダウンロードしながら再生を行う(疑似ストリーミングとも呼ばれる)
  • ある特定の地点から再生を行う場合、その地点までデータのダウンロードが済んでいる必要がある
  • データを連続的にダウンロードする動作をするため、通信速度が遅い場合ページ全体の表示速度に影響しやすい
  • 一度ダウンロードしたデータはキャッシュとして持つため、高速なシークや再生が可能

ライブストリーミングの特徴

HLSなどのストリーミング配信のタイプ。
※ HLSはライブストリーミングプロトコルの1つです。RTMPやMPEG-DASHなど複数のプロトコルが存在します。

  • 動画を全体ではなく分割して配信されたものを再生
  • 分割されているためある特定の地点から再生を行う場合、その地点からのデータのダウンロードだけで再生が可能
  • 分割の割合を操作できるため、初期セグメント(一番最初のデータ)のサイズを小さくするなどの操作でページ読み込み速度の影響具合を調整できる
  • マルチビットレート配信が可能

FV動画をHLS形式で実装して得られたメリット

上記特徴でもあるように、ライブストリーミングでは初期セグメントのサイズ調整ができるため、ページ読み込み速度の維持とFCPスコアの維持がある程度できたのは大きなメリットだと思いました。

またライブストリーミングであるため、回線速度が遅い場合は動画が止まるだけで全体のページ読み込み速度に大きな影響が出づらいのもページ体験に貢献できたと思います。関連してプログレッシブダウンロードでは厳しい高解像度動画も配信しやすい点もメリットと言えそうです。

メリットはありますがFV動画自体がライブストリーミングである必要性はない為、HLS形式で実装が求められる場面は少ないように感じました。
たとえば冒頭の以下の様な要件がある場合でも、スプラッシュを入れてダウンロード時間を稼ぐ事が要件に追加できればプログレッシブダウンロードで問題ない場面も往々に考えられます。

  • 再生動画の長さが割と長くファイルサイズが大きい
  • ある程度の解像度が求められる
  • 動画実装前と同等のFCPスコア維持が必要
  • ページ読み込み速度も犠牲に出来ない

勿論ファイルサイズによってはダウンロード時間を稼ぐのが現実的な時間内に収まらない事もあります。モバイル回線でお昼時を想定しているなら永遠にスプラッシュ画面から抜けられない事も容易に考えられるでしょう。

必ずしも必要性はないものの、実際にFV動画をライブストリーミングで実装してみて思ったこととしては状況・要件によっては選択肢に追加してみるのも1つの手ではありそうです。幸いhls.jsを用いればすべてのモダンブラウザで対応できるので実装ボリュームは限定的です。