Chromeで動画のシークができない

HTMLにvideo要素で動画を埋め込んでみたところ、開始・停止の制御はできるものの、シークバーを動かしてもシークできずに悩んでました。

調べたところ、Chromeではサーバがrange requestsに対応していない場合に、シークできないようでした。

動画ファイルをHTTP(S)で配信するサーバはrange requestsが必須となりそうです。とはいえ、nginxなどメジャーなサーバは心配しなくても対応しているとは思います。

range requests非対応時のブラウザの挙動

Chromeでは、シークがいっさいできませんでした。最後まで再生を終えても、次は最初に戻ることしかできません。video要素のcurrentTime属性に値を代入すると0(先頭)に戻ってしまいます。(動作確認したバージョンはChrome 87)

Firefoxでは、動画ファイルをサーバから取得している範囲ではシークできました。再生し始めた段階では少し先までしかシークできませんが、最後まで再生すれば、次はどこからでも再生を再開できます。(動作確認したバージョンはFirefox 72)

Firefoxの動作は理解できますが、Chromeの動作はいじわるのような。。。

range requestsの動作概要

ブラウザは動画をシークしたときに、リクエストヘッダに

Range: bytes=1024-2047

のようにRangeを付けてサーバにリクエストします。リクエストする範囲を動画ファイルのバイト単位で示します。

サーバはrange requestsに対応している場合はステータスコード 206 Partial Content を返して、その範囲をレスポンスします。range requestsに対応していない場合は、通常のリクエストと同じように全体を返します。

詳細は以下のページに書いてあります。

サーバ側のrange requests対応

range requestsはnginxでは対応していました。たいていのHTTPサーバは大丈夫だと思いますが、簡易的なHTTPサーバでは対応していないこともあります。

python -m http.server コマンドでPythonのHTTPサーバを簡易的に動かせますが、これはrange requestsに対応していませんでした。

PythonのHTTPサーバに関する記事