(2016/7/25): 最近のChromeやSafariでのアップデート関連を新しい記事にまとめてみました。
モバイルブラウザでは、<video>
タグを使ってビデオの再生を行うとき、ユーザに無断でダウンロードを開始して通信料金が過剰にかからないようにするために、preload
属性を指定しても無効になるようになっています。
ですが、ユーザが再生を開始するためにボタンをクリックしてからバッファリングを開始するのではなく、先にダウンロードを始めておいて、ユーザが操作するときにはダウンロードが完了していて、ボタンをタップすれば即座に再生が開始される、といった動作を実現させたい場合もあるのではないでしょうか。
そこで、第一歩目として、HTML5のアプリケーションキャッシュが本当に<video>
タグで上手く活用できないのか、iOSとAndroidで検証してみたいと思います。
とりあえず、やってみた
<!DOCTYPE html>
<html manifest="cache.manifest">
<head>
...
(中略)
...
</head>
<body>
<video controls>
<source src="video.mp4">
<source src="video.webm">
</video>
</body>
</html>
CACHE MANIFEST
# version 0.1
sample.html
video.mp4
video.webm
単純に、このような感じでマニフェストを用意して、iOSのSafariやAndroidの標準ブラウザ、Chrome、Firefoxで再生してみると...、<video>
タグはキャッシュを完全に無視して、最初からバッファリングを開始して再生しようとしてしまいます。
本当にキャッシュされないのか?
実は、マニフェストが無視されるわけではなく、キャッシュ自体は機能しているようで、ブラウザには読み込まれるにもかかわらず、<video>
タグは無視して自らコンテンツをダウンロードしようとする、ということのようです。
少し細工してみた
それならば、HTML上では<video>
タグの再生ファイルの場所を明示せず、キャッシュが完了してからJavaScriptでファイルの場所を与えてやるとどうなるか、確かめてみます。
<!DOCTYPE html>
<html manifest="cache.manifest">
<head>
...
(中略)
...
<script src="cache.js"></script>
</head>
<body>
<video id="video" controls></video>
</body>
</html>
function setVideo() {
var v = document.getElementById('video');
v.src =
(v.canPlayType('video/mp4; codecs="avc1.640029,mp4a.40.2"') == 'probably') ?
'video.mp4' : 'video.webm';
}
function update() {
var c = window.applicationCache;
if(c == c.UPDATEREADY) {
c.swapCache();
setTimeout(function() {
location.reload();
}, 2000);
}
}
window.addEventListener('load', function() {
var c = window.applicationCache;
c.addEventListener('cached', setVideo, false);
c.addEventListener('noupdate', setVideo, false);
c.addEventListener('updateready', update, false);
}, false);
で、マニフェストも更新。
CACHE MANIFEST
# version 0.2
sample.html
video.mp4
video.webm
コードは適当なので多少間違いや不備があるかもしれませんが...
さて、このようにするとどうなったかといいますと...
- iOS Safariの場合、再生ボタンをタップすると、キャッシュされた動画が即座に再生されます。
- Android (標準ブラウザ、Chrome、Firefox)の場合、依然として、キャッシュが無視され、一からバッファリングをやり直して再生しようとします。
以上、まとめ
そういうわけで、iOS Safariでは、キャッシュが完了してから、src
属性にファイルの場所をJavaScriptで後から指定してやると、キャッシュを参照して再生してくれる、ということになるようです。しかし、Androidではどうあがいてもキャッシュから動画を再生してくれない、ということにもなってしまいます。
そうなると、Androidでは他に手立てはないのだろうか、ということになりますが...続きは次の機会に。