サムネイル画像をlocalにキャッシュするようにしました
動画のサムネイルをキャッシュして表示スピードを上げる
一部の動画サイトでは画像の読み込みが遅く、表示に時間がかかるためサムネイルをlocalに保存する仕様にしました。また、スマートフォンで表示する場合に無駄に大きいサイズの画像を取得しているのも解消されます。
具体的には対象の画像をとってきて最適なサイズ(と言っても大きめですが)のサムネイルを作成して保存するだけです。
画像の取得
イメージを取得するだけならLWP::UserAgentで出来るのですが、今回はFetch::Imageというモジュールを使ってみました。
このモジュールの特徴としては画像ファイルかどうかを判定するバリデーションしてくれると言う事と、取得した画像を一時ファイルとして保存してくれるところ。
テンポリファイルの保存場所はOSに応じて変わります。
cpanm でインストールするとtestでコケるので -fでインストールしてしまってます(testの中で該当のURLが無いっぽいのが原因みたいなので)
404の時のエラーを判定したかったので Fetch::Image を継承して _head メッソドをオーバーライドして使っています。
package Morolicious::Fetch::Image; use strict; use warnings; use base "Fetch::Image"; use Data::Validate::URI qw/is_web_uri/; # returns a HTTP::Response for a HTTP HEAD request sub _head{ my ( $self, $ua, $url ) = @_; my $head = $ua->head( $url ); $head->is_error(404) && Exception::Simple->throw("not found"); $head->is_error && Exception::Simple->throw("transfer error"); exists( $self->{'config'}->{'allowed_types'}->{ $head->header('content-type') } ) || Exception::Simple->throw("invalid content-type"); if ( $head->header('content-length') && ( $head->header('content-length') > $self->{'config'}->{'max_filesize'} ) ){ #file too big Exception::Simple->throw("filesize exceeded"); } return $head; } 1;
サムネイルの作成
サムネイルの作成などPerlで画像を編集する場合にはImage::Magickを使うことが多かったのですが、今回はImagerを使っています。特に理由は無かったのですが、Imagerの方がAPIがきれいという事で使ってみました。
実装
基本的にはFetch::Imageで得たテンポラリファイルのpathをImagerで読み込んで、サムネイルを作成後localに保存しているだけです。
MoroliciousではQudoを使ってジョブキューを処理しています。AnyEventのタイマー処理を使って、未キャッシュの動画情報をDBから探してキューを作成しています。
ジョブキューを見つけるとQudoのworkerが画像を読み込んでサムネイルを作成・保存する仕組みにしています。
恩恵を受けるのは新着一覧や動画の検索ページ等のサムネイルを多く表示するページのみですが、少しは快適になっているかな?