All Articles

AWS LambdaでS3にアップロードすると自動でリサイズ・減色するパッケージ書いた

リサイズとか減色とかも自動でやりたい人向け

このご時世のフロントエンドエンジニアという肩書きを持ってる方々におかれましては、画像の減色とか最適化はタスクのうちの1つだと思いますが、 それって自身の管理下にある静的な画像リソースに限られてしまいますよね(背景画像とか、CSSスプライト用の画像とか)。 例えばユーザーの投稿した画像は管理外になってしまうし(VCS管理下に置かれない)、リサイズするスクリプト書いたりするのも面倒でした。 (そもそもユーザ画像を減色するのはどうなのってこともありますが、必要なケースもままあるかと)

ということで、AWS Lambdaを使って、S3に上がった画像を自動的にリサイズ、最適化して戻してくれるスクリプト書きました。

ysugimoto/aws-lambda-image

動作としては、

S3に上げる →Lambdaでイベント検知、処理実行 →S3に戻す

という感じです。Lambdaの設定とかは下記のサイトとか参考にしました。公式が一番早いといえば早いですね:

AWS Lambdaを始めてみる(2).Amazon S3イベントを扱う Amazon S3 イベント通知の設定

今回はs3:ObjectCreated:Putのイベントを使います。それから、対象はjpg/pngのファイルのみです。gifはいいかなって。

使い方など

READMEを見て頂くとわかりますが、リポジトリをcloneしてビルドしてzipアーカイブをLambdaにアップロードするだけです。簡単です。 あとは設定ファイルで幾つか挙動を変更できるようにしてます。

アップロードされたら減色、リサイズして別bucketに送る

一番想定される使い方です。イベント検知用のbucketに画像をPutして、処理した画像をメインのbucketに送る、という感じです。

{
  "bucket": "本番のbucket"undefined
  "reduce": {
      "directory": "減色したファイルを置くディレクトリパス"
  }undefined
  "resizes": [
    {
      "size": リサイズしたいサイズ(width:px)undefined
      "directory": "リサイズ・減色したファイルを置くディレクトリパス"
    }
    undefined ...
  ]
}

bucketは転送先のbucketです。指定されなかった場合はPutされたbucketを使います。 reduceはPutされた画像自体を減色する設定です。directory以下に格納します。 resizesは配列で、何枚でもサムネイルの作成が可能です。リサイズした画像ももちろん減色します。

で、設定を書いたらmakeでアーカイブを作ってLambdaにアップロードしましょう。設定が上手く行っていれば、S3にアップロードすると減色されてサイズが小さくなった画像が指定の場所に作成されているはずです。 注意点として、Lambdaがイベントを検知しているbucket内、指定ディレクトリに減色・リサイズ後のファイルを置く設定にすると、無限イベントループが起きます。これ注意ですね。

その辺りを防ぐため、make configtestというコマンドをバンドルしてます。無限ループが起こりそうな設定の時は警告が出るようにしてますので、使ってみてください。

その他、ハマったところなど

  • Lambdaのnodeはv0.10.26です。Promiseとかそういうのねぇから!(polyfill使った)
  • Lambdaは/tmpに50MB程度の領域を用意してくれるそうですが、このパッケージはオンザフライで処理してる(nodeのBufferとStreamであれこれします)
  • Lambdaはシェルが無いので、テストが手動すぎて辛すぎた><
  • なんやかんやAmazon Linuxぽいので、Linux用のバイナリをバンドルして実行するように。よってMacでは開発しづらく、初期はUbuntuでやってた
  • 一回無限イベントやらかして多額の請求が来ないかびびってた(大丈夫そう)
  • nodeのStream初めてちゃんと使った。難しい

という感じですかね。よろしければMITライセンスの範囲でお使いくださいませ。 PRもお待ちしております。

現場からは以上です。

Thanks for @1000ch, @ahomu!