AWS
lambda
ElasticTranscoder

AWS LambdaとElastic Transcoder

More than 1 year has passed since last update.

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タブで
S3_Management_Console.png

今回は動画ということで、マルチパートアップロード前提でマルチパートアップロードが完了した場合に通知する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で遊んでみてはいかがでしょうか?

こちらは個人の意見で会社とは関係ありません。お約束です。