前回の記事では、通信処理に Socket.IO を用いることで fps の改善を図りました。
今回は、前回の記事から3点、試行錯誤を行った結果について掲載させていただきます。
■画像のフォーマットについて
Androidのカメラで撮影した画像は、形式が「YUV」というものになっています。
今回の調査で、このままの状態のデータだと、サイズが非常に大きいことがわかりました。
前回は、これをJPEG画像に変換していましたが、この画像を更に小さいサイズにすることが
できれば、fps の改善を図れると考えました。
Androidでは、YUV形式の画像から変換できるフォーマットに、以下3種類があります。
JPEG
PNG
WEBP
そこで、PNG、WEBPそれぞれにデータを変換し、fpsがどのようになるのか測定したところ、
PNGは、JPEGに比べてファイルサイズが大きくなり、結果的に fps が落ちました。
WEBPというのは、Googleが開発している静止画フォーマットです。
こちらに変換を行ってみたところ、同一環境下の場合、JPEGと比較して2割~3割、
画像サイズが小さくなりました。
ただし、そもそもの変換処理が遅く、通信ではなく、そちらのほうで遅延が発生し、
結果として fps が落ちてしまいました。(数fps程度にまで落ちてしまいます)
よって、最適なフォーマットは前回利用していたJPEGという結論になりました。
このため、フォーマットを変更することでの改善は見込めませんでした。
ただし、リアルタイムに動画を配信するという仕組みにおいては
WEBPを利用することはそぐわなかったですが、
大量の枚数の画像を、サーバに保存しておく場合には、
JPEGよりも容量の軽い、こちらのフォーマットのほうが適しています。
今後、開発を進めていくうえで、WEBPを利用するシーンが出てくるかもしれません。
■画像の圧縮率について
JPEG画像を作成する際、圧縮率を設定することができます。
0~100の間で指定することができ、数値が小さいほうが、より画像サイズが小さくなります。
詳しい話は、他者様のページに詳しく記載があるので割愛しますが、
動画をリアルタイムで再生するという用途であれば、
最低でも75の圧縮率はないと、品質的に問題があります。
数値を下げるほうが効果は上がりますが、品質は下がるため、
今回はひとまず80とし、この値を今後、どうしていくのかは、
さらに色々と改善を図った後で、最後に決定しようと思います。
■画像を1秒単位でまとめて送信する
複数の画像を一度にアップロードする方が、通信負荷を低減でき、速度が改善する
のではないかと推測し、画像データを複数枚、端末で保持しておいた後で、
1秒単位で一度にサーバに送信するように、修正してみました。
現在、Socket.IOの通信部分はブラウザ(HTML)で実施しており、
画像の送信については、form 部品の text タグに、
画像データを Base64 変換したものを設定しています。
クライアント側は単純に、text タグの数を複数用意して、すべてのタグが
埋まったところで送信するようにし、サーバ側ではその画像を一気に保存、
所定の枚数に達した時点で動画変換を行う
というようなロジックに修正しました。
この結果、画像サイズ「512×384」で20fps迄、性能を改善することができました。
※前回は、画像サイズ「448×336」で15fps
図1 200枚の画像が10秒でアップされています
図2 画像サイズが「512×384」となっています
■今後の改善について
ここから先、さらにfps値を改善していくためには、
今のところは主に、携帯端末側と、サーバ側のボトルネックとなっている部分を
1つ1つ、改善していく必要がありますが、
どこがボトルネックとなっているのかを、まだ把握できていません。
次週は、現段階の仕組みでの、各部分に要している時間を計測することで、
今後、どこを改善していくのかをまとめようと思います。
弊社では全国各地の請負い(ご自宅)で作業協力頂ける、フリーランスエンジニアの方を常時探しております。
ご興味ある方は、お気軽にお問い合わせ下さい。