家にある動画を再生するのに、いちいちデスクトップパソコンを立ち上げたり、NASっぽいものを構築するのもめんどくさくて
URLを生成してiPhoneとかのブラウザでシュッと見られるようにしたかった。
長い動画を再生するためにストリーミング配信したくて
手持ちのMacやiOS系デバイスで再生するのだと、どうやらHLSが向いてそうだという結論に落ち着いた。
自宅にサーバーを置きたくないので (でかいし、うるさいしで邪魔)
クラウド環境でいろいろやってみることにした。
結果できたのが以下のようなもの。
動画視聴までのワークフロー
- 手元にある動画ファイルをS3にアップロード
- S3にファイルが置かれたのを検知してLambdaを起動
- LambdaでElasticTranscoderにエンコードジョブを作成してアップした動画をエンコード
- エンコードが完了したらファイルをS3に出力
- S3のファイルのURLをSafariで開いて再生
必要な作業は以下の通り
- ElasticTranscoder側の設定 (Pipeline, Preset)
- Lambda Functionの作成
S3のPUTイベントを検知してElasticTranscoderにジョブを投げるLambda Functionを作ります。
基本的には以下の記事を参考に進めました。
ElasticTranscoderの設定
Presetの作成
動画をエンコードする際の設定を決めます。
今回はさほど画質にこだわっていなかったのでデフォルトで用意されている設定を使うことにしました。
1M ~ 1.5MくらいのPresetがHD周辺の解像度でエンコードしてくれたので、そのまま採用しています。
この際、IDというカラムに表示されているPreset IDをメモしておきます。
Pipelineの作成
ElasticTranscoderの作業フローを設定していきます。
S3上のどのBucketにある動画を、どのBucketにエンコードして出力するのかを決めます。
基本的には2つのBucketを用意し、仮にA, BというBucketがあるとすると
Aに動画ファイルをアップロード -> Lamba Functionがジョブを投げる -> ElasticTranscoderがエンコード -> Bにエンコード結果のファイルを保存
という流れになります。
こちらも生成後のPipeline IDをメモしておきましょう。
Lambda Functionの作成
先程のQiitaの記事を参考に、Lambda Functionを作っていきます。
メモしていた2つのIDを変数に埋めてください。
var aws = require('aws-sdk'); var s3 = new aws.S3({apiVersion: '2006-03-01'}); var ets = new aws.ElasticTranscoder({apiVersion: '2012-09-25', region: 'ap-northeast-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 = 'xxxxxxx'; var presetId = 'xxxxxx'; var fileName = key.split('.')[0]; ets.createJob({ PipelineId: pipelineId, OutputKeyPrefix: fileName + '/', Input: { Key: key, FrameRate: 'auto', Resolution: 'auto', AspectRatio: 'auto', Interlaced: 'auto', Container: 'auto', }, Outputs: [ { Key: 'ts-720p', PresetId: presetId, Rotate: 'auto', SegmentDuration: "10" }, ], Playlists: [ { Format: 'HLSv3', Name: 'master', OutputKeys: [ 'ts-720p', ], }, ], }, function(error, data) { if(error) { console.log(error); context.done('error',error); } else { console.log('Job submitted'); context.done(null,''); } }); };
またTriggersも設定します。
今回はS3上の.mp4
というSuffixのファイルのObjectCreatedByPut
とObjectCreatedByCompleteMultipartUpload
イベントを検知して起動するように設定しています。
これでS3に動画がアップされると自動でエンコードが開始されるようになります。
動画の再生
エンコードが完了すると.m3u8
ファイルが2種類と.ts
ファイルが大量にbucket上に生成されます。
.m3u8
ファイルは動画のプレイリストとしてのテキストファイルです。
HLSはAppleが仕様を作っているプロトコルということもあり、Safariであればこの.m3u8
ファイルのURLを開くだけで動画配信が始まります。
S3のPolicyを編集してIP絞るなど
インターネットに広く公開しないような設定をお忘れなく。
所感
ほぼプログラムを書かずにストリーミング配信を実現することができるので非常に楽。
ただElasticTranscoderの料金がバツグンに高いので、気になる方は手元のマシンでffmpeg使うなりしてHLS形式にするところまでやってS3に上げるのがよさそう。
HLSがHTTP/1.1の上で動作するため考えることも少なく、基本的にS3に動画ファイルとプレイリストを置いて静的に配信できれば
あとはプレーヤー側がうまくつなげて再生してくれるため、とても楽にストリーミング再生が実現できます。
またRTMPなどのプロトコルと違い、配信用サーバーを置かずにすんだり
CDNを使うことで容易に配信負荷分散ができるので、そのうち仕事で使う場面もでてきそう。
実際こないだのAbemaTVのカンファレンスでも現場のおもしろい話が聞けたので今後もHLS注目していこうと思います。