DEVELOPMENT
目次
Line Messaging API を AWS Lambda + API Gatewayで実装し、S3へのアップロード、Rekognitionでの画像解析をする紹介です。
最初に
皆さんLINEはメッセージツールとして大体使っていると思います。
うちで運用しているwebサイトは、このブログのように、hugo や hexo、Gatsbyなどの静的サイトジェネレーターを使って、マークダウン方式で記事を作成し、
サイトの更新をしています。
その際、エンジニアであれば、ターミナルやエディタで作業可能ですが、
非エンジニアの場合にこの作業をしてもらう場合、どうすればいいか考えると
- netlify でhostingするように変える
- 自前で投稿ページを作り、AWS codeBuildか何かでジェネレーターを実行するよう作る
- マークダウン方式だけ覚えてもらい、webのマークダウンエディタを使い作成してもらい、エンジニアがUPする
wordpressは今更絶対嫌なんで、このくらいでしょうか?
将来的には、みんなターミナルが触れるようになるといいと、願っているので、 今回は勉強のためにも、
3 の マークダウン方式だけ覚えてもらい、webのマークダウンエディタを使い作成してもらう
を採用しようと思いました。
画像問題
その場合、画像はどうすればいいか。画像もエンジニアに渡して埋め込んでもうとなると、とってもエンジニがが手間です。
DropBoxやGoogle photo flicker等も試しましたが、サイズや作業的にイマイチだったので、
ホスティング先を自分で用意し、
誰もが使い慣れているLineで画像がUPできて、ホスティング先を返して上げれば楽だな。と思い作ることにしました。
ついでに解析もしちゃう
流れとしては、
- Lineに画像送信
- Webhookより、API GatewayからLambdaを呼ぶ
- 送られてきた画像をS3にUP
- Hosting先URLをLineで返却
ですが、せっかくS3に画像上げたんなら、前から試したかったRekognitionで、画像を解析し、ラベルにより、画像のキーワードを抽出するようにしました。
そして最後に、抽出されたキーワードをTranslateで日本語にし、返してあげるという流れになります。
構成
投稿側
- LINEに画像送信
- LINE Messaging APIのwebhookにて、APIGatewayを通じて、Lambdaへ
- 送られてきた画像を取得し、S3へUPしそのURLを取得
- S3にアップされた画像をRekognitionで画像解析
- 英語でラベルを取得
- Rekognitionで取得したラベルを Translatteへ
- ラベルを日本語で取得
閲覧側
こっちはよくあるサーバーレスの構成ですね。
- UPされた画像URLへアクセス
- Route53からCloudfrontへ
- CloudfrontからS3へ画像を取得
- 返却
- 返却
- 画像表示
この組み方は、
▶ サーバレス AWS s3 + cloudfront + route53 + ACM で静的website ホスティング のメモ
に詳しく記載してます。
準備
まずは、下記のページより、
- Line Developer登録し、Messaging APIを使える状況に整える
- AWS S3やLambda、API Gatewayの準備
を進めます。
▶ Line Messaging API で Line Bot を作ってみた | AWS lambda
ちょっと手こずった部分
LINEから送られてきた画像取得がサクッとできなかった
const getLineImage = ("メッセージIDです") => {
return new Promise((resolve, reject) => {
client.getMessageContent(id)
.then((stream) => {
var data = []
stream.on('data', (chunk) => {
data.push(new Buffer.from(chunk))
})
stream.on('error', (error) => {
debug("Error: line image. " + error)
reject(error)
})
stream.on('end', () => {
debug("Success: get line image.")
resolve(data)
})
})
})
}
コール時は、awaitで呼びますね。
途中経過で処理が必要なので、Promiseをでさらにラッピングしました。
リファレンス ▶ Line Developer
参考 ▶ LINE BOTに送った画像をNode.jsで受信して保存するサンプル | Qiita
LINEで取得した画像をS3へUP
const AWS = require('aws-sdk')
AWS.config.region = 'リージョン'
const s3 = new AWS.S3({ apiVersion: 'xxxxxxxxxxxxx' })
// put image for s3 bucket.
// put image for s3 bucket.
const putS3 = async (data, id) => {
debug(data)
var params = {
Bucket: process.env.S3_BUCKET,
Key: "ファイル名",
ContentType: 'ファイルフォーマット', // ここないと、webでアクセスしても表示できず、ダンロードされちゃう
Body: Buffer.concat(data)
}
return await s3.putObject(params).promise()
}
await で呼び出せばOKです。
参考 ▶ JavaScript Promises の使用 | AWS ドキュメント
Rekognitionへの処理
// get label of images from rekognition
const getImageLabelFromRekognition = (id) => {
return new Promise((resolve, reject) => {
const params = {
Image: {
S3Object: {
Bucket: "バケット名",
Name: "UPした画像のファイル名",
},
},
MaxLabels: 30 // 最大取得件数
}
rekognition.detectLabels(params).promise()
.then((data) => {
var list = []
data.Labels.forEach(label => {
list.push(label.Name)
debug(`Label: ${label.Name}`)
debug(`Confidence: ${label.Confidence}`)
debug("Instances:")
label.Instances.forEach(instance => {
let box = instance.BoundingBox
debug(" Bounding box:")
debug(` Top: ${box.Top}`)
debug(` Left: ${box.Left}`)
debug(` Width: ${box.Width}`)
debug(` Height: ${box.Height}`)
debug(` Confidence: ${instance.Confidence}`)
})
debug("Parents:")
label.Parents.forEach(parent => {
debug(` ${parent.Name}`)
})
debug("------------")
})
debug("success: rekognition")
resolve(list) // キーワードを配列で返した
}).catch((error) => {
debug("error: rekognition. " + error)
reject(error)
})
})
}
S3から画像を取得して、渡せば可能です。ほぼドキュメント通りですね。
Translateの処理
先程の配列のデータを連結し、文字列にし、一気に渡してます。 ソッチのほうがレスポンス早そうな気がするので。
const getTranslate = async (text) => {
let params = {
Text: text,
SourceLanguageCode: 'en',
TargetLanguageCode: 'ja',
}
return await translate.translateText(params).promise()
}
まとめ
promise連打なので、promiseやawait async部分についてしっかり理解しておいたほうが良さそうですね。 Lineの画像の取得部分が少し手こずりましたが
なんとかなりました。
このあと、サービス化に向けて、LINE PAYの導入方法とか調べてみようと思います。
何かあればTwitterでどうぞ!
株式会社UKAI 代表取締役CEO。建築を専攻していたが、新卒でYahoo!Japanにエンジニアとして入社。その後、転職、脱サラ、フリーランスエンジニアを経て、田舎へ移住し、ゲストハウスの開業、法人成り。ゲストハウス2軒、焼肉店、カフェ、食品製造業を運営しています。詳細はこちらから