AWS Lambda
AWS Lambdaはre:Inventで発表されたクラウド上でコードスニペットをイベントドリブンで実行出来るプラットフォームです。
S3 EventNotificationやDynamoDB、Kinesisと連携することが出来ます。例えば、S3にファイルがPUTされたら、そのイベントをトリガーにしてDynamoDBに情報を書き込んだり、AWS SDKを利用して他のAWSサービスを呼び出すことも可能です。現在のところ、LambdaではNode.jsがサポートされています。サードパーティモジュールもnpm_modulesディレクトリも含めてzipでUploadすることで利用することが可能です。
http://aws.amazon.com/lambda/
Amazon Elastic Transcoder
Amazon Elastic Transcoderは動画や音声を簡単にエンコードが行えるフルマネージドサービスです。リリース時に書いたBlogですが、http://d.conma.me/entry/2013/01/30/002445 に概要をまとめています。
Amazon Elastic Transcoderもリリース後機能追加や性能改善が行われており、SmoothStreamingやSSE対応などが直近で行われた追加です。
組み合わせてみる
今回は、AWS Lambdaを簡単に使ってみる例としてS3の特定のバケットに動画がアップロードされたら、S3のEvent NotificationからLambdaを呼び出して、Elastic TranscoderにエンコードJobを登録するというsnippetです。
Amazon Elastic Transcoderの作成
Amazon Elastic TranscoderのPiplineの作成は割愛します。http://d.conma.me/entry/2013/01/30/002445
に簡単にですが書いてありますのでご参照下さい。
LambdaへFunctionの登録
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
var ets = new aws.ElasticTranscoder({apiVersion: '2012-09-25', region: 'us-east-1'});
exports.handler = function(event, context) {
console.log('Received event:');
console.log(JSON.stringify(event, null, ' '));
var bucket = event.Records[0].s3.bucket.name;
var key = event.Records[0].s3.object.key;
var pipelineId = key.split('/')[0];
var presetId = key.split('/')[1];
var fileName = (key.split('/')[2]).split('.')[0];
ets.createJob({
PipelineId: pipelineId,
OutputKeyPrefix: 'demo/',
Input: {
Key: key,
FrameRate: 'auto',
Resolution: 'auto',
AspectRatio: 'auto',
Interlaced: 'auto',
Container: 'auto',
},
Output: {
Key: fileName + '.mp4',
ThumbnailPattern: fileName + '-thumbs-{count}',
PresetId: presetId,
Rotate: 'auto'
}
}, function(error, data) {
if(error) {
console.log(error);
context.done('error',error);
} else {
console.log('Job submitted');
context.done(null,'');
}
});
};
このような簡単なsnippetを登録しておきます。
あくまで参考ということで、エラーハンドリングや重複処理が甘い、mp4以外のpresetへ未対応なコードとなっていますが、LambdaをとS3 Notificationを使うイメージを掴んでいただければと思います。
1点だけ注意ですが、functionを作成する際に、Roleを作成します。こちらはLambdaに設定されるIAM Roleですが、標準のままだと
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:*"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
のようにS3に対する権限のみついているシンプルなものが付与されるため、Elastic TranscoderにJobをSubmit出来る権限をつけます。
IAMの画面からRolesの中に先ほど作成されたlambda_exec_role
(デフォルト名)があるので、それに権限を付与します。もちろん、Lambdaのfunction作成時に一緒に権限を付与してしまう事も可能です。
後から付与する場合は、先ほどのIAM Rolesから選択したRole中のAttache Role Policy
からSelect Policy Template
内のAmazon Elastic Transcoder Jobs Submitter
を付与します。
function毎に必要な権限を追加してRoleを作成することをオススメします。
S3の準備
動画をアップロードする用とエンコード済み動画を格納するバケットをそれぞれ作成しておきます。動画をアップロードするためのバケットのEventsタブで
今回は動画ということで、マルチパートアップロード前提でマルチパートアップロードが完了した場合に通知するCompleteMultiPartUpload
をEventに指定し、先ほど作成したLambdaのfunctionを呼び出すように設定します。(通常のPutを使う場合はEventでPut
を指定します)
Invocation roleはIAM Roleで
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
"*"
],
"Action": [
"lambda:InvokeFunction"
]
}
]
}
このような権限を設定します。Lambdaの画面からS3にConfigure Event SouceでS3に関連付けると自動的にこのロールを作る事が可能です。
エンコードしてみる
Elastic TranscoderにはPipline IDと呼ばれる識別子とエンコード動画形式を指定するPreset IDと呼ばれるものがあります。Jobを登録する際はこちら双方のIDが必要になるのですがsnippetに埋め込むのも変更しづらいので、Objectのkey prefixとして指定するようにしてみました。
形式は
Pipline ID/preset ID/ファイル名
この順番でディレクトリを切って、ファイルをアップロードするといい感じにエンコードをしてくれると思います。
まとめ
今回は簡単にS3とElastic Transcoderが連携出来るのがわかっていただけたと思います。短いコードでS3にアップロードしてエンコードまでがすぐに出来るようになりました。今までだと、S3をポーリングするか別途APIサーバにエンコード要求を送るなどしていたかと思います。この構成にCloud FrontをS3の前面に置くことでCognitoなどもつかうと、EC2インスタンスを一切たてること無く、動画のアップロードからエンコードして、CDN経由で配信まで可能になります。もちろん認証付きです。
また発展系として、DynamoDBに再生数やLike数などを入れて、DynamoDBとSNS Mobile Pushと組み合わせると、動画がアップロードされたりLikeが一定数ついたらPush通知を送るという応用も出来ると思います。
是非、AWS Lambdaで遊んでみてはいかがでしょうか?
こちらは個人の意見で会社とは関係ありません。お約束です。