質問: スマートフォンには通信制限というものがあってこの通信制限にひっかかるとサーバーからの画像の転送が著しく遅くなり、体感速度がかなり悪くなってしまいます。 そこで、サーバー側でスマートフォンとの通信速度(スマートフォン側からみたダウンロード速度)を測定して、基準値(例えば通信速度が100kbs以下)の場合は荒い画像を送信するなどして体感速度を上げたいと思っています。 サーバー側でスマートフォンとの通信速度を知ることができれば可能なのですが そもそもサーバー側でスマートフォンとの通信速度を知ることは可能なんでしょうか? 調べた感じでは `ping` コマンド `-s` オプションなどで送信するパケットサイズを調整することが可能であったり、 スマートフォン側からサーバー側のサイズの大きいダミーファイルをダウンロードさせて通信速度を調べるなどが考えられますが、ユーザーにサイズの大きいファイルをダウンロードさせると通信料を余計に消費させることにもなりかねず、なるべく通信料を抑えた方法でユーザーのスマートフォン側の通信速度を調べることはできませんか?
回答: 静止画の質問だと思ったので回答しませんでしたが、動画であれば次のようになっています。仕組みは幾つかあるのですがAppleが提唱して標準化されたHTTP Live Stream (HLS)方式について書きます。 プレーヤは動画を再生する前にマニフェストファイル(例:.m3u8の拡張子)を読み込みます。このファイルには、動画のビットレート、エンコード方式、画面のサイズなどの組み合わせで決定される複数のURLが含まれています。通常ビットレートで高中低の3つくらいを含めます。 ``` #EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000,CODECS="vp8,vorbis",RESOLUTION=240x135 http://example.com/low.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000,CODECS="vp8,vorbis",RESOLUTION=640x360 http://example.com/mid.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000,CODECS="vp8,vorbis",RESOLUTION=1280x720 http://example.com/hi.m3u8 ``` そのURLに従って次のマニフェストファイル(拡張子.m3u8)を読み込みます。このファイルには動画をぶつ切りにしたセグメントファイル(例:.tsとか、下の例では.webmの拡張子)のURLが複数入っています。 ``` #EXTM3U #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-TARGETDURATION:10 #EXTINF:10, http://media.example.com/segment1.webm #EXTINF:10, http://media.example.com/segment2.webm #EXTINF:10, http://media.example.com/segment3.webm #EXT-X-ENDLIST ``` 1つのセグメントはキーフレーム(画面全体の画像)が先頭に入っていて、あとは差分が続き、適宜キーフレームが挿入されています。これでどのファイルから再生してもOKだし、シークも素早くできるわけです。 プレーヤーはあるセグメントを再生中にそれに続くセグメントを次々と読み込みます。もしダウンロードスピードが再生に追いつかない場合は、最初のマニフェストに出てきたより低いビットレートのファイル群に切り替えます。 従ってサーバー側ではクライアント側の通信状況を知る必要はなく、ビットレートの変更はすべてクライアント側で行っています。