iOSのHTML5 Audio/VideoのcurrentTimeがおかしい

iOSのHTML5 Audio/VideoのcurrentTimeがおかしい

  • このエントリーをはてなブックマークに追加

1年前に買ったSIMフリー版のiPhone6をauで使っていましたが、iijmioの「おうちでナンバーポータビリティ」でMNPしました。特に問題などなく使えています。4インチのを出して欲しいのでiPhone6sは見送りました。

前回、AndroidのHTML5 Audioのバグについて書きましたが、iOSのHTML5 Audio/Videoでも次の2つのバグを見つけました。

  • currentTime に連続して同じ値を代入するとシークできない。
  • 再生終了後、currentTime へ代入した直後に play() を呼んでも再生が始まらない。

今回は、これらの発生条件の詳細と回避方法について書きます。
なお、Audioを使っての説明となりますが、Videoでも同じです。

currentTime に連続して同じ値を代入するとシークできない

iOS8,iOS9で発生します。iOS7では発生しません。

var audio = new Audio("sample.m4a");
audio.play();

var seekButton = document.getElementById("seekButton");
seekButton.addEventListener(function() {
    audio.currentTime = 10;
    audio.currentTime = 10;
}, false);

サンプルを実行する

普通、このように同じ値を連続して代入するコードを書くことはありませんが、複雑な処理を書いていると、少し離れた場所で同じ値を再度代入してしまうことが起きてしまうことはあると思います。

回避方法ですが、(1回目の)代入直後は seeking が true となっており、またそのとき currentTime の値を読み出すと代入した値がそのまま返ってくるようなので、(2回目の)代入直前に seeking と currentTime をチェックすればよさそうです。

seekButton.addEventListener(function() {
    audio.currentTime = 10;
    if (!audio.seeking || audio.currentTime !== 10) {
        audio.currentTime = 10;
    }
}, false);

なお、連続した代入でも値が異なれば大丈夫なようです。

seekButton.addEventListener(function() {
    audio.currentTime = 10;
    audio.currentTime = 10.000000000000002;  // 倍精度浮動小数で10の次に大きい値
}, false);

2回目の代入を setTimeout で行うのも問題ないようです。

seekButton.addEventListener(function() {
    audio.currentTime = 10;
    setTimeout(function() {
        audio.currentTime = 10;
    }, 0);
}, false);
続きを読む

再生終了後、currentTime へ代入した直後に play() を呼んでも再生が始まらない

ひとつ目と同様iOS8,iOS9で発生しiOS7では発生しませんが、こちらはMacのSafari9.0でも発生しました(Mac Safariの他のバージョンは未確認)。

var audio = new Audio("sample.m4a");
audio.play();

var seekButton = document.getElementById("seekButton");
seekButton.addEventListener(function() {
    if (audio.ended) {
        audio.currentTime = 10;
        audio.play();
    } else {
        alert("再生終了するまで待ってね");
    }
}, false);

サンプルを実行する

play() の呼び出しを setTimeout で行うと大丈夫なようです。

seekButton.addEventListener(function() {
    if (audio.ended) {
        audio.currentTime = 10;
        setTimeout(function() {
            audio.play();
        }, 0);
    } else {
        alert("再生終了するまで待ってね");
    }
}, false);

まとめ

これら2つのバグを見ると、currentTimeに代入した直後にさらに別の操作をすると何か問題を引き起こす可能性がありそうで、この2つだけでなく他にもバグがありそうな気がします。iOSのHTML5 Audio/VideoでのcurrentTimeの操作絡みで何か問題が起きた場合は疑ってみるとよいかもしれません。

※サンプルの音源は、著作権が切れたパブリックドメインのものを使用しています。
(ベートーヴェン ピアノソナタ第8番ハ短調「悲愴」 Op.13 第2楽章 Pヴィルヘルム・バックハウス 1958年録音)

  • このエントリーをはてなブックマークに追加

記事作成者の紹介

らくさん(フロントエンドエンジニア)

フロントエンドエンジニアのらくさんです。JswfPlayerという弊社サービスでFlash再生エンジンを開発したり、動画広告Guileの動画プレーヤーを開発したりしています。

関連するSONICMOOVのサービス

フロントエンドエンジニア募集中!

×

SNSでも情報配信中!ぜひご登録ください。

×

SNSでも
情報配信中!
SONICMOOV Facebookページ SONICMOOV Twitter
フロントエンドエンジニア募集中!

新着の記事

mautic is open source marketing automation