🤣

LambdaでS3に上がったMP4をHLSに変換する (動画サイト構築までの道②)

2022/11/20に公開

はじめに

このシリーズでは React を利用して、ストリーミング動画サイトを構築するために必要な動画周りの配信について解説していくシリーズになります

今回は Lambda を利用して S3 に保存されたMP4を自動でHLSに変換する仕組みを作っていきます。

色々記事は世の中にありどれも同じような仕組みでやっていますが、Lambda 上で実行するコードの設定がわかりづらいと感じたので丁寧に説明できればと思います。

過去のシリーズ

環境

VSCode
Ubuntu 20.04 (WSL2)
Docker 20.10.12
docker-compose version v2.2.3
git version 2.25.1

S3 を作成する

AWS コンソールを開いて「S3」と検索して開きます

「バケットを作成」をクリック

バケット名に「hls-handson」と入力して「バケットを作成」をクリック
※S3 のバケット名は各自でユニークなものをつけて以降読み替えてください

作成した「hls-handson」をクリック

「フォルダを作成」をクリック

フォルダ名に「input」と入力して「フォルダの作成」をクリック

同じ要領で「output」というフォルダを作成します
hls-handson に input と output のフォルダができていれば大丈夫です

AWS Elemental MediaConvert の設定

AWS コンソールから「AWS Elemental MediaConvert」を検索して開きます

左メニューから「ジョブテンプレート」をクリック

「テンプレートの作成」をクリック

「名前」に「mp4ToHLS」を入力

左メニューから「入力」の横にある「追加」をクリック
ここで何か設定する必要はありません

左メニューから「出力」の横にある「追加」をクリック

「Apple HLS」を選択して「選択」をクリック

「送信先」の「参照」から「作成したバケット名/input/」を選択します

左メニューから「H264, AAC」をクリック

「名前修飾子」に「_hls」と入力します

「最大ビットレート(ビット/秒)」に「5000000」と入力します

最後に「作成」をクリックします

作成できました

Lambda の設定

今回は Python を利用して Lambda 関数を作ります
関数の中では/inputMP4がアップロードされたら起動して、HLSに変換します

AWS コンソールから「lambda」と検索してひらきます

「関数の作成」をクリック

項目
関数名 hlsConvert
ランタイム Python3.9
実行ロール AWS ポリシーテンプレートから新しいロールを作成
ロール名 hls-handson-lambda-role
ポリシーテンプレート - オプション Amazon S3 オブジェクトの読み込み専用アクセス権

「関数の作成」をクリック

「トリガーを追加」をクリック

項目
トリガー S3 を選択
Bucket 作成したバケット
Prefix input/
Suffix .mp4
Recursive invocation

「追加」をクリック

次に関数を登録します。タブから「コード」をクリック

以下のコードをエディタに貼り付けます

import os
import urllib.parse
import boto3


def lambda_handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')

    settings = make_settings(bucket, key)
    user_metadata = {
        'JobCreatedBy': 'videoConvertSample',
    }

    client = boto3.client('mediaconvert', endpoint_url = "[MediaConvertのAPIエンドポイント]")
    result = client.create_job(
        Role = "arn:aws:iam::[アカウントID]:role/service-role/MediaConvert_Default_Role",
        JobTemplate = "[MediaConvertのテンプレート名: 今回はmp4ToHLS]",
        Settings=settings,
        UserMetadata=user_metadata,
    )

def make_settings(bucket, key):
    basename = os.path.basename(key).split('.')[0]

    return \
    {
        "Inputs": [
            {
                "FileInput": f"s3://{bucket}/{key}",
            }
        ],
        "OutputGroups": [
            {
                "Name": "Apple HLS",
                "OutputGroupSettings": {
                    "Type": "HLS_GROUP_SETTINGS",
                    "HlsGroupSettings": {
                        "Destination": f"s3://{bucket}/output/",
                    },
                },
                "Outputs": [
                    {
                        "VideoDescription": {
                            "Width": 640,
                            "Height": 360,
                        },
                    },
                ],
            },
        ],
    }

コードの 3 箇所を修正します。

  1. MediaConvert の API エンドポイントは MediaConvert の左メニューから「アカウント」をクリックすると表示されます

  1. アカウント ID にはそれぞれのアカウント ID をいれます。注意としてはここで用いるサービスロールは前回のハンズオンで作成したものになります。作成していない場合は MediaConvert のジョブの作成を 1 度行って、「AWS の統合」を設定することで作成できます

  1. MediaConvert で作成したテンプレート名をいれます

私の場合以下のようなコードになりました

import os
import urllib.parse
import boto3


def lambda_handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')

    settings = make_settings(bucket, key)
    user_metadata = {
        'JobCreatedBy': 'videoConvertSample',
    }

    client = boto3.client('mediaconvert', endpoint_url = "https://xxxxxx.mediaconvert.ap-northeast-1.amazonaws.com")
    result = client.create_job(
        Role = "arn:aws:iam::xxxxxxxxxx:role/service-role/MediaConvert_Default_Role",
        JobTemplate = "mp4ToHLS",
        Settings=settings,
        UserMetadata=user_metadata,
    )

def make_settings(bucket, key):
    basename = os.path.basename(key).split('.')[0]

    return \
    {
        "Inputs": [
            {
                "FileInput": f"s3://{bucket}/{key}",
            }
        ],
        "OutputGroups": [
            {
                "Name": "Apple HLS",
                "OutputGroupSettings": {
                    "Type": "HLS_GROUP_SETTINGS",
                    "HlsGroupSettings": {
                        "Destination": f"s3://{bucket}/output/",
                    },
                },
                "Outputs": [
                    {
                        "VideoDescription": {
                            "Width": 640,
                            "Height": 360,
                        },
                    },
                ],
            },
        ],
    }

次に変更を Lambda に反映させるため「Deploy」をクリック

次にタブの「設定」をクリックして左メニューから「アクセス権限」をクリックして「実行ロール」の「ロール名」をクリックします

「許可を追加」→「ポリシーをアタッチ」をクリック

「IAMFullAccess」, 「AWSElementalMediaConvertFullAccess」にチェックをいれて「ポリシーをアタッチ」をクリック

試してみる

「S3」を開いて作成したバケットの「input」ディレクトリを開きます
「アップロード」をクリック

「ファイル追加」から適当な.mp4のファイルを選択します

「アップロード」をクリック

そのあと 30 秒ほど待ってから「output」ディレクトリを開きます

S3 にアップロードされたmp4が自動でhlsに変換されました

おわりに

これである程度動画サイトを作るための用意が終わりました
次回は最後に React を使って簡単な動画アップロードのフォームと仕組みを作成してこのシリーズも終了したいと思います。

参考

https://qiita.com/tacos_salad/items/7a6085c812e98a2dcec3

GitHubで編集を提案

Discussion