AWS Lambdaのimagemagickでリサイズ失敗問題について
結論
先に結論から言うと、Lambdaがデフォルトで提供しているimagemagickライブラリだと特定の画像のリサイズで失敗するっぽいです。
ローカルでnpm install imagemagick
したパッケージを含めてlambdaにzipアップロードして、同じコード同じ画像で試して正常に動いたので間違いないはず。
問題のエラー
以下Lambda functionを「Edit code inline」で入力して、S3によくある普通の画像をアップロードして実行させました。*1
var im = require('imagemagick'); var aws = require('aws-sdk'); var s3 = new aws.S3(); var thumbnailSize = 600; function resizeImage(context, bucket, key, data) { var contentType = data.ContentType; var extension = contentType.split('/').pop(); im.resize({ srcData: data.Body, format: extension, timeout: 0, width: thumbnailSize }, function(err, stdout, stderr) { if (err) { console.log(err); context.done('resize failed: '+key); return; } // avoid endless loop if (bucket.match(/-thumbnail$/i)) { context.done('no support bucket: '+bucket); return; } var thumbnailBucket = bucket + "-thumbnail"; var thumbnailKey = 'thumbnail/' + key.split('.')[0] + "-thumbnail." + extension; s3.putObject({ Bucket: thumbnailBucket, Key: thumbnailKey, Body: new Buffer(stdout, 'binary'), ContentType: contentType }, function(err, res) { if (err) { console.log(err); context.done('error putting object: '+key); } else { console.log('create thumbnail: '+thumbnailKey); context.done(); } }); }); } var createThumbnail = function(event, context) { var bucket = event.Records[0].s3.bucket.name; var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); s3.getObject({ Bucket: bucket, Key: key, IfMatch: event.Records[0].s3.object.eTag }, function(err, data) { if (err) { console.log(err); context.done('error getting object: '+key); return; } resizeImage(context, bucket, key, data); }); }; exports.handler = function(event, context) { createThumbnail(event, context); };
すると以下のログがCloud Watchに出力されました。
{ [Error: Command failed: ] timedOut: false, killed: true, code: null, signal: 'SIGKILL' }
メモリを上げ下げしたり、画像の解像度・ファイルサイズ、画像の形式・メタ情報まで色々変更して試してみても改善されず。 最終手段で、imagemagickを含めてアップして実行するとすんなり動きました。意味がわからない。
まとめ
素直にnpmで最新版(安定版)を準備してまとめてLambdaにzipアップロードが一番良いと思います。 ちなみにzipアップロードですが、以下のようなshellでzipを作ってます。そのままフォルダを圧縮するとエラーになるので気をつけてください。
#!/bin/sh zip -r lambda index.js node_modules