[AWS Elemental MediaConvert]動画のHLS変換と等間隔でサムネイル画像を生成する方法

データ活用ことはじめ

データ活用ことはじめ

AWS Elemental MediaConvert(以下、MediaConvert)を利用して、以下の処理を実装する機会があったので、その手順をまとめてみました。

  • S3に保存されたMPEG2形式の動画(30FPS)をHLS形式に変換する
  • 動画から0.5秒間隔でサムネイル画像を作成する

1.はじめに

MediaConvertを活用することで、動画の変換処理を数ステップで実行することができます。

PythonのOpenCVライブラリを使用して、指定した間隔でサムネイル画像を作成する方法なども検討しましたが、今回はAWSの動画変換サービスであるMediaConvertを活用して実現する方法を確認しました。

構成図:

MediaConvertをConsoleで操作することもできますが、Lambda関数でMediaConvertのAPIを呼び出す処理を作成し、自動処理に組み込めるようにしました。

さらに、Lambda関数内で動画ファイルに応じてジョブ設定を動的に変更することもできます。(コーデックやビットレート、変換後ファイルの出力先など)

以下が手順の概要です。

  1. ストレージの作成(S3)
  2. アクセス許可の設定(IAM)
  3. ジョブの設定(MediaConvert)
  4. ジョブの作成(Lambda)

次項から、手順に沿って解説します。

2.ストレージの作成(S3)

動画のInput用とOutput用のS3バケットを作成し、Input用バケットに動画ファイルをアップロードしておきます。

3.アクセス許可の設定(IAM)

MediaConvert用とLambda関数用の2つのIAMロールを作成します。

サービス用のIAMロールを作成(AWS CLI)

# MediaConvert用
aws iam create-role --role-name mc-default-role --path /service-role/ --assume-role-policy-document file://mc_trust_policy.json
# Lambda関数用
aws iam create-role --role-name lmd-default-role --path /service-role/ --assume-role-policy-document file://lmd_trust_policy.json

※ロールのARNのパスを/service-role/にするため、–path /service-role/を指定しています。

信頼ポリシー:

「mc-trust_policy.json」

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "mediaconvert.amazonaws.com"            
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

「lmd_trust_policy.json」

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}	

インラインアクセス許可ポリシーの追加(AWS CLI)

# MediaConvert用
aws iam put-role-policy --role-name mc-default-role --policy-name mc-default-policy --policy-document file://mc_inline_policy.json
# Lambda関数用
aws iam put-role-policy --role-name lmd-default-role --policy-name lmd-default-policy --policy-document file://lmd_inline_policy.json

アタッチした許可ポリシー:

  • MediaConvert用:
{
    "Effect": "Allow",
    "Action": [
        "s3:Get*",
        "s3:List*"
    ],
    "Resource": [
        "arn:aws:s3:::video-dev-input/*"
    ]
},
{
    "Effect": "Allow",
    "Action": [
        "s3:Put*"
    ],
    "Resource": [
        "arn:aws:s3:::video-dev-output/*"
    ]
}

Input用のバケットからファイルを読み取る権限(GetおよびListアクション)と、Output用のバケットにファイルを書き込む権限(Putアクション)を付与しています。

  • Lambda関数用
{
    "Action": "logs:CreateLogGroup",
    "Resource": "arn:aws:logs:us-east-1:{account-ID}:*",
    "Effect": "Allow"
},
{
    "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
    ],
    "Resource": "arn:aws:logs:us-east-1:{account-ID}:log-group:*:*",
    "Effect": "Allow"
},
{
    "Action": "iam:PassRole",
    "Resource": "arn:aws:iam::{account-ID}:role/service-role/mc-default-role",
    "Effect": "Allow",
    "Sid": "PassRole"
},
{
    "Action": "mediaconvert:*",
    "Resource": "*",
    "Effect": "Allow",
    "Sid": "MediaConvertService"
}

Lambda関数がロググループを作成し、ログストリームを作成してログイベントを送信できる権限を付与しています。
また、IAMロールの引き渡し(PassRoleアクション)と、MediaConvertサービスの操作権限を付与しています。

4.ジョブの設定(MediaConvert)

API経由でジョブを作成するためのジョブ設定ファイル(JSON)を作成します。
JSONファイルを新規に作成し、MediaConvertのジョブに必要な設定を記述します。

設定内容には、入力ファイル、出力先、コーデックなどが含まれます。
出力先は複数指定することができるため、今回はHLS変換用とサムネイル生成用の2つの出力グループを設定します。

設定内容は、MediaConvertのConsole上でジョブテンプレートを実際に作成し、「JSONを表示」を選択すると、必要な設定内容がJSON形式で表示されます。
この内容を参考にしながら、必要な設定を追加していく方法が簡単です。

次に、2つの出力グループの設定について説明します。

出力グループ:HLS変換用

出力グループの追加で「Apple HLS」を選択します。

  • Apple HLS グループの設定:

・送信先: 事前に作成したOutput用のS3バケットを指定
・セグメントの長さ(秒):任意の長さを秒単位で指定 ※デフォルトは10秒(オプション)

  • 出力/エンコード設定:

・名前修飾子: 変換後のファイル名の末尾に追加される文字列を指定
・ビデオコーデック: 動画ファイルに合わせて指定
・最大ビットレート(ビット/秒): 動画ファイルに合わせて指定

出力グループ:サムネイル生成用

サムネイル用に出力グループをもうひとつ追加します。
「ファイルグループ」を選択します。

サムネイル画像の0.5秒間隔(15フレーム)ごとの取得は、MediaConvertのフレームキャプチャ出力を利用して実現できます。
フレームキャプチャ出力は、ビデオの静止画を作成するために設定した出力です。

今回、HLS変換と合わせて構成しているのは問題ありませんが、フレームキャプチャ出力のみのジョブは対応していないようなので、注意が必要です。

参照:
“フレームキャプチャ出力を持つファイルグループ”.AWS MediaConvert
ユーザーガイド.https://docs.aws.amazon.com/ja_jp/mediaconvert/latest/ug/file-group-with-frame-capture-output.html,(参照2024-03-25).

オーディオは不要なので削除します。

  • 出力設定:

・拡張子: 出力ファイルの拡張子を指定 – ここでは「jpg」を指定
・コンテナ: コンテナ形式での出力は不要のため、「コンテナなし」を選択

  • エンコード設定:

・ビデオコーデック: 「JPEGへのフレームキャプチャ」を指定

・フレームレート: 動画のフレームレートを確認し、フレームキャプチャの間隔を設定
分子にはFPSを、分母にはキャプチャしたいフレーム番号を指定します。
ここでは、30FPSの動画から、15フレームごとに1フレームをJPEGファイルにキャプチャします。

・最大キャプチャ: キャプチャの最大数を指定
今回テスト用に用意したのが30FPSの1分間の動画なので、0.5秒間隔で取得した場合、取得枚数は120枚取得となります。
このため最大キャプチャ数は130としました。

5.ジョブの作成(Lambda)

以下、Lambda関数内でMediaConvertのジョブ設定(JSON)を読み込み、動的に設定するPythonコード例です。

with open("job-settings.json") as json_file:
    mc_data = json.load(json_file)

mc_data["Settings"]["Inputs"][0]["FileInput"] = input_file_path
mc_data["Settings"]["OutputGroups"][0]["OutputGroupSettings"][
    "HlsGroupSettings"]["Destination"] = dest_hls_path
mc_data["Settings"]["OutputGroups"][1]["OutputGroupSettings"][
    "FileGroupSettings"]["Destination"] = dest_thumbs_path

・job-settings.jsonというファイルからMediaConvertのジョブ設定を読み込みます。

・読み込んだ設定に対して、入力ファイルパスや出力先パスなど、動的に変更する必要がある値を設定します。

このように、Lambda関数内で動的な設定を行うことで、柔軟性のあるジョブの実行が可能となります。

以下、Boto3を使用してMediaConvertのクライアントを作成し、ジョブを作成するPythonコード例です。

# client
mc_client = boto3.client("mediaconvert",
                         region_name="us-east-1",
                         endpoint_url=mc_endpoint_url)

# mediaconvert job
response = mc_client.create_job(Role=mediaconvert_role_arn,
                                Settings=mc_data["Settings"])

・boto3.client()を使用してMediaConvertのクライアントを作成します。
region_nameでリージョンを、endpoint_urlでカスタムエンドポイントを指定します。
※エンドポイントのURLはConsoleのMediaConvertの画面から確認できます。

・mc_client.create_job()を使用してMediaConvertでジョブを作成します。
MediaConvertのIAMロールのARNを指定し、Settingsパラメータには動的に設定されたジョブ設定を指定します。

Pythonコード内でMediaConvertのジョブを簡単に作成することができました。

以下のパラメータを使用してLambda関数を実行します。

{
  "file_name": "video1"
}

Lambda関数が実行され、指定されたパラメータを使用してMediaConvertのジョブが作成されました。

ジョブの詳細情報や実行結果は、正常に処理された場合はLambda関数のレスポンスやCloudWatchログから確認できます。

ジョブが完了すると、動画ファイル 「video1」 が処理され、指定した出力先にHLS形式の動画ファイルとサムネイル画像が保存されることを確認できました。

6.ジョブの結果確認について

今回は紹介しませんでしたが、create_jobメソッドではジョブの実行結果を直接確認することができません。
別途ジョブステータス確認用のAPIを実行して、ジョブの成功または失敗に応じて適切な処理を行うフローを入れるのが望ましいです。

例えば、ジョブのステータス確認用のLambda関数と、それを制御するStep Functionsのステートマシンを構築するといったアプローチが有効です。
ステートマシンが、Lambda関数の実行をトリガーし、ジョブのステータスに応じて適切な処理フローに分岐します。
このアプローチにより、ジョブの実行結果を迅速に確認し、必要に応じて適切な対処を行う流れを実現できます。

7.おわりに

AWSの動画変換サービスであるMediaConvertを活用することで、よりスケーラブルで柔軟な動画処理ソリューションを構築することができます。
今回は、MediaConvertを使用して、HLS形式への動画変換と等間隔でのサムネイル画像の生成を実現しました。

実装にあたり、LambdaのIAMロールにiam:PassRoleが必要であったり、create_jobに指定する設定が理解しづらかったりといった課題がありましたが、これらに対処することで、要件を満たす実装が完成しました。

本記事が、動画処理における課題解決や実装の一助となれば幸いです。
システムエグゼでは、今後もAWSのサービスを活用した価値あるソリューションの提供を目指してまいります。
AWSを活用した動画処理に関するご質問やご相談がございましたら、お気軽にお問い合わせください。

※Amazon Web Services、および、かかる資料で使用されるその他のAWS商標は、米国その他の諸国における、Amazon.com, Inc.またはその関連会社の商標です。

BI_banner01.png