Elemental MediaConvertを利用して動画変換を自動化する

2018.06.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンニチハ、千葉です。

MediaConvertを利用して、mp4をHLSに変換するエントリーを書きました。

Elemental MediaConvertを利用してmp4をHLS変換 + サムネイル出力

今回は、上記で作成したMediaConvertのジョブテンプレートを利用して、S3にファイルをputすると自動で動画変換する仕組みを作ってみます。処理イメージとしては以下です。

  • S3にmp4をアップロード
  • mp4ファイルが置かれたことをトリガーにLambdaを実行(mp4以外はLambdaは発火しない)
  • LambdaからMediaConvertのジョブを作成する
  • mp4がHLSに変換される

やってみた

作業サマリ

  • S3バケット作成
    • アップロード用(mp4ファイル配置)
    • 動画変換用(HLSファイル配置)
  • MediaConvertの設定
  • Lambdaの実装

です。それではやっていきましょう。

S3バケットの作成

S3バケットを作成しましょう。アップロード用、動画変換用2つ作成します。因みに今回2つバケットを用意してますが、バケット1つでも問題ないです。

MediaConvertの設定

これを参考に、ジョブテンプレートを作成します。

Elemental MediaConvertを利用してmp4をHLS変換 + サムネイル出力

Lambdaの実装

S3にmp4ファイルがアップロードされたタイミングで発火させるようにトリガーを設定します。

Lambdaで利用するIAMロールには、追加でMediaConvertのジョブをキックするためのポリシーを追加します。CreateJobに加え、PassRoleも必要でした。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "iam:PassRole",
                "mediaconvert:CreateJob"
            ],
            "Resource": "*"
        }
    ]
}

Lambdaコードのポイントです。(修正箇所をハイライト)

  • eventからアップされたbucket名、keyを取得しMediaConvertにジョブ作成時にインプットとして渡す
  • MediaConverのジョブは、事前に作成したテンプレートを指定している。可変部分(入力ファイル、出力先)のみjsonで指定する。渡せるパラメータについては、手動でMediaConvertのジョブを作成したあとにjsonを確認できるので参考にする。
  • endpoint_urlは、MediaConvertのアカウントから確認できるので、それを指定する
  • create_jobのIAMロールは、こちらを参考に作成する

lambda_function

import json
import urllib.parse
import boto3
import os

print('Loading function')

s3 = boto3.client('s3')
mediaconvert =  boto3.client('mediaconvert', region_name='ap-northeast-1', endpoint_url='https://xxxxxxxx.mediaconvert.ap-northeast-1.amazonaws.com')

def lambda_handler(event, context):
    # Get the object from the event and show its content type
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    inputFile = "s3://" + bucket + "/" + key
    outputKey = "s3://[出力するバケット]/[キー]"

    
    try:
        # Load job.json from disk and store as Python object: job_object
        with open("job.json", "r") as jsonfile:
            job_object = json.load(jsonfile)
            
        # Input/Output Setting
        job_object["OutputGroups"][0]["OutputGroupSettings"]["HlsGroupSettings"]["Destination"] = outputKey
        job_object["OutputGroups"][1]["OutputGroupSettings"]["FileGroupSettings"]["Destination"] = outputKey
        job_object["Inputs"][0]["FileInput"] = inputFile

        # Exec MediaConvert's job
        response = mediaconvert.create_job(
          JobTemplate='arn:aws:mediaconvert:ap-northeast-1:XXXXXXXXXXXX:jobTemplates/[ジョブテンプレート名]',
          Queue='arn:aws:mediaconvert:ap-northeast-1:XXXXXXXXXXXX:queues/Default',
          Role='arn:aws:iam::XXXXXXXXXXXX:role/[ロール名]',
          Settings=job_object
        )
    except Exception as e:
        print(e)
        print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
        raise e

job.json

{
  "OutputGroups": [
    {
        "Name": "Apple HLS",
        "OutputGroupSettings": {
          "Type": "HLS_GROUP_SETTINGS",
          "HlsGroupSettings": {
            "Destination": ""
        }
      }
    },
    {
      "Name": "File Group",
      "OutputGroupSettings": {
        "Type": "FILE_GROUP_SETTINGS",
        "FileGroupSettings": {
          "Destination": ""
        }
      }
    }
  ],
  "Inputs": [
    {
      "FileInput": ""
    }
  ]
}

動作確認

S3へmp4をアップロードしてみます。

mp4へのアップロードをトリガーにMediaConvertのジョブが実行され、HLS形式で動画が出力されていることを確認できました。

最後に

検証時にLambdaのロールにiam:PassRoleが必要だったり、create_jobに指定するテンプレートがよくわからなかったり、はまって苦労しました。はまりつつ、いい感じに仕組みを作れたので大満足です。動画変換基盤としてご利用くださいませ。