※動画変換できるわぁい で作っちゃうと痛い目見るかもしれませんのでご注意を。。
##ざっくり流れ(適当)
##1. S3
準備
- 適当なS3バケットを作ります 例:hoge001.fuga002.com
- バケット内にmoviesというフォルダを作ります(作らなくても可)
- バケットの設定(後でも可)
- hoge001.fuga002.comバケットのプロパティ > イベント
- イベント:Put, CompleteMultiPartUpload (←アップロードと、分割アップロード)
- プレフィックス:movies/ (←moviesフォルダ配下)
- サフィックス:.mp4
- 送信先:Lambda関数
- Lambda関数名:mp4_transcoder (←2で作るLambdaの関数名にします)
- hoge001.fuga002.comバケットのプロパティ > イベント
##2. Lambda
?Lambdaてなんや?
“AWS Lambda は、コードを AWS Lambda にアップロードすると
サービスが AWS インフラストラクチャを使用してコードの実行を代行するコンピューティングサービスです。”
手順
- [Create a Lambda function] します
- [Skip] します(例文をもとに自分の好きなLambdaを書くのもいいと思います)
- [Name]はお好きなようにします
- [Description]もお好きなように説明書きします
- [Runtime]はNode.jsです
- Lambda function codeに下記のようなコードを入れます。(一部要編集)
NodeJSコード
console.log('Loading function');
var aws = require('aws-sdk');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });
var s3tokyo = new aws.S3({apiVersion: '2006-03-01', endpoint: 'https://s3-ap-northeast-1.amazonaws.com'});
var ets = new aws.ElasticTranscoder({apiVersion: '2012-09-25', region: 'ap-northeast-1'});
exports.handler = function(event, context) {
console.log('Received event:', JSON.stringify(event, null, " "));
var bucket = event.Records[0].s3.bucket.name;
var key = event.Records[0].s3.object.key;
var uploadFolderName = key.split('/')[0];
var fileName = key.split('/')[1].split('.')[0];
var extenSion = key.split('.')[1];
var filePathAndName = key.split('.')[0];
s3tokyo.getObject({Bucket:bucket, Key:key}, function(err, data){
if (err){
//getObject failed
console.log(err);
var message = 'Error getting object ' + key + ' from bucket ' + bucket +
'. Make sure they exist and your bucket is in the same region as this function.';
console.log(message);
context.fail(message);
}
else {
//getObject complete
console.log('data:', data);
console.log('bucket:', bucket);
console.log('key:', key);
console.log('uploadFolderName:', uploadFolderName);
console.log('fileName:', fileName);
console.log('extenSion:', extenSion);
console.log('filePathAndName:', filePathAndName);
console.log('ContentType:', data.ContentType);
var isNotMp4file = (extenSion != 'mp4');
if (isNotMp4file) {
//context fail message if it isn't mp4 file.
console.log('not mp4 file! process.exit!');
context.fail(message);
process.exit();
}
else {
//Check the ContentType
var isNotCorrectContentType = (data.ContentType != 'video/mp4');
if (isNotCorrectContentType) {
//if ContentType not equal "video/mp4", export the console.log
console.log('[must conversion] data.ContentType != video/mp4');
}
var type = 'video/mp4';
var params = {
Bucket: bucket,
CopySource: bucket + '/' + key,
Key: key,
ContentType: type,
MetadataDirective: 'REPLACE'
};
console.log('PARAMS is :', params);
console.log('To params set -> video/mp4');
//Rewrite the ContentType
s3tokyo.copyObject(params, function(err2, data2){
if (err2){
console.log('replace false...');
context.done('error','error2 getting file '+ String(err2));
}
else {
//Transcode to HLS
ets.createJob(
{
PipelineId: '*******************',
Input:
{
Key: key,
FrameRate: 'auto',
Resolution: 'auto',
AspectRatio: 'auto',
Interlaced: 'auto',
Container: 'auto',
},
Output:
{
Key: filePathAndName,
ThumbnailPattern: filePathAndName + '-thumbs-{count}',
SegmentDuration:'60',
PresetId: '1351620000001-200050',
Rotate: 'auto'
}
}, function(error, data) {
if(error)
{
console.log(error);
context.done('Job error...',error);
}
else {
console.log('Job submitted');
context.done(null,'');
}
}
);
//Transcode to mp3
ets.createJob(
{
PipelineId: '*******************',
Input:
{
Key: key,
FrameRate: 'auto',
Resolution: 'auto',
AspectRatio: 'auto',
Interlaced: 'auto',
Container: 'auto',
},
Output:
{
Key: filePathAndName + ".mp3",
PresetId: '1351620000001-300040',
}
},
function(error, data)
{
if(error)
{
console.log(error);
context.done('Job error...',error);
}
else
{
console.log('Job submitted');
context.done(null,'');
}
}
);
}
});
}
}
});
};
上記コードが主に行っていることは
1. S3にput, CompleteMultiPartUploadされた際にイベント発生
2. 対象のオブジェクト情報を取得
3. 拡張子がmp4でない場合はexit
コンソールログ出力「`not mp4 file! process.exit!`」
4. content-typeが"video/mp4"でない場合はexitコンソールログ出力「`[must conversion] data.ContentType != video/mp4`」
5. それ以外であればElastic TranscoderへJOB出力
6.Roleは、管理者権限があればlambda_basic_executionというRoleをその場で作り、後ほどにでもIAMの当該Roleに対して、S3へのアクセスポリシーと、ElasticTranscoderへのアクセスポリシーを付与します。(重要)
7.メモリやタイムアウト値は大きめがよいです。ただし…その分…お金が…
8.VPCは任意といった感じでしょうか..?(最近追加されたので詳しくは知らず。。)
####その他備考
-
console.logはCloudWatchへ出力されるデバッグ用です。ログの出力先は AWS CloudWatch > ロググループ /aws/lambda/mp4_transcoder
-
フォルダ構成を深く掘る場合は、splitをうまく使ってください
-
PipelineId: '**********'にはElastic Transcoderで作成したパイプラインIDを入力します
-
Elastic Transcoderのジョブ作成の各パラメータ(.tsとか.flvとか.mp3に変換する際の)は下記を参考にしました
http://docs.aws.amazon.com/ja_jp/elastictranscoder/latest/developerguide/create-job.html -
料金:https://aws.amazon.com/jp/lambda/pricing/
0.20 USD/1,000,000 件のリクエスト(0.0000002 USD/秒)
##3. Elastic Transcoder
?Elastic Transcoderてなんや?
“Amazon Elastic Transcoder はクラウドのメディア変換サービスです。
高度なスケーラビリティ、使いやすさ、高い費用効率性を実現する設計で、開発者や企業は、メディアファイルをその元のソース形式から
スマートフォン、タブレット、PC などのデバイスで再生可能できるバージョンに変換(または「トランスコード」)できます。”
パイプライン(←変換元と先の道路的な)のおもなの設定
- 概要
- Name: mp4-transcoder-pipeline
- Status: Active
- Input Bucket: hoge001.fuga002.com
- トランスコード先、サムネイル保存先
- Bucket: hoge001.fuga002.com
- Storage Class: Standard
- IAM Role
- Elastic_Transcoder_Default_Role (←先ほどと同様にその場で作成)
- Notifications
- On Completion Event: Create a New SNS Topicから成功時のトピック名を適当に作成しておきます。
- On Error Event: 同様にCreate a New SNS Topicから失敗時のトピック名を適当に作成しておきます。(後述するAWS SNSへ通知が飛ぶようになります。)
####動き
-
LambdaがpipelineIDを指定し、Jobを作成する。 (jobは各動画ファイルの変換命令書)
-
Jobsのページで、pipelineIDを指定し、[search]を押すとエンコード履歴が確認できます。
-
JobのStatusは確認したものは以下
- 成功:Complete
- 実行中:Proccessing
- 失敗:Error
- 待機中:Submitted
-
Errorの場合は、JobのIDの左側にある虫眼鏡のアイコンをクリックし、"Status Details"のエラー内容を確認すること。
##4. SNS(Simple Notification Service)
?Simple Notification Serviceてなんや?
“Amazon SNS は、高速で、柔軟性に優れ、完全マネージド型の pub-sub メッセージングサービスです。
Amazon SNS は、通知、メール、SMS メッセージをプッシュするクラウドベースのモバイルアプリケーション通知サービスとして、
またはエンタープライズメッセージングインフラストラクチャとして使用できます。”
-
Amazon SNSのページの、左メニュー"Topics"から、先ほどElastic Transcoderで設定したTopicを表示します。
-
CompleteかErrorどちらかのトピックのARN名をクリックします。
-
Create Subscriptionを押下し、好きなProtocolとEndpointを指定すれば、そのEndpoint宛へ購読可否が飛びます。
(例:
Protocol → Email
Endpoint → 自分のメールアドレス) -
届いたメール内のConfirm subscriptionのリンクへ飛べば購読手続き完了です。
##5. CloudFront
?CloudFrontてなんや?
“Amazon CloudFront はコンテンツ配信ウェブサービスです。
他のアマゾン ウェブ サービス製品と統合されたこのサービスを利用すると、開発者や事業主は、
低レイテンシーと高速なデータ転送速度で簡単にエンドユーザーにコンテンツを配信できます。最低利用量の条件はありません。”
####おもな設定
coming soon...
##所感
そのうちcloudfrontの連携内容も書きます。
##参考にしましたURL様
- http://qiita.com/ricken360/items/3223630da37956a1b96c
- http://akiyoko.hatenablog.jp/entry/2015/08/09/232933
- http://qiita.com/con_mame/items/b58a5e017e7c9ab2356b#%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B
- http://qiita.com/terapyon/items/ff2dd73bd479fbd44e82
- http://qiita.com/terapyon/items/b77ac981da790662e247
- http://popkirby.github.io/contents/nodeguide/style.html#conditions
- http://docs.aws.amazon.com/ja_jp/elastictranscoder/latest/developerguide/create-job.html#create-job-requests
- http://dev.classmethod.jp/cloud/aws/iam-policy-for-project-members/