[小ネタ]AWS Elemental MediaConvertで手軽に動画を繋げる

手軽過ぎて困惑が止まらない
2020.06.23

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

無性にあんバターが恋しくて仕方ない日々です。


▲ これ、何て呼んでます?

大判焼き派、AWS事業本部のShirotaです。まぁどう呼んだってこれが美味しい事には変わりないと思います。
梅雨時の湿気に気が滅入ってあんこに思いを馳せてしまいましたが、負けずにやっていきましょう。

動画を作っていてこんな事、ありませんか?

「あ!ED動画の差し込みを忘れていた!でも今から動画編集ソフトを立ち上げるの、面倒だなぁ……」

こういった状況に出くわしてしまい、お悩み中の Developers.IO 2020 CONNECT 準備中のクラスメソッド社員の方 はいらっしゃいますか?
勿論、そうでなくても二つの動画を繋げる為に動画編集ソフトを立ち上げるのは面倒だったり、そもそも動画編集ソフトを持っていない場合があると思います。
この状況に打ってつけなAWS Elemental MediaConvert(以下MediaConvert)の機能があるのでお話ししたいと思います。
また、手軽にMediaConvertのジョブを実行できるように今回作成したジョブテンプレートも載せて、そちらの利用方法についても簡単にお話し致します。

今回やる事のおさらい

まず、事前に二本の動画を用意しました。

上記のOP動画と、以下のED動画です。

この二本の動画を、動画編集ソフトを使う事なくMediaConvertのみを利用して 繋げてみたいと思います。

AWS上でやる事としては、

  • S3に合成したい動画をアップロードする
  • (MediaConvertを利用した事が無い場合は)MediaConvert用のIAMロールを作成する
  • MediaConvertのジョブを作成する

の3つになります。
今回は何度も同じジョブを実行する際に少しでも効率良く設定する事ができるようにする為にジョブテンプレートを作成する事にしました。
MediaConvertのジョブテンプレートはジョブ設定時の入力項目の一部を保存する事ができるので、以降同じ設定でジョブを実行したい際に効率良く作業をする事ができます。
また、自身がジョブ実行時に利用している設定を人に伝える際にもMediaConvertにはジョブテンプレートのインポート機能がある為、大変便利です。

入力動画の結合機能(入力ステッチング機能)について

MediaConvertでは、複数動画をインポートした際に動画を結合する入力ステッチング機能があります。

  1. 複数の入力ファイルを 1 つのアセットに結合 (入力ステッチング) するには、別の入力をジョブに追加します。これを行うには、[Job] (ジョブ) ペインの [Inputs] (入力) セクションで [Add] (追加) を選択します。ジョブに複数の入力ファイルがある場合、AWS Elemental MediaConvert はユーザーがジョブで指定した順序で入力を連結することによって出力を作成します。
    ジョブには最大 150 個の入力を含めることができます。

ステップ 1: 入力ファイルを指定する - MediaConvert

こちらについて、実際に弊社 清水の「やってみた」ブログがございますのでジョブの設定等の細かい手順に関しましては以下ブログを参考にして下さい。

今回ですと、ジョブ実行時に「繋げたい動画1」「繋げたい動画2」をそれぞれ「Input 1」「Input 2」に入力する事で、「1+2が繋がった動画」を作成する事ができそうです。

今回作成したジョブテンプレート

まずは、今回作成したジョブテンプレートを載せます。
その後に、このテンプレートで実装している設定と、実際のテンプレートの使い方についてお話ししたいと思います。

{
  "Name": "Devio-connect",
  "Settings": {
    "OutputGroups": [
      {
        "Name": "File Group",
        "Outputs": [
          {
            "ContainerSettings": {
              "Container": "MP4",
              "Mp4Settings": {
                "CslgAtom": "INCLUDE",
                "CttsVersion": 0,
                "FreeSpaceBox": "EXCLUDE",
                "MoovPlacement": "PROGRESSIVE_DOWNLOAD"
              }
            },
            "VideoDescription": {
              "Width": 1920,
              "ScalingBehavior": "DEFAULT",
              "Height": 1080,
              "TimecodeInsertion": "DISABLED",
              "AntiAlias": "ENABLED",
              "Sharpness": 50,
              "CodecSettings": {
                "Codec": "H_264",
                "H264Settings": {
                  "InterlaceMode": "PROGRESSIVE",
                  "ParNumerator": 16,
                  "NumberReferenceFrames": 3,
                  "Syntax": "DEFAULT",
                  "Softness": 0,
                  "FramerateDenominator": 1,
                  "GopClosedCadence": 1,
                  "GopSize": 90,
                  "Slices": 1,
                  "GopBReference": "DISABLED",
                  "SlowPal": "DISABLED",
                  "ParDenominator": 9,
                  "SpatialAdaptiveQuantization": "ENABLED",
                  "TemporalAdaptiveQuantization": "ENABLED",
                  "FlickerAdaptiveQuantization": "DISABLED",
                  "EntropyEncoding": "CABAC",
                  "Bitrate": 8000000,
                  "FramerateControl": "SPECIFIED",
                  "RateControlMode": "CBR",
                  "CodecProfile": "MAIN",
                  "Telecine": "NONE",
                  "FramerateNumerator": 30,
                  "MinIInterval": 0,
                  "AdaptiveQuantization": "HIGH",
                  "CodecLevel": "AUTO",
                  "FieldEncoding": "PAFF",
                  "SceneChangeDetect": "ENABLED",
                  "QualityTuningLevel": "SINGLE_PASS",
                  "FramerateConversionAlgorithm": "DUPLICATE_DROP",
                  "UnregisteredSeiTimecode": "DISABLED",
                  "GopSizeUnits": "FRAMES",
                  "ParControl": "INITIALIZE_FROM_SOURCE",
                  "NumberBFramesBetweenReferenceFrames": 2,
                  "RepeatPps": "DISABLED",
                  "DynamicSubGop": "STATIC"
                }
              },
              "AfdSignaling": "NONE",
              "DropFrameTimecode": "ENABLED",
              "RespondToAfd": "NONE",
              "ColorMetadata": "INSERT"
            },
            "AudioDescriptions": [
              {
                "AudioTypeControl": "FOLLOW_INPUT",
                "CodecSettings": {
                  "Codec": "AAC",
                  "AacSettings": {
                    "AudioDescriptionBroadcasterMix": "NORMAL",
                    "Bitrate": 96000,
                    "RateControlMode": "CBR",
                    "CodecProfile": "LC",
                    "CodingMode": "CODING_MODE_2_0",
                    "RawFormat": "NONE",
                    "SampleRate": 48000,
                    "Specification": "MPEG4"
                  }
                },
                "LanguageCodeControl": "FOLLOW_INPUT"
              }
            ],
            "Extension": ".mp4"
          }
        ],
        "OutputGroupSettings": {
          "Type": "FILE_GROUP_SETTINGS",
          "FileGroupSettings": {}
        }
      }
    ],
    "AdAvailOffset": 0,
    "Inputs": [
      {
        "AudioSelectors": {
          "Audio Selector 1": {
            "Offset": 0,
            "DefaultSelection": "DEFAULT",
            "ProgramSelection": 1
          }
        },
        "VideoSelector": {
          "ColorSpace": "FOLLOW",
          "Rotate": "DEGREE_0",
          "AlphaBehavior": "DISCARD"
        },
        "FilterEnable": "AUTO",
        "PsiControl": "USE_PSI",
        "FilterStrength": 0,
        "DeblockFilter": "DISABLED",
        "DenoiseFilter": "DISABLED",
        "TimecodeSource": "EMBEDDED"
      }
    ]
  },
  "AccelerationSettings": {
    "Mode": "DISABLED"
  },
  "StatusUpdateInterval": "SECONDS_60",
  "Priority": 0,
  "HopDestinations": []
}

今回は、入力された動画を以下のようにして出力するように設定しています。

  • ファイル形式:MP4
  • エンコーダ:H.264
  • アスペクト比:16:9
  • サイズ:1920×1080
  • フレームレート:30fps
  • ビットレート:8Mbps
  • 音声コーデック:AAC-LC
  • チャンネル:ステレオ
  • サンプルレート:48kHz

これは、YouTubeのおすすめエンコード設定に準拠したものです。

アップロードする動画におすすめのエンコード設定 - YouTube ヘルプ

ジョブテンプレートをインポートする

さて、上記のテンプレートを実際に使う際には、MediaConvertにインポートする必要があります。
まずは、上記のjsonをローカルに保存しておいて下さい。
そのファイルをMediaConvertのジョブテンプレート一覧画面から、ジョブテンプレートをインポートします。


▲ ここからインポートする


▲ 先ほど保存したテンプレートを選択

後は、テンプレートの名前をつけて保存すれば完了です。


▲ 後は実際に使うだけ

実際にジョブテンプレートを利用してジョブを作成する

さて、早速作成したジョブテンプレートを利用してジョブを作成してみましょう。


▲ 先ほどの画面からジョブを作成する

上記のようにジョブテンプレートを選択してジョブを作成すると、ジョブテンプレートで設定した内容が反映されたジョブ作成画面に移動します。


▲ 今回は入力したい動画が二つなのでインプットを増やす

後は事前にS3にアップロードしておいた結合したい動画を、順番に気をつけて選択し、アウトプット先のS3の指定、ジョブを実行する際に利用するIAMロールを選択したらジョブを実行するだけです!


▲ まずはOP


▲ 次にED


▲ アウトプット先を指定


▲ IAMロールも指定したらジョブ作成!

ちなみに、ここで利用しているIAMロールで利用しているIAMポリシーは「AWSElementalMediaConvertFullAccess」です。

実際にできたもの

上記のジョブで作成できた動画が以下になります。

無事動画が繋がりました!
折角なので、MediaConvertから出力された動画の情報も確認してみました。


▲ 理想のエンコード設定で出来ている

MediaConvert、使いこなしたい

動画編集ソフトを使う事なく、MediaConvertだけで簡単に2本の動画を繋げて1本の動画を作成する事ができました!
この他にもMediaConvertだけで字幕を入れたり、サムネイル画像を作成することもできる為、簡単な動画編集だったらMediaConvertを利用する事で事が足りてしまう事も多いのではないかと思いました。

今回、弊社では Developers.IO 2020 CONNECT をきっかけに動画作成に携わる機会が出来た人も多いのではないかと思います。
この期に併せてMediaConvertに触ってみる事もオススメしたいなと思い、今回は小ネタブログを書いてみました。

そして、この小ネタが手軽に動画を繋げたい人の助けになれば幸いです。