Amazon S3、Lambda、Zencoderを利用したトランスコードの自動化

Brightcove Tech Talkへようこそ! テクノロジーにフォーカスしたこの新しいブログでは、動画やソフトウェアのエンジニアリングに関するトピックを扱います。例えば、各種コネクテッドデバイス用に動画を作成し配信するための方法や、ハウツーガイドなどがテーマとなります。初投稿の今回は、Zencoder、Lambda、S3を使用し、わずか数行のコードでトランスコードのワークフローを簡単に自動化する方法についてお話しします。

ウォッチフォルダ(「ドロップフォルダ」や「ホットフォルダ」とも呼ばれます)は、あらゆるファイルベースのワークフローをまとめて自動化する使いやすいツールです。メディアを同じフォーマットにトランスコードする作業を定期的に行う場合は、生のファイルをフォルダにドロップするだけで、トランスコードされたファイルを自動的に作成できます。これは、動画のポストプロダクションのワークフローでクライアントから承認をもらうためのメディアを作成したり、複数の配信用フォーマットを生成したりする場合に、一般的に求められる手順です。

https://lh6.googleusercontent.com/ne1ybtoVXnToktWBjw9lwB9UQ6iR853R66-YJsLj2qGfpTLwf7rAWvh2V3VSnU3Au5yCEFDYv3iYKS8sQopcXrTYn-l1PAo1DRV6xjn1Juo-iwswJv-5vyi9Fk1ykP8gTWIT2pJs

今回の投稿では、Lambdaを用いてリソースを結合する練習を行います。ファイルをS3バケットにドロップすると、Zencoder APIを使ったトランスコードジョブが始まり、結果として生成されたファイルがS3に返されます。この手法を応用し、ワークフロー内の他のステップも自動化することができます。例えば、トランスコードしたファイルで追加的なアクション(プッシュ通知の生成、ファイルのCDNへの移動など)を実行することができます。

あなたが開発者で、AWSについて熟知している場合は、ステップ3のLambda関数までスキップするか、GitHubからコード例を入手し、自ら試行してみてください。

クラウド上でトランスコードする利点

ウォッチフォルダは、Adobe Media EncoderやTelestream、Sorenson Squeezeなどの一般的なエンコーダーでサポートされています。小規模なエンコード作業のためにSorensonやAdobeの製品のライセンスを購入するのは費用効果が高いとは言えない一方、大量のコンテンツがある場合に多数のエンコーディングサーバーを構成し、保守管理する場合は膨大なコストと時間がかかります。

ここで使用するツール(Zencoder、S3、およびLambda)は、使用状況に応じて課金される安価なもので、初期費用も最低料金も不要です。したがって、このウォッチフォルダは、作業規模の大小にかかわらず費用効果が高いと言えます。実際の費用も、S3のストレージで1GBあたり3セント、Zencoderのトランスコード出力1分あたり5セント(量が多い場合は2セント)と明快なため、使用料を見積もるのも簡単です。出力ファイルはS3に書き込まれ、すぐにWeb配信に使用できます。

仕組み

このウォッチフォルダは、Amazon S3バケットの中に存在します。このバケットにファイルをアップロードすると、Lambda関数が起動し、エンコードジョブを作成するリクエストを生成してZencoder APIに送信します。ZencoderはS3からファイルを取得し、これから定義する出力フォーマットにトランスコードした後、トランスコード済みのファイルをS3にドロップして返します。その後は、ファイルをクライアントに配信したり、CloudFrontや別のCDNを介してエンドユーザーに直接届けたりすることもできます。

前提条件

このチュートリアルを実践する場合は、アマゾン ウェブ サービス(AWS)のアカウントZencoderのアカウントが必要です。デモ目的の場合は無料サービス分だけでも十分ですが、利用できるS3ストレージは5GBのみとなり、Zencoderは出力を5秒単位で切り出します。

ステップ1:S3バケットをセットアップ

まずはS3上でウォッチフォルダをセットアップする必要があります。S3バケットをセットアップ済みでない場合は、AWSコンソールにログインし、S3サービスまでナビゲートしてください。次に「Create Bucket」をクリックし、名前を付けます。バケットの名前はサービス全体で一意のものでなければならないため、自分の名前や会社名などの一意のプリフィックスを付けるとよいでしょう。

https://lh6.googleusercontent.com/d4-qZpYiN-An4nDunW66CfH25Zx4ViA49t3neGKQY92Ti1D43Jy2AM8pLC0SZOs873CmnFVElquiYP_KbIevClLadzuWpYIMYSgalIc89O1xoSGDA2yekx_7kUMwxzUm1-iPQyGM

「Region」(地域)は、Zencoderのデフォルトである「US Standard」のままにしておいてください。こうすることで、Zencoderがあなたのファイルを取得するときにS3移行費用が発生するのを防ぎます。他地域のバケットを使う必要がある場合は、Zencoderのジョブに「Region」パラメータを追加し、トランスコードが同じ地域内で実行されるよう設定することでもできます。

S3バケットにフォルダを2個作成します。1個はあなたがファイルをアップロードするフォルダ、もう1個はZencoderがトランスコード済みのファイルをアップロードするフォルダです。ここでは単純に「inputs/」と「outputs/」という名前を使用します。

ステップ2:ZencoderにS3バケットへのアクセス権を付与

あなたのS3バケット内にあるファイルの読み込みと書き込みを行うアクセス権をZencoderに付与する方法は2つあります。最も簡単なのは、ZencoderのIAMユーザーアクセス権を認めるポリシーをS3バケットに追加するやり方です。
S3バケットの「Properties」ペインで、「Permissions」、次に「Add Bucket Policy」の順にクリックします。ここでZencoderのバケットポリシー(Zencoderのドキュメンテーション、またはこちらのGitHubリポジトリから入手可能)を貼り付け、「YOUR-BUCKET」のインスタンスを2つとも、ステップ1で指定した実際のバケットの名前と置き換えます。

https://lh4.googleusercontent.com/yXR6O28MKEkCPxaaKN-AKhbfq9Zb1jLhyfwGBwRc74r5U3tE4vGelhrlwdEKTv_aCeSQ2-gBVrOSb-AmgYbR9po28exYHk1D6A01FyhfMU572Q6KQNJ7Jz9_xiu51wjVtbdeIoeG

Zencoderにあなたのバケットへのアクセス権を付与するもう1つの方法は、AmazonS3FullAccessポリシーを利用して(またはこのバケットに限定して)IAMユーザーを作成し、そのユーザーのAccess Key IDとSecret Access KeyをあなたのZencoderアカウントのCredentialsセクションに追加するやり方です

ステップ3:Lambda関数を作成

https://lh5.googleusercontent.com/kG8puMgEaMaRymy5CpILl4bh-vlop2EeQcm8KsxBGdkgXCancACm_ZZ90tdZrVImfeon6WPDs3gGDGWDCH6JatiRuYZEcpA5ZcNJzPbzo1vNcfAvNElULfwgoYgpFCsHebpSL_O2

AWSコンソールから、Lambdaサービスをクリックします。次に、「Create a Lambda Function」をクリックします(Lambdaを使うのが初めての場合は「Get Started」をクリック)。ブループリントステップをスキップすると、Configure Function画面が表示されます。関数に名前を付け(例えば“transcode Video”など)、ランタイムにPython 2.7を選択します。

コード例をLambda関数のコードセクションに貼り付けます。その際、一番上のグローバル変数を一部編集する必要があります。具体的には、API_KEYをあなたのZencoder Full Access APIキーに設定し、INPUT_FOLDER_NAMEをあなたがS3で作成したウォッチフォルダの名前に、またS3_OUTPUT_BASE_URLを出力ファイルの保存先のバケットおよびフォルダの名前にそれぞれ書き換えます。さらに、NOTIFICATION_EMAILには、Zencoderからの通知を受信したいメールアドレスを設定します(通知を受け取りたくない場合は、Lambda関数の39行目を削除します)。

lambda_function.pyのコードについて少し説明します。基本的に、S3にアップロードされたファイルの名前をもとに出力ファイルの名前を生成することになります。api_dataオブジェクトは、Zencoderに送られるジョブで、ここにすべての出力とエンコーディングパラメータの定義が含まれます。その内容を必要に応じて書き換えることも可能で、ZencoderのRequest Builderではテンプレートがいくつか用意されています。ここからジョブをZencoder APIのエンドポイントに送信し、レスポンスをログに記録します。

次に、見出し「Create New Role」配下の「S3 Execution Role」を選択します。作成画面を表示させるには、ブラウザのポップアップを許可する必要があります。この画面で、新しいロールの名前を入力し、「Allow」をクリックします。このロールは、Lambda関数を実行するパーミッション(権限)スキームを定義します。今回のケースでは、LambdaにS3バケットへのアクセスを許可します。Lambda画面に戻ると、先ほど作成した新しいロールが、「Role」フィールド内で選択されているはずです。

タイムアウトを10秒に延ばします。現実的には、関数の実行に1500ミリ秒以上かかることはほぼありませんが、APIの応答が遅いときに備えて数秒の余裕を与えておくほうが関数のレジリエンスが増します。なお、Lambdaは実行時間100ミリ秒ごとに課金するため、あまり長く設定しないほうがよいでしょう。次に「Next」、さらに「Create Function」の順にクリックします。
「Event Sources」タブで、イベントソースを追加します。「Event source type」では「S3」を、「Bucket」ではステップ1のS3バケットを選択し、「Event type」は「Object Created (All)」に設定します。

https://lh6.googleusercontent.com/zNsc0t_fH8oAHIwkB-uLqOOPi03g4CeldslcH-KnWXVVG7_MxwoirWtQm6b9FzPDuLzzUZAmp-qtnSgrkP1MOC992qNSXnRvPnHdOkLy6gYOiDvUg2wxJTMzZlKwg7wSk9DsFNoq「Prefix」フィールドには、S3バケットで作成したウォッチフォルダの名前を入力します(例:「inputs/」)。こうすることで、バケット内の他のフォルダではなく、ここで指定したフォルダにファイルが追加されたときだけ、Lambda関数が起動するようになります。さらに重要な点として、出力ファイルがエンコーディングジョブのトリガーとなり、これが無限ループで実行され続けるのを防ぎます。最後に、「Enable event source」にチェックを入れて送信します。

以上で終了

これで、ウォッチフォルダ入りのS3バケットと、そのウォッチフォルダからファイル作成イベントを受け取るLambda関数を生成することができました。この関数は、作成されたファイルをトランスコードし、出力フォルダにドロップして返すZencoderジョブを生成します。試しに何らかのメディアをウォッチフォルダにアップロードして、実際の動作を見てみましょう。

トラブルシューティングが必要な場合は、AWS CloudWatchログで、Lambda関数への各コールの詳細をチェックしてください。ZencoderのJobsビューでも、各ジョブと、検出されたエラーの詳細を見ることができます。