[UPDATE] AWS Elemental MediaLiveでワークフローウィザードが利用可能になりました

AWS Elemental MediaLiveでリソース作成がシンプルになるWorkflow Wizardが利用可能になりました。AWS Elemental MediaPackageやAmazon CloudFrontの設定もWizardで完結します!
2021.03.07

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

はじめに

清水です。本日お届けするアップデート情報はこちら!AWS Elemental MediaLiveでワークフローウィザード(Workflow Wizard)が利用可能になりました!(2021/03/05にポストされたアップデート情報になります。)

AWS Elemental MediaLiveを用いてライブストリーミングワークフローを構築しようとした場合、これまではMediaLive自体の各種設定のほか、ライブオリジンとなるAWS Elemental MediaStoreやAWS Elemental MediaPackage、そしてCDNであるAmazon CloudFrontなどそれぞれの設定が個別に必要でした。

今回のアップデートで追加されたワークフローウィザードを使うことで、MediaLive自体の設定がウィザード形式で簡略化されるほか、ワークフローにあわせてMediaStoreやMediaPackage、CloduFrontなどのリソースの設定も行われます。このワークフローウィザードのみで、AWS側のライブストリーミングの準備が完了するかたちですね。内部的にワークフローウィザードはAWS CloudFormationスタックを作成しているとのこと、またワークフロー(スタック)の作成後に、リソースのカスタマイズも可能とのことです。

本エントリではこのAWS Elemental MediaLiveワークフローを使って実際にライブストリーミングワークフローを構築、ライブ配信を行ってみました。これまでの各サービスを個別に設定していく流れよりも、シンプルな手順でライブストリーミングワークフローが構築できるかと思います。

AWS Elemental MediaLiveのWorkflow Wizardを使ってみた

Workflow Wizardを使ってリソースを作成する

それでは実際にMediaLiveのWorkflow Wizardを使ってみます。MediaLiveのマネジメントコンソールに移動し、左側のメニューを確認してみましょう。(表示されていない場合はハンバーガーボタンをクリックします。)[New]の表示とともにWorkflow Wizardの項目がありますね。こちらをクリックしてWorkflow Wizardに進みます。

MediaLive workflowsの一覧画面ですね、まだworkflowは作成していないので表示されるものはありません。右上の[Create workflow]ボタンから進みましょう。

実際にWorkflow Wizardがはじまります。Step 1 「Enter basic details」ではWorkflow nameやMediaLiveのChannel class、そしてIAMロールの設定を行います。Workflow nameはサポートしている文字種を確認して適切に入力します。MediaLive channel classは今回は検証目的なのでSINGLE_PIPELINEとしました。IAMロールは既存のMediaLiveAccessRoleを使用します。

IAMロールについて、これまでMediaLiveを使用したことがないAWSアカウントだったり、MediaLiveAccessRoleが存在しない場合、以下のように「Create role from template」という項目が現れるかと思います。こちらから[Create IAM role]でIAMロールを作成し、作成したIAMロールを使用しましょう。

[Next]ボタンでWizardの次のステップに進みます。Step 2 「Choose a video source」では入力するビデオソースについての設定を行います。今回はinput typeとしてRTMP (push)を選択しました。Inputについても新たに作成します。(既存のものを使うこともできるようですね。)Input destinationsについては使用するStreaming Softwareなども確認し、適切な文字列(Application nameとApplication instance)を入力します。Input security groupは既存のものを選択しましたが、ここも新規に作成することもできるようです。入力ビデオソースのコーデックや解像度についても適切なものを選択します。

[Next]ボタンで次Step 3 「Add video outputs」に進みます。Outputについての設定ですね。Choose outputsの項目をクリックすると、以下5つの項目が現れます。この中から複数の項目が選択できるようです。

今回はMediaPackageを選択しました。またVideo QualityについてはSTANDARD_QUALITYを選択します。MediaPackageを選択することで現れたMediaPackage向けの設定項目では、新規のMediaPackage Channelを作成するか既存のChannelを使うかの選択が行えます。今回は新規にMediaPackage Channelを作成することとしました。Video renditionsについてはデフォルトで選択されているもので進めます。

このVideo renditionsについても、他の項目(解像度の他、NTSC formatのほかPAL format)の追加が行えるようです。

[Next]で進むと、最後のStep 4 「Review and create resources」画面になります。ここで項目をひと通り確認しましょう。エラーなどが表示されていれば、該当箇所に戻って修正を行います。

確認できたら、[Create workflow resources]ボタンを押下します。最後にもう一度、Workflowで作成されるリソースについての確認が表示されます。問題ないことを確認したら、[Create workflow resources]をクリックしましょう。これで実際にWorkflowのリソースの作成が開始されます。

Wizardが完了すると以下のWorkflow詳細画面に遷移します。遷移直後はいずれのリソースも作成前となりますが、順次作成がはじまっていきます。

5分ほど経つと、WorkflowのstateがCreate completeとなり、すべてのリソースの作成が完了します。

「Link to resource」のリンクから各リソースの詳細が確認できるほか、画面上部にも記載があるようにCloudFormationスタックも確認できます。

Templateも表示されます。インデントのないJSON形式ですが、jqコマンドでフォーマットするといい感じに読めそうでした。(参考として、整形したTemplateを本エントリ末尾に記載します。)

WorkflowをStartしてライブ配信してみる

Workflow Wizardを使って、MediaLiveならびにMediaPackage、CloudFrontのリソースが作成されました。それではWorfklowをStartさせて、実際にライブ配信を行ってみます。

Workflowの詳細ページ、[Start workflow]ボタンででワークフローをStartさせます。

実際にはこのWorkflowに関連するMediaLiveのChannelがStartしますが、Workflow一覧画面で確認できるのはメリットですね。

Streaming SoftwareにRTMP PUSHのエンドポイントを入力して映像の打ち上げを開始します。このエンドポイントの情報はMediaLiveのInput画面から確認しました。Workflowの該当リソースの「Link to resource」のリンクから飛ぶと参照しやすいかと思います。

映像打ち上げ後、HLSのEndpoint URLを参照して再生を確認します。このURLはMediaPackageのEndpoint画面からCloudFront URLの項目を確認します。こちらもWorkflowの該当リソース(ここではMediaPackage HLS endpoint)の「Link to resource」のリンクから飛ぶと参照しやすいかと思います。

再生プレイヤーはVideoJS HTTP Streaming (VHS)のデモページを使用しました。Video URLに先ほどのMediaPackage HLS endpointのCloudFront URLを入力、Mime Typeがapplication/x-mpegURLであることを確認して[Load]して再生ボタンをクリックします。ライブ配信ができました!

まとめ

AWS Elemental MediaLiveの新機能、Workflow Wizardを使ってライブ配信に必要なリソースを作成、ライブ配信が行えることを確認してみました。Wizardに従っていくことで、MediaLiveのリソースがこれまでよりもだいぶシンプルに作成できるかと思います。またAWS Elemental MediaPackageやAmazon CloudFrontなどライブ配信に実際に必要なリソースの作成、設定も行えるのも嬉しいですね。これらのリソースがWorkflow画面で一覧できるのもポイントかと思います。またWorkflow作成後の画面にもありましたが、Media Services Application Mapper (MSAM)を用いてのリソースモニタリングとも相性が良さそうかなと思います。(リソースにMSAMなタグも付与されていますね。)Workflow Wizardで作成されたリソースに対する変更もできるようなので、これを元に独自のカスタマイズを加えていくこともできそうですね。

おまけ

今回の作成したWorkflowのCloudFromation Stack、そのTemplateをjqコマンドで整形したものをまとめておきます。

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Media Services Workflow created by MediaLive",
  "Resources": {
    "MediaLiveInput": {
      "Type": "AWS::MediaLive::Input",
      "Properties": {
        "Name": "blog-workflow-Input",
        "Type": "RTMP_PUSH",
        "Tags": {
          "MSAM-Diagram": "blog-workflow",
          "MSAM-Tile": "blog-workflow",
          "MediaLive-Workflow": "blog-workflow"
        },
        "Destinations": [
          {
            "StreamName": "appname/appinst"
          }
        ],
        "InputSecurityGroups": [
          "1234567"
        ]
      },
      "DependsOn": []
    },
    "MediaPackageChannel": {
      "Type": "AWS::MediaPackage::Channel",
      "Properties": {
        "Description": "Channel created by MediaLive workflow - blog-workflow",
        "Id": "blog-workflow",
        "Tags": [
          {
            "Key": "MSAM-Diagram",
            "Value": "blog-workflow"
          },
          {
            "Key": "MSAM-Tile",
            "Value": "blog-workflow"
          },
          {
            "Key": "MediaLive-Workflow",
            "Value": "blog-workflow"
          }
        ]
      }
    },
    "MediaPackageHLSEndpoint": {
      "Type": "AWS::MediaPackage::OriginEndpoint",
      "Properties": {
        "Id": "blog-workflowHLSEndpoint",
        "ChannelId": "blog-workflow",
        "Description": "HLS endpoint created by MediaLive for channel blog-workflow",
        "ManifestName": "index",
        "StartoverWindowSeconds": 0,
        "TimeDelaySeconds": 0,
        "HlsPackage": {
          "AdMarkers": "NONE",
          "AdsOnDeliveryRestrictions": "RESTRICTED",
          "AdTriggers": [
            "SPLICE_INSERT",
            "PROVIDER_ADVERTISEMENT",
            "DISTRIBUTOR_ADVERTISEMENT",
            "PROVIDER_PLACEMENT_OPPORTUNITY",
            "DISTRIBUTOR_PLACEMENT_OPPORTUNITY"
          ],
          "IncludeIframeOnlyStream": false,
          "PlaylistType": "EVENT",
          "PlaylistWindowSeconds": 60,
          "ProgramDateTimeIntervalSeconds": 0,
          "SegmentDurationSeconds": 6,
          "StreamSelection": {
            "StreamOrder": "ORIGINAL"
          },
          "UseAudioRenditionGroup": false
        },
        "Origination": "ALLOW",
        "Tags": [
          {
            "Key": "MSAM-Diagram",
            "Value": "blog-workflow"
          },
          {
            "Key": "MSAM-Tile",
            "Value": "blog-workflow"
          },
          {
            "Key": "MediaLive-Workflow",
            "Value": "blog-workflow"
          }
        ]
      },
      "DependsOn": "MediaPackageChannel"
    },
    "MediaPackageCMAFEndpoint": {
      "Type": "AWS::MediaPackage::OriginEndpoint",
      "Properties": {
        "Id": "blog-workflowCMAFEndpoint",
        "ChannelId": "blog-workflow",
        "Description": "CMAF endpoint created by MediaLive for channel blog-workflow",
        "ManifestName": "index",
        "StartoverWindowSeconds": 0,
        "TimeDelaySeconds": 0,
        "CmafPackage": {
          "SegmentDurationSeconds": 2,
          "SegmentPrefix": "2",
          "HlsManifests": [
            {
              "Id": "CMAF_HLS",
              "PlaylistWindowSeconds": 60,
              "PlaylistType": "EVENT",
              "AdMarkers": "NONE",
              "AdTriggers": [
                "SPLICE_INSERT",
                "PROVIDER_ADVERTISEMENT",
                "DISTRIBUTOR_ADVERTISEMENT",
                "PROVIDER_PLACEMENT_OPPORTUNITY",
                "DISTRIBUTOR_PLACEMENT_OPPORTUNITY"
              ],
              "AdsOnDeliveryRestrictions": "RESTRICTED",
              "IncludeIframeOnlyStream": false
            }
          ],
          "StreamSelection": {
            "StreamOrder": "ORIGINAL"
          }
        },
        "Origination": "ALLOW",
        "Tags": [
          {
            "Key": "MSAM-Diagram",
            "Value": "blog-workflow"
          },
          {
            "Key": "MSAM-Tile",
            "Value": "blog-workflow"
          },
          {
            "Key": "MediaLive-Workflow",
            "Value": "blog-workflow"
          }
        ]
      },
      "DependsOn": "MediaPackageChannel"
    },
    "MediaPackageDASHEndpoint": {
      "Type": "AWS::MediaPackage::OriginEndpoint",
      "Properties": {
        "Id": "blog-workflowDASHEndpoint",
        "ChannelId": "blog-workflow",
        "Description": "DASH endpoint created by MediaLive for channel blog-workflow",
        "ManifestName": "index",
        "StartoverWindowSeconds": 0,
        "TimeDelaySeconds": 0,
        "DashPackage": {
          "SegmentDurationSeconds": 2,
          "ManifestWindowSeconds": 60,
          "Profile": "NONE",
          "MinUpdatePeriodSeconds": 15,
          "MinBufferTimeSeconds": 30,
          "SuggestedPresentationDelaySeconds": 25,
          "PeriodTriggers": [],
          "ManifestLayout": "FULL",
          "SegmentTemplateFormat": "NUMBER_WITH_TIMELINE",
          "AdTriggers": [
            "SPLICE_INSERT",
            "PROVIDER_ADVERTISEMENT",
            "DISTRIBUTOR_ADVERTISEMENT",
            "PROVIDER_PLACEMENT_OPPORTUNITY",
            "DISTRIBUTOR_PLACEMENT_OPPORTUNITY"
          ],
          "AdsOnDeliveryRestrictions": "RESTRICTED",
          "StreamSelection": {
            "StreamOrder": "ORIGINAL"
          }
        },
        "Origination": "ALLOW",
        "Tags": [
          {
            "Key": "MSAM-Diagram",
            "Value": "blog-workflow"
          },
          {
            "Key": "MSAM-Tile",
            "Value": "blog-workflow"
          },
          {
            "Key": "MediaLive-Workflow",
            "Value": "blog-workflow"
          }
        ]
      },
      "DependsOn": "MediaPackageChannel"
    },
    "MediaPackageCloudFrontDistribution": {
      "Type": "AWS::CloudFront::Distribution",
      "Properties": {
        "DistributionConfig": {
          "Enabled": true,
          "Comment": "Created by MediaLive workflow blog-workflow",
          "CustomErrorResponses": [
            {
              "ErrorCode": 400,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 403,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 404,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 405,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 414,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 416,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 500,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 501,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 502,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 503,
              "ErrorCachingMinTTL": 1
            },
            {
              "ErrorCode": 504,
              "ErrorCachingMinTTL": 1
            }
          ],
          "DefaultCacheBehavior": {
            "TargetOriginId": "EMP-blog-workflow",
            "AllowedMethods": [
              "GET",
              "HEAD"
            ],
            "CachedMethods": [
              "GET",
              "HEAD"
            ],
            "Compress": false,
            "ForwardedValues": {
              "QueryString": true,
              "QueryStringCacheKeys": [
                "m",
                "start",
                "end"
              ]
            },
            "SmoothStreaming": false,
            "ViewerProtocolPolicy": "redirect-to-https",
            "MinTTL": 0,
            "DefaultTTL": 86400,
            "MaxTTL": 31536000
          },
          "Origins": [
            {
              "Id": "EMP-blog-workflow",
              "DomainName": {
                "Fn::Select": [
                  0,
                  {
                    "Fn::Split": [
                      "/",
                      {
                        "Fn::Select": [
                          1,
                          {
                            "Fn::Split": [
                              "https://",
                              {
                                "Fn::GetAtt": [
                                  "MediaPackageHLSEndpoint",
                                  "Url"
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ]
              },
              "OriginPath": "",
              "CustomOriginConfig": {
                "HTTPPort": 80,
                "HTTPSPort": 443,
                "OriginProtocolPolicy": "match-viewer",
                "OriginSSLProtocols": [
                  "TLSv1",
                  "TLSv1.1",
                  "TLSv1.2"
                ],
                "OriginReadTimeout": 30,
                "OriginKeepaliveTimeout": 5
              }
            }
          ],
          "PriceClass": "PriceClass_All"
        },
        "Tags": [
          {
            "Key": "mediapackage:cloudfront_assoc",
            "Value": {
              "Fn::GetAtt": [
                "MediaPackageChannel",
                "Arn"
              ]
            }
          },
          {
            "Key": "MSAM-Diagram",
            "Value": "blog-workflow"
          },
          {
            "Key": "MSAM-Tile",
            "Value": "blog-workflow"
          },
          {
            "Key": "MediaLive-Workflow",
            "Value": "blog-workflow"
          }
        ]
      },
      "DependsOn": [
        "MediaPackageHLSEndpoint",
        "MediaPackageCMAFEndpoint",
        "MediaPackageDASHEndpoint"
      ]
    },
    "MediaLiveChannel": {
      "Type": "AWS::MediaLive::Channel",
      "Properties": {
        "Name": "blog-workflow",
        "ChannelClass": "SINGLE_PIPELINE",
        "LogLevel": "DISABLED",
        "RoleArn": "arn:aws:iam::123456789012:role/MediaLiveAccessRole",
        "InputAttachments": [
          {
            "InputAttachmentName": "blog-workflow",
            "InputId": {
              "Ref": "MediaLiveInput"
            },
            "InputSettings": {
              "AudioSelectors": [],
              "CaptionSelectors": [],
              "DeblockFilter": "DISABLED",
              "DenoiseFilter": "DISABLED",
              "FilterStrength": 1,
              "InputFilter": "AUTO",
              "Smpte2038DataPreference": "IGNORE",
              "SourceEndBehavior": "CONTINUE"
            }
          }
        ],
        "InputSpecification": {
          "Codec": "AVC",
          "MaximumBitrate": "MAX_20_MBPS",
          "Resolution": "HD"
        },
        "Destinations": [
          {
            "Id": "mediapackage-destination",
            "MediaPackageSettings": [
              {
                "ChannelId": "blog-workflow"
              }
            ]
          }
        ],
        "EncoderSettings": {
          "AudioDescriptions": [
            {
              "Name": "audio_mediapackage_0",
              "AudioSelectorName": "Default",
              "AudioTypeControl": "FOLLOW_INPUT",
              "LanguageCodeControl": "FOLLOW_INPUT",
              "CodecSettings": {
                "AacSettings": {
                  "InputType": "NORMAL",
                  "Bitrate": 128000,
                  "CodingMode": "CODING_MODE_2_0",
                  "RawFormat": "NONE",
                  "Spec": "MPEG4",
                  "Profile": "LC",
                  "RateControlMode": "CBR",
                  "SampleRate": 48000
                }
              }
            },
            {
              "Name": "audio_mediapackage_1",
              "AudioSelectorName": "Default",
              "AudioTypeControl": "FOLLOW_INPUT",
              "LanguageCodeControl": "FOLLOW_INPUT",
              "CodecSettings": {
                "AacSettings": {
                  "InputType": "NORMAL",
                  "Bitrate": 128000,
                  "CodingMode": "CODING_MODE_2_0",
                  "RawFormat": "NONE",
                  "Spec": "MPEG4",
                  "Profile": "LC",
                  "RateControlMode": "CBR",
                  "SampleRate": 48000
                }
              }
            },
            {
              "Name": "audio_mediapackage_2",
              "AudioSelectorName": "Default",
              "AudioTypeControl": "FOLLOW_INPUT",
              "LanguageCodeControl": "FOLLOW_INPUT",
              "CodecSettings": {
                "AacSettings": {
                  "InputType": "NORMAL",
                  "Bitrate": 128000,
                  "CodingMode": "CODING_MODE_2_0",
                  "RawFormat": "NONE",
                  "Spec": "MPEG4",
                  "Profile": "LC",
                  "RateControlMode": "CBR",
                  "SampleRate": 48000
                }
              }
            },
            {
              "Name": "audio_mediapackage_3",
              "AudioSelectorName": "Default",
              "AudioTypeControl": "FOLLOW_INPUT",
              "LanguageCodeControl": "FOLLOW_INPUT",
              "CodecSettings": {
                "AacSettings": {
                  "InputType": "NORMAL",
                  "Bitrate": 128000,
                  "CodingMode": "CODING_MODE_2_0",
                  "RawFormat": "NONE",
                  "Spec": "MPEG4",
                  "Profile": "LC",
                  "RateControlMode": "CBR",
                  "SampleRate": 48000
                }
              }
            }
          ],
          "CaptionDescriptions": [],
          "OutputGroups": [
            {
              "Name": "mediapackage",
              "OutputGroupSettings": {
                "MediaPackageGroupSettings": {
                  "Destination": {
                    "DestinationRefId": "mediapackage-destination"
                  }
                }
              },
              "Outputs": [
                {
                  "OutputName": "emp_720p60",
                  "VideoDescriptionName": "emp_720p60",
                  "AudioDescriptionNames": [
                    "audio_mediapackage_0"
                  ],
                  "CaptionDescriptionNames": [],
                  "OutputSettings": {
                    "MediaPackageOutputSettings": {}
                  }
                },
                {
                  "OutputName": "emp_720p30",
                  "VideoDescriptionName": "emp_720p30",
                  "AudioDescriptionNames": [
                    "audio_mediapackage_1"
                  ],
                  "CaptionDescriptionNames": [],
                  "OutputSettings": {
                    "MediaPackageOutputSettings": {}
                  }
                },
                {
                  "OutputName": "emp_480p30",
                  "VideoDescriptionName": "emp_480p30",
                  "AudioDescriptionNames": [
                    "audio_mediapackage_2"
                  ],
                  "CaptionDescriptionNames": [],
                  "OutputSettings": {
                    "MediaPackageOutputSettings": {}
                  }
                },
                {
                  "OutputName": "emp_240p30",
                  "VideoDescriptionName": "emp_240p30",
                  "AudioDescriptionNames": [
                    "audio_mediapackage_3"
                  ],
                  "CaptionDescriptionNames": [],
                  "OutputSettings": {
                    "MediaPackageOutputSettings": {}
                  }
                }
              ]
            }
          ],
          "TimecodeConfig": {
            "Source": "EMBEDDED"
          },
          "VideoDescriptions": [
            {
              "CodecSettings": {
                "H264Settings": {
                  "AfdSignaling": "NONE",
                  "ColorMetadata": "INSERT",
                  "AdaptiveQuantization": "HIGH",
                  "EntropyEncoding": "CABAC",
                  "FlickerAq": "DISABLED",
                  "ForceFieldPictures": "DISABLED",
                  "FramerateControl": "SPECIFIED",
                  "FramerateNumerator": 60000,
                  "FramerateDenominator": 1001,
                  "GopBReference": "DISABLED",
                  "GopClosedCadence": 1,
                  "GopNumBFrames": 3,
                  "GopSize": 120,
                  "GopSizeUnits": "FRAMES",
                  "SubgopLength": "DYNAMIC",
                  "ScanType": "PROGRESSIVE",
                  "Level": "H264_LEVEL_AUTO",
                  "LookAheadRateControl": "HIGH",
                  "MaxBitrate": 5000000,
                  "NumRefFrames": 3,
                  "ParControl": "SPECIFIED",
                  "ParNumerator": 1,
                  "ParDenominator": 1,
                  "Profile": "HIGH",
                  "QvbrQualityLevel": 8,
                  "RateControlMode": "QVBR",
                  "Syntax": "DEFAULT",
                  "SceneChangeDetect": "ENABLED",
                  "Slices": 1,
                  "SpatialAq": "ENABLED",
                  "TemporalAq": "ENABLED",
                  "TimecodeInsertion": "DISABLED"
                }
              },
              "Height": 720,
              "Name": "emp_720p60",
              "RespondToAfd": "NONE",
              "Sharpness": 75,
              "ScalingBehavior": "DEFAULT",
              "Width": 1280
            },
            {
              "CodecSettings": {
                "H264Settings": {
                  "AfdSignaling": "NONE",
                  "ColorMetadata": "INSERT",
                  "AdaptiveQuantization": "HIGH",
                  "EntropyEncoding": "CABAC",
                  "FlickerAq": "DISABLED",
                  "ForceFieldPictures": "DISABLED",
                  "FramerateControl": "SPECIFIED",
                  "FramerateNumerator": 30000,
                  "FramerateDenominator": 1001,
                  "GopBReference": "DISABLED",
                  "GopClosedCadence": 1,
                  "GopNumBFrames": 3,
                  "GopSize": 60,
                  "GopSizeUnits": "FRAMES",
                  "SubgopLength": "DYNAMIC",
                  "ScanType": "PROGRESSIVE",
                  "Level": "H264_LEVEL_AUTO",
                  "LookAheadRateControl": "HIGH",
                  "MaxBitrate": 3000000,
                  "NumRefFrames": 3,
                  "ParControl": "SPECIFIED",
                  "ParNumerator": 1,
                  "ParDenominator": 1,
                  "Profile": "HIGH",
                  "QvbrQualityLevel": 8,
                  "RateControlMode": "QVBR",
                  "Syntax": "DEFAULT",
                  "SceneChangeDetect": "ENABLED",
                  "Slices": 1,
                  "SpatialAq": "ENABLED",
                  "TemporalAq": "ENABLED",
                  "TimecodeInsertion": "DISABLED"
                }
              },
              "Height": 720,
              "Name": "emp_720p30",
              "RespondToAfd": "NONE",
              "Sharpness": 75,
              "ScalingBehavior": "DEFAULT",
              "Width": 1280
            },
            {
              "CodecSettings": {
                "H264Settings": {
                  "AfdSignaling": "NONE",
                  "ColorMetadata": "INSERT",
                  "AdaptiveQuantization": "HIGH",
                  "EntropyEncoding": "CABAC",
                  "FlickerAq": "DISABLED",
                  "ForceFieldPictures": "DISABLED",
                  "FramerateControl": "SPECIFIED",
                  "FramerateNumerator": 30000,
                  "FramerateDenominator": 1001,
                  "GopBReference": "ENABLED",
                  "GopClosedCadence": 1,
                  "GopNumBFrames": 3,
                  "GopSize": 60,
                  "GopSizeUnits": "FRAMES",
                  "SubgopLength": "DYNAMIC",
                  "ScanType": "PROGRESSIVE",
                  "Level": "H264_LEVEL_AUTO",
                  "LookAheadRateControl": "HIGH",
                  "MaxBitrate": 1500000,
                  "NumRefFrames": 3,
                  "ParControl": "SPECIFIED",
                  "ParNumerator": 1,
                  "ParDenominator": 1,
                  "Profile": "MAIN",
                  "QvbrQualityLevel": 8,
                  "RateControlMode": "QVBR",
                  "Syntax": "DEFAULT",
                  "SceneChangeDetect": "ENABLED",
                  "Slices": 1,
                  "SpatialAq": "ENABLED",
                  "TemporalAq": "ENABLED",
                  "TimecodeInsertion": "DISABLED"
                }
              },
              "Height": 480,
              "Name": "emp_480p30",
              "RespondToAfd": "NONE",
              "Sharpness": 100,
              "ScalingBehavior": "STRETCH_TO_OUTPUT",
              "Width": 854
            },
            {
              "CodecSettings": {
                "H264Settings": {
                  "AfdSignaling": "NONE",
                  "ColorMetadata": "INSERT",
                  "AdaptiveQuantization": "HIGH",
                  "EntropyEncoding": "CABAC",
                  "FlickerAq": "DISABLED",
                  "ForceFieldPictures": "DISABLED",
                  "FramerateControl": "SPECIFIED",
                  "FramerateNumerator": 30000,
                  "FramerateDenominator": 1001,
                  "GopBReference": "ENABLED",
                  "GopClosedCadence": 1,
                  "GopNumBFrames": 3,
                  "GopSize": 60,
                  "GopSizeUnits": "FRAMES",
                  "SubgopLength": "DYNAMIC",
                  "ScanType": "PROGRESSIVE",
                  "Level": "H264_LEVEL_AUTO",
                  "LookAheadRateControl": "HIGH",
                  "MaxBitrate": 750000,
                  "NumRefFrames": 3,
                  "ParControl": "SPECIFIED",
                  "ParNumerator": 1,
                  "ParDenominator": 1,
                  "Profile": "MAIN",
                  "QvbrQualityLevel": 8,
                  "RateControlMode": "QVBR",
                  "Syntax": "DEFAULT",
                  "SceneChangeDetect": "ENABLED",
                  "Slices": 1,
                  "SpatialAq": "ENABLED",
                  "TemporalAq": "ENABLED",
                  "TimecodeInsertion": "DISABLED"
                }
              },
              "Height": 240,
              "Name": "emp_240p30",
              "RespondToAfd": "NONE",
              "Sharpness": 100,
              "ScalingBehavior": "STRETCH_TO_OUTPUT",
              "Width": 426
            }
          ]
        },
        "Tags": {
          "MSAM-Diagram": "blog-workflow",
          "MSAM-Tile": "blog-workflow",
          "MediaLive-Workflow": "blog-workflow"
        }
      },
      "DependsOn": [
        "MediaLiveInput",
        "MediaPackageChannel",
        "MediaPackageHLSEndpoint",
        "MediaPackageCMAFEndpoint",
        "MediaPackageDASHEndpoint"
      ]
    }
  }
}