読者です 読者をやめる 読者になる 読者になる

ふっちーのやんのかやんねーのかブログ

ITの技術的なこともそうでないことも。

【Javascript】HTML5 Videoを使った動画プレイヤーの実装方法いろいろ

こんにちは、ふっちーです。

近日のアドテク業界は動画が非常にアツイ感じなので、 スマートフォンにおけるブラウザ/WebViewのHTML5 video(以下video)を使った動画プレイヤー事情を、インライン再生自動再生の観点で検証してみました。

■まとめ

実際どうなのよ、ていうのが知りたいと思うので、まず結果からお伝えしたいと思います。

iOS/WebView、Android/ブラウザ、Android/WebViewはvideoを直接利用するのがよさそう

iOS/Safariはvideoとcanvasを合わせて利用するのがよさそう

・標準的にインライン再生の実装を行い、フルスクリーン再生の実装を独自に行なったほうが共通化できる

Android/ブラウザにおける自動再生が課題

検証を行ったバリエーションと動作状況は以下の通りでした。

◎:インライン再生可+自動再生可
◯:インライン再生可
△:インライン再生不可
×:再生不可

  iOS/Safari iOS/WebView Android/ブラウザ Android/WebView Android/WebView
OSバージョン 8以上 8以上   4.1以下 4.2以上
video
video×canvas ×
jpeg×canvas
ネイティブ - -

参考までに。

■はじめに

今回は、HTML5 videoを使った動画プレイヤーの実装と検証を行った、

HTML5 video

HTML5 video × HTML5 canvas(以下canvas

の2つの手法ついて、ソースコードとそれぞれの再生を実現する方法と問題点についてまとめてみました。

jpeg × HTML5 canvas

は動画のフレーム毎にキャプチャした画像を順番にcanvasに描画するパラパラマンガ的な手法なのですが、こちらについては次の機会にまとめようと思います。

(1. )videoを利用した動画プレイヤー

videoを利用し、動画のインライン再生と自動再生を行う検証です。

この手法はvideoを利用した最もシンプルな方法になるのですが、

iOS/Safariでインライン再生が実現できない

iOS/SafariAndroid/ブラウザで自動再生が実現できない

といった問題点が残りました。

ちなみに、iOS/Safariでインライン再生についてはiOS10になることで解消される予定のようです。

ソースコード

<video id="js-video" preload="none" webkit-playsinline="webkit-playsinline">
    <source src="video.mp4" type="video/mp4">
</video>

<script>
  var elemVideo = document.getElementById('js-video');

  // 再生実行用の関数
  var videoPlay = function () {
    elemVideo.play();
  }
</script>

■インライン再生設定

Android/ブラウザ、Android/WebViewでは標準でインライン再生となるので特に問題なしです。

iOS/WebViewでインライン再生が行えるように、videoタグにwebkit-playsinline属性を設定します。

先述したとおり、残念ながら現状iOS/Safariではvideoを利用したインライン再生は行えず、ビデオプレーヤーによるフルスクリーン再生となります

<video id="js-video" preload="none" webkit-playsinline="webkit-playsinline">

■自動再生設定

iOS/SafariAndroid/ブラウザの場合

iOS/SafariAndroid/ブラウザでは、自動再生は行えません

これは、videoのplay、loadなどのイベントの発火にユーザアクションが必須となっているブラウザ仕様に起因しているためどうしようもなさそうです。

Javascriptでvideoのplayイベントの発火させても再生は開始されずautoplay属性による自動再生ついても同様に行えないようです。

PCブラウザ等では以下のスクリプトで自動再生を開始できます。

<script>
  // windowのonload発火時に再生実行用の関数をコール
  window.addEventListener('load', videoPlay);
</script>

iOS/WebView・Android/WebViewの場合

アプリ内からvideoのplayイベントを発火させることで自動再生を開始することが出来ます。

今回のソースコードで言うと、アプリからvideoPlay()を実行<することで自動再生を実現します。

この際、自動再生を開始するタイミングなどはアプリ側の実装で行うことになります。

(2.)video×canvasを利用した動画プレイヤー

videoとcanvasを利用し、動画のインライン再生と自動再生を行う検証です。

要約すると、videoのcurrentTimeをsetInterval()でカウントアップしていき、都度のフレームをcanvasに描画する仕組みになります。

この手法を取ることで、iOS/Safariでインライン再生を実現できます。

問題点としては、

・音声の再生に対応していない(実際に再生を行っているわけではないので)

Androidの低いバージョンの端末では、canvasへの描画が正しく行えない場合がある

canvasを利用するため端末負荷が高い

といったところです。

音声再生については、HTML5 audioでcurrentTimeの同期をとった音声ファイルを再生することで、擬似的に再現することが出来ます。ジャストアイデアですが。

ソースコード

<video id="js-video" preload="none">
    <source src="video.mp4" type="video/mp4">
</video>

<canvas id="js-canvas"></canvas>

<script>
  var elemVideo = document.getElementById('js-video');
  var elemCanvas = document.getElementById('js-canvas');

  var canvasDrawTimer;
  var lastTime;

  var videoPlay = function () {
    canvasDrawTimer = setInterval(function() {
      // 前回の描画時間都の差分を取り、currentTimeを設定
      var nowTime = Date.now();
      var diffTime = (nowTime - lastTime) / 1000;
      lastTime = nowTime;
      elemVideo.currentTime = elemVideo.currentTime + diffTime;

      // canvasへの描画を実行
      canvasDraw();
    }, 1000 / 24); // 24fpsで描画する
  }

  function canvasDraw() {
    // 動画の縦横サイズ・アスペクト比を取得しcanvasの縦横サイズを変更
    var aspectRatio = elemVideo.videoHeight / elemVideo.videoWidth;
    var canvasWidth = elemCanvas.clientWidth;
    var canvasHeight = Math.floor(canvasWidth * aspectRatio);
    elemCanvas.setAttribute("width", canvasWidth.toString());
    elemCanvas.setAttribute("height", canvasHeight.toString());

    // canvasに描画
    var ctx = elemCanvas.getContext('2d');
    ctx.drawImage(elemVideo, 0, 0, elemVideo.videoWidth,
        elemVideo.videoHeight, 0, 0, canvasWidth, canvasHeight);

    // 総再生時間と現在の再生時間を比較し再生を終了
    var currentTime = (Math.round(parseFloat(elemVideo.currentTime) * 10000) / 10000);
    var duration = (Math.round(parseFloat(elemVideo.duration) * 10000) / 10000);
    if (duration >= 1 && currentTime >= duration) {
      clearInterval(canvasDrawTimer);
    }
  }
}
</script>

■インライン再生設定

こちらの方法では、標準がインライン再生の対応となります。

逆に、フルスクリーン再生を行う際には、フルスクリーンを行う実装を別途行う必要があります

繰り返しになりますが、iOS/Safariでインライン再生を実現できる点においては胸熱です。

■自動再生設定

windowのonload時にvideoPlay()を発火させてあげることで自動再生を実現します。

<script>
  window.addEventListener('load', videoPlay);
</script>

■最後に

ブラウザにおける自動再生については、ユーザーの通信量を意識したブラウザ成約だとかがいろいろ絡んでいるようで、一筋縄には行かないようです。

ただ、現状においても、対象となるブラウザ毎にそれぞれの動作パターンを組み合わせることで、スマートフォン向けの最適な動画プレイヤーが作成できそうな予感はしますね。

プレイヤーだけでなく、プレイヤーに対応した動画素材の作成も大きな課題になりそうですが。。。

今回はこんなところで。