Chrome for Android で HLS 再生をしようと playlist.m3u8 をリクエストすると、
Range: bytes=0-1
を含む意図しないリクエストが発生し、2byte のデータ(改行コード)が返る。
その結果 video.js が「サポートしていないファイルだ」として再生を諦めてしまう。
Name | Status | Type | Initiator | Size | Time ... |
---|---|---|---|---|---|
playlist.m3u8 | 200 | media | unknown | 0 | ... |
- XMLHttpRequest の setRequestHeader で
Range: bytes=0-1
を発行している箇所を探ったがそのようなコードはない - ブレークポイントを設定してコードを丹念に追ったが、いつの間にかエラーになる
- Google.search("nginx proxy range request streaming") で探す
-
以下の情報がヒットした
-
httpdがRangeリクエスト(bytes)に対応していないとiphoneから動画再生ができない 2012-01-08
Accept-Range: bytes
をサポートしていないサーバが 200 を返すと iPhone で動画や音声を再生できないらしい
iphoneのリクエストヘッダを見ていると、動画再生時にまず"Range: bytes=0-1" を送って、Rangeリクエストに対応しているかチェックしている様子。そのときに"206 Partial Content" が返ってこない場合、Rangeリクエストに対応していないと判断して、動画の再生を諦めるっぽ。
-
nginxリバースProxyにてRANGEリクエスト対応 2014-04-06
- iPhone(Chrome for Androidも?) ではストリーミング再生に先立ち、
Range: bytes=0-1
の 2byte を要求し、206 が返ってこない場合は再生を諦めるらしい - nginx のリバースプロキシにおいてキャッシュしつつ 206 を返す方法は2つあるとのこと
-
1つは proxy_cache_key $http_range を追加する
-
2つ目は nginx にパッチを当てるらしい(nginx 1.2.0 で有効との事)
// ngx_http_upstream.c #if (NGX_HTTP_CACHE) - if (r->cached) { + if (r->cached || r->upstream->>cacheable) { r->allow_ranges = 1; return NGX_OK; } #endif
-
- さらに探すと nginx 1.7.7 以降で使える
proxy_force_ranges
という directive がある との事
Syntax: proxy_force_ranges on | off; Default: proxy_force_ranges off; Context: http, server, location This directive appeared in version 1.7.7.
Enables byte-range support for both cached and uncached responses from the proxied server regardless of the “Accept-Ranges” field in these responses. via
- iPhone(Chrome for Androidも?) ではストリーミング再生に先立ち、
-
location /api/ {
proxy_http_version 1.1;
proxy_pass http://xx.xx.xx.xx/api/;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, Authorization, Accept";
add_header Access-Control-Allow-Credentials true;
proxy_force_ranges on; # https://gist.github.com/uupaa/ad00a1912b5770b0023d
}
上手く行った!