AWS Lambda で画像のサムネイルを作る
What for?
- 基本の素振りはできたので、少しは役に立つものを作る
- S3にアップロードされた画像のサムネイルをつくる
Prepare
- node.js x imagemagick にトライ
このライブラリが使えそう github.com
Exif情報の読み込み
var im = require('imagemagick'); im.readMetadata('hoge.jpg', function(err, metadata){ if (err) throw err; console.log('Shot at '+metadata.exif.dateTimeOriginal); })
- convertでのリサイズ
- S3のデータにどうやってconvertかけよう?
- バイナリデータ拾ってきて流し込みたいな
- S3のデータにどうやってconvertかけよう?
var im = require('imagemagick'); im.convert(['hoge.jpg', '-resize', '25x120', 'hoge-small.jpg'], function(err, stdout){ if (err) throw err; console.log('stdout:', stdout); });
- バイナリデータ流し込みでconvertして、file put
- imagick: srcDataで流し込める
- S3: s3.getObjectで取ってきてbodyをかちこむ
var im = require('imagemagick'); var fs = require('fs'); im.resize({ srcData: fs.readFileSync('hoge.jpg', 'binary'), width: 256 }, function(err, stdout, stderr){ if (err) throw err fs.writeFileSync('hoge-resized.jpg', stdout, 'binary'); console.log('resized kittens.jpg to fit within 256x256px') });
S3のObject取ってくる練習
- 準備で対象S3にfull accessできるIAM role作っとく
- 実行するときは、Role指定で実行
$ AWS_PROFILE=rw-s3 node simpleS3.js
BacketList取ってくるだけ
var AWS = require('aws-sdk'); s3 = new AWS.S3(); s3.listBuckets(function(err, data) { if (err) { console.log("Error:", err); } else { for (var index in data.Buckets) { var bucket = data.Buckets[index]; console.log("Bucket: ", bucket.Name, ' : ', bucket.CreationDate); } } });
- S3からファイルをローカルに保存
- readstreamでデータ取ってきて、fsのwritestreamでputする
var AWS = require('aws-sdk'); var fs = require('fs'); var s3 = new AWS.S3(); var params = {Bucket: 'for-lambda-test', Key: 'hoge.jpg'}; var file = fs.createWriteStream('output.jpg'); s3.getObject(params).createReadStream().pipe(file);
Code
- コードの大きな流れ
- S3にファイルをput -> Lambda関数が呼ばれる -> eventからS3 objectを取得 -> w100_ のprefixの有無の確認 -> convertする -> 同じバケットにサムネイルを保存する
var AWS = require('aws-sdk'); var fs = require('fs'); var im = require('imagemagick'); var s3 = new AWS.S3(); exports.handler = function (event, context) { var bucket = event.Records[0].s3.bucket.name; var key = event.Records[0].s3.object.key; var params = { Bucket: bucket, Key : key }; console.log(params); // For stop infinity loop if (key.substr(0,5) === 'w100_') { return; } s3.getObject(params, function (err, data) { if (err) { context.done('error on get obj', err); } console.log(data); im.resize({ srcData: data.Body, width: 100 }, function (err, stdout, stderr) { if (err) { context.done('error on resizing', err); } s3.putObject({ Bucket: bucket, Key : 'w100_' + key, Body : new Buffer(stdout, 'binary') }, function (err, res) { if (err) { context.done('error on put obj', err); } context.done(); }); }); }); };
- 初回は、
w100_ のprefixの有無の確認
の記述を書き忘れて、無限ループに突入していた- ファイルが数百個できて悲惨だった...orz
// For stop infinity loop if (key.substr(0,5) === 'w100_') { return; }
TODO
- Node.js のoutputやらエラーハンドリング周りがわかってない
- Node.js の writeStream やら readStream やらがしっくりきてない
- 不安だからテスト書きながら進めたいけど、Node.jsのテスト手法やいかに
node-imagemagick
の最終更新がJul 24, 2014
なので違う方法のほうが良さそう