[新機能] AWS Elemental MediaLiveでチャンネル設定をJSONでExport/Importする機能が追加されました!

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

はじめに

清水です。先日東京リージョンでも利用可能になったAWS Elemental MediaLiveですが、新たにチャンネル設定をJSON形式でExport/Inportする機能が追加されました。

これまでも設定済みのテンプレートを利用する、既存チャンネルをCloneするという機能はあったのですが、これでカスタマイズしたチャンネル設定を残しておくこと、また別アカウント/別リージョンにチャンネル設定を移す、ということが容易にできるようになりました。これまで別リージョンで使っていたチャンネル設定を東京リージョンで利用したい、なんてときにとても便利ですね!ナイスタイミングでとてもうれしいアップデードです。本エントリではこのJSONでのExport/Inport機能を実際に試してみたのでまとめてみます。

MediaLiveのチャンネル設定をJSONでExportしてみる

MediaLiveのチャンネル設定をExportするため、まずはオレゴンリージョンでチャンネルを作成してみます。チャンネル設定としては設定済みのテンプレート「Live event」を選択しました。

これをそのままExportしてもおもしろくないので… 出力設定を少しカスタマイズしてみます。まずはABR設定の一番高ビットレート、高解像度の設定になる、Output 1に登録されている「_1080p30」の設定を削除します。

削除すると、このようにOutput 1は2つ目のABR設定だった「_720p30」がOutput 1となります。

ついで、出力設定にHLSの他、Archive出力も追加してみます。以下のように出力先はS3を設定しました。これで[Create channel]ボタンを押下して、チャンネルを作成します。

チャンネル作成後、チャンネル詳細ページに[Create custom template]のボタンがありますね。こちらをダウンロードすると、チャンネル設定がJSONでダウンロードできます。

[チャンネル名].jsonという名称でダウンロードできますね。ダウンロードしてみたJSONはこちらのようになりました。(けっこう長めのJSONです… 500行超)

{
  "name": "MediaLiveChannel0208",
  "id": "XXXXXXX",
  "arn": "arn:aws:medialive:us-west-2:123456789012:channel:XXXXXXX",
  "inputAttachments": [
    {
      "inputId": "XXXXXXX",
      "inputSettings": {
        "networkInputSettings": {
          "serverValidation": "CHECK_CRYPTOGRAPHY_AND_VALIDATE_NAME"
        },
        "sourceEndBehavior": "CONTINUE",
        "inputFilter": "AUTO",
        "filterStrength": 1,
        "deblockFilter": "DISABLED",
        "denoiseFilter": "DISABLED",
        "audioSelectors": [],
        "captionSelectors": [
          {
            "selectorSettings": {
              "embeddedSourceSettings": {
                "source608ChannelNumber": 1,
                "source608TrackNumber": 1,
                "convert608To708": "DISABLED",
                "scte20Detection": "OFF"
              }
            },
            "name": "EmbeddedSelector"
          }
        ]
      }
    }
  ],
  "state": "RUNNING",
  "pipelinesRunningCount": 2,
  "destinations": [
    {
      "id": "destination1",
      "settings": [
        {
          "url": "mediastoressl://XXXXXXXXXXXXXX.data.mediastore.us-west-2.amazonaws.com/live/mystream",
          "username": "",
          "passwordParam": ""
        },
        {
          "url": "mediastoressl://XXXXXXXXXXXXXX.data.mediastore.us-west-2.amazonaws.com/live/mystream",
          "username": "",
          "passwordParam": ""
        }
      ]
    },
    {
      "id": "k805s",
      "settings": [
        {
          "url": "s3ssl://XXXXXXXXXXXXXXXXXXXX/medialive-archive/MediaLiveChannel0208/delivery",
          "username": "",
          "passwordParam": ""
        },
        {
          "url": "s3ssl://XXXXXXXXXXXXXXXXXXXX/medialive-archive/MediaLiveChannel0208/backup",
          "username": "",
          "passwordParam": ""
        }
      ]
    }
  ],
  "egressEndpoints": [
    {
      "sourceIp": "XX.XX.XX.XX"
    },
    {
      "sourceIp": "XX.XX.XX.XX"
    }
  ],
  "encoderSettings": {
    "audioDescriptions": [
      {
        "codecSettings": {
          "aacSettings": {
            "inputType": "NORMAL",
            "bitrate": 128000,
            "codingMode": "CODING_MODE_2_0",
            "rawFormat": "NONE",
            "spec": "MPEG4",
            "profile": "LC",
            "rateControlMode": "CBR",
            "sampleRate": 48000
          }
        },
        "audioTypeControl": "FOLLOW_INPUT",
        "languageCodeControl": "FOLLOW_INPUT",
        "name": "audio_2"
      },
      {
        "codecSettings": {
          "aacSettings": {
            "inputType": "NORMAL",
            "bitrate": 192000,
            "codingMode": "CODING_MODE_2_0",
            "rawFormat": "NONE",
            "spec": "MPEG4",
            "profile": "LC",
            "rateControlMode": "CBR",
            "sampleRate": 48000
          }
        },
        "audioTypeControl": "FOLLOW_INPUT",
        "languageCodeControl": "FOLLOW_INPUT",
        "name": "audio_za9dzo"
      },
      {
        "codecSettings": {
          "aacSettings": {
            "inputType": "NORMAL",
            "bitrate": 192000,
            "codingMode": "CODING_MODE_2_0",
            "rawFormat": "NONE",
            "spec": "MPEG4",
            "profile": "LC",
            "rateControlMode": "CBR",
            "sampleRate": 48000
          }
        },
        "audioTypeControl": "FOLLOW_INPUT",
        "languageCodeControl": "FOLLOW_INPUT",
        "name": "audio_40bxb2"
      },
      {
        "codecSettings": {
          "aacSettings": {
            "inputType": "NORMAL",
            "bitrate": 192000,
            "codingMode": "CODING_MODE_2_0",
            "rawFormat": "NONE",
            "spec": "MPEG4",
            "profile": "LC",
            "rateControlMode": "CBR",
            "sampleRate": 48000
          }
        },
        "audioTypeControl": "FOLLOW_INPUT",
        "languageCodeControl": "FOLLOW_INPUT",
        "name": "audio_n4q6tr"
      }
    ],
    "captionDescriptions": [],
    "outputGroups": [
      {
        "outputGroupSettings": {
          "hlsGroupSettings": {
            "adMarkers": [],
            "captionLanguageSetting": "OMIT",
            "captionLanguageMappings": [],
            "hlsCdnSettings": {
              "hlsWebdavSettings": {
                "numRetries": 10,
                "connectionRetryInterval": 1,
                "restartDelay": 15,
                "filecacheDuration": 300,
                "httpTransferMode": "NON_CHUNKED"
              }
            },
            "inputLossAction": "EMIT_OUTPUT",
            "manifestCompression": "NONE",
            "destination": {
              "destinationRefId": "destination1"
            },
            "ivInManifest": "INCLUDE",
            "ivSource": "FOLLOWS_SEGMENT_NUMBER",
            "clientCache": "ENABLED",
            "tsFileMode": "SEGMENTED_FILES",
            "manifestDurationFormat": "INTEGER",
            "segmentationMode": "USE_SEGMENT_DURATION",
            "outputSelection": "MANIFESTS_AND_SEGMENTS",
            "streamInfResolution": "INCLUDE",
            "indexNSegments": 10,
            "programDateTime": "EXCLUDE",
            "programDateTimePeriod": 600,
            "keepSegments": 21,
            "segmentLength": 6,
            "timedMetadataId3Frame": "PRIV",
            "timedMetadataId3Period": 10,
            "codecSpecification": "RFC_4281",
            "directoryStructure": "SINGLE_DIRECTORY",
            "segmentsPerSubdirectory": 10000,
            "mode": "LIVE"
          }
        },
        "name": "HD",
        "outputs": [
          {
            "outputSettings": {
              "hlsOutputSettings": {
                "nameModifier": "_720p30",
                "hlsSettings": {
                  "standardHlsSettings": {
                    "m3u8Settings": {
                      "audioFramesPerPes": 4,
                      "audioPids": "492-498",
                      "ecmPid": "8182",
                      "pcrControl": "PCR_EVERY_PES_PACKET",
                      "pmtPid": "480",
                      "programNum": 1,
                      "scte35Pid": "500",
                      "scte35Behavior": "NO_PASSTHROUGH",
                      "timedMetadataBehavior": "NO_PASSTHROUGH",
                      "videoPid": "481"
                    },
                    "audioRenditionSets": "PROGRAM_AUDIO"
                  }
                }
              }
            },
            "videoDescriptionName": "video_720p30",
            "audioDescriptionNames": [
              "audio_2"
            ],
            "captionDescriptionNames": []
          },
          {
            "outputSettings": {
              "hlsOutputSettings": {
                "nameModifier": "_480p30",
                "hlsSettings": {
                  "standardHlsSettings": {
                    "m3u8Settings": {
                      "audioFramesPerPes": 4,
                      "audioPids": "492-498",
                      "ecmPid": "8182",
                      "pcrControl": "PCR_EVERY_PES_PACKET",
                      "pmtPid": "480",
                      "programNum": 1,
                      "scte35Pid": "500",
                      "scte35Behavior": "NO_PASSTHROUGH",
                      "timedMetadataBehavior": "NO_PASSTHROUGH",
                      "videoPid": "481"
                    },
                    "audioRenditionSets": "PROGRAM_AUDIO"
                  }
                }
              }
            },
            "videoDescriptionName": "video_480p30",
            "audioDescriptionNames": [
              "audio_za9dzo"
            ],
            "captionDescriptionNames": []
          },
          {
            "outputSettings": {
              "hlsOutputSettings": {
                "nameModifier": "_240p30",
                "hlsSettings": {
                  "standardHlsSettings": {
                    "m3u8Settings": {
                      "audioFramesPerPes": 4,
                      "audioPids": "492-498",
                      "ecmPid": "8182",
                      "pcrControl": "PCR_EVERY_PES_PACKET",
                      "pmtPid": "480",
                      "programNum": 1,
                      "scte35Pid": "500",
                      "scte35Behavior": "NO_PASSTHROUGH",
                      "timedMetadataBehavior": "NO_PASSTHROUGH",
                      "videoPid": "481"
                    },
                    "audioRenditionSets": "PROGRAM_AUDIO"
                  }
                }
              }
            },
            "videoDescriptionName": "video_240p30",
            "audioDescriptionNames": [
              "audio_40bxb2"
            ],
            "captionDescriptionNames": []
          }
        ]
      },
      {
        "outputGroupSettings": {
          "archiveGroupSettings": {
            "destination": {
              "destinationRefId": "k805s"
            },
            "rolloverInterval": 600
          }
        },
        "name": "MediaLiveChannel0208",
        "outputs": [
          {
            "outputSettings": {
              "archiveOutputSettings": {
                "nameModifier": "_1",
                "containerSettings": {
                  "m2tsSettings": {
                    "ccDescriptor": "DISABLED",
                    "ebif": "NONE",
                    "programNum": 1,
                    "patInterval": 100,
                    "pmtInterval": 100,
                    "pcrControl": "PCR_EVERY_PES_PACKET",
                    "pcrPeriod": 40,
                    "timedMetadataBehavior": "NO_PASSTHROUGH",
                    "bufferModel": "MULTIPLEX",
                    "rateMode": "CBR",
                    "audioBufferModel": "ATSC",
                    "audioStreamType": "DVB",
                    "audioFramesPerPes": 2,
                    "segmentationStyle": "MAINTAIN_CADENCE",
                    "segmentationMarkers": "NONE",
                    "ebpPlacement": "VIDEO_AND_AUDIO_PIDS",
                    "ebpAudioInterval": "VIDEO_INTERVAL",
                    "esRateInPes": "EXCLUDE",
                    "arib": "DISABLED",
                    "aribCaptionsPidControl": "AUTO",
                    "absentInputAudioBehavior": "ENCODE_SILENCE",
                    "pmtPid": "480",
                    "videoPid": "481",
                    "audioPids": "482-498",
                    "dvbTeletextPid": "499",
                    "dvbSubPids": "460-479",
                    "scte27Pids": "450-459",
                    "scte35Pid": "500",
                    "scte35Control": "NONE",
                    "klv": "NONE",
                    "klvDataPids": "501",
                    "timedMetadataPid": "502",
                    "etvPlatformPid": "504",
                    "etvSignalPid": "505",
                    "ecmPid": "506",
                    "aribCaptionsPid": "507"
                  }
                }
              }
            },
            "outputName": "fydhcj",
            "videoDescriptionName": "video_pxpv4",
            "audioDescriptionNames": [
              "audio_n4q6tr"
            ],
            "captionDescriptionNames": []
          }
        ]
      }
    ],
    "timecodeConfig": {
      "source": "EMBEDDED"
    },
    "videoDescriptions": [
      {
        "codecSettings": {
          "h264Settings": {
            "afdSignaling": "NONE",
            "colorMetadata": "INSERT",
            "adaptiveQuantization": "HIGH",
            "bitrate": 3000000,
            "entropyEncoding": "CABAC",
            "flickerAq": "ENABLED",
            "framerateControl": "SPECIFIED",
            "framerateNumerator": 30,
            "framerateDenominator": 1,
            "gopBReference": "ENABLED",
            "gopClosedCadence": 1,
            "gopNumBFrames": 3,
            "gopSize": 60,
            "gopSizeUnits": "FRAMES",
            "scanType": "PROGRESSIVE",
            "level": "H264_LEVEL_AUTO",
            "lookAheadRateControl": "HIGH",
            "numRefFrames": 3,
            "parControl": "INITIALIZE_FROM_SOURCE",
            "profile": "HIGH",
            "rateControlMode": "CBR",
            "syntax": "DEFAULT",
            "sceneChangeDetect": "ENABLED",
            "slices": 1,
            "spatialAq": "ENABLED",
            "temporalAq": "ENABLED",
            "timecodeInsertion": "DISABLED"
          }
        },
        "height": 720,
        "name": "video_720p30",
        "respondToAfd": "NONE",
        "sharpness": 100,
        "scalingBehavior": "DEFAULT",
        "width": 1280
      },
      {
        "codecSettings": {
          "h264Settings": {
            "afdSignaling": "NONE",
            "colorMetadata": "INSERT",
            "adaptiveQuantization": "HIGH",
            "bitrate": 1500000,
            "entropyEncoding": "CABAC",
            "flickerAq": "ENABLED",
            "framerateControl": "SPECIFIED",
            "framerateNumerator": 30,
            "framerateDenominator": 1,
            "gopBReference": "ENABLED",
            "gopClosedCadence": 1,
            "gopNumBFrames": 3,
            "gopSize": 60,
            "gopSizeUnits": "FRAMES",
            "scanType": "PROGRESSIVE",
            "level": "H264_LEVEL_AUTO",
            "lookAheadRateControl": "HIGH",
            "numRefFrames": 3,
            "parControl": "SPECIFIED",
            "parNumerator": 4,
            "parDenominator": 3,
            "profile": "MAIN",
            "rateControlMode": "CBR",
            "syntax": "DEFAULT",
            "sceneChangeDetect": "ENABLED",
            "slices": 1,
            "spatialAq": "ENABLED",
            "temporalAq": "ENABLED",
            "timecodeInsertion": "DISABLED"
          }
        },
        "height": 480,
        "name": "video_480p30",
        "respondToAfd": "NONE",
        "sharpness": 100,
        "scalingBehavior": "STRETCH_TO_OUTPUT",
        "width": 640
      },
      {
        "codecSettings": {
          "h264Settings": {
            "afdSignaling": "NONE",
            "colorMetadata": "INSERT",
            "adaptiveQuantization": "HIGH",
            "bitrate": 750000,
            "entropyEncoding": "CABAC",
            "flickerAq": "ENABLED",
            "framerateControl": "SPECIFIED",
            "framerateNumerator": 30,
            "framerateDenominator": 1,
            "gopBReference": "ENABLED",
            "gopClosedCadence": 1,
            "gopNumBFrames": 3,
            "gopSize": 60,
            "gopSizeUnits": "FRAMES",
            "scanType": "PROGRESSIVE",
            "level": "H264_LEVEL_AUTO",
            "lookAheadRateControl": "HIGH",
            "numRefFrames": 3,
            "parControl": "SPECIFIED",
            "parNumerator": 4,
            "parDenominator": 3,
            "profile": "MAIN",
            "rateControlMode": "CBR",
            "syntax": "DEFAULT",
            "sceneChangeDetect": "ENABLED",
            "slices": 1,
            "spatialAq": "ENABLED",
            "temporalAq": "ENABLED",
            "timecodeInsertion": "DISABLED"
          }
        },
        "height": 240,
        "name": "video_240p30",
        "respondToAfd": "NONE",
        "sharpness": 100,
        "scalingBehavior": "STRETCH_TO_OUTPUT",
        "width": 320
      },
      {
        "codecSettings": {
          "h264Settings": {
            "afdSignaling": "NONE",
            "colorMetadata": "INSERT",
            "adaptiveQuantization": "MEDIUM",
            "bitrate": 5000000,
            "entropyEncoding": "CABAC",
            "flickerAq": "ENABLED",
            "framerateControl": "INITIALIZE_FROM_SOURCE",
            "gopBReference": "DISABLED",
            "gopClosedCadence": 1,
            "gopNumBFrames": 2,
            "gopSize": 90,
            "gopSizeUnits": "FRAMES",
            "scanType": "PROGRESSIVE",
            "level": "H264_LEVEL_AUTO",
            "lookAheadRateControl": "MEDIUM",
            "numRefFrames": 1,
            "parControl": "INITIALIZE_FROM_SOURCE",
            "profile": "MAIN",
            "rateControlMode": "CBR",
            "syntax": "DEFAULT",
            "sceneChangeDetect": "ENABLED",
            "spatialAq": "ENABLED",
            "temporalAq": "ENABLED",
            "timecodeInsertion": "DISABLED"
          }
        },
        "name": "video_pxpv4",
        "respondToAfd": "NONE",
        "sharpness": 50,
        "scalingBehavior": "DEFAULT"
      }
    ]
  },
  "roleArn": "arn:aws:iam::123456789012:role/MediaLiveAccessRole",
  "inputSpecification": {
    "codec": "AVC",
    "resolution": "HD",
    "maximumBitrate": "MAX_20_MBPS"
  }
}

MediaLiveのチャンネル設定をJSONからImportしてみる

今度はExportしたJSONを、Importしてみます。せっかくなのでサービスリリースされたばかりの東京リージョンでImportして、新たにチャンネルを作成してみましょう。Create channelページの最下部にある、Channel templateの箇所で[Select custom template]のボタンをクリックし、さきほどダウンロードしたJSONファイルを選択します。

JSONをImportすると、いくつかの項目がJSONに記載された内容で設定済みになります。チャンネル名は「[設定元チャンネル名] - clone」となるようですね。またOutput groupsもImportしたJSONの内容が引き継がれていることがわかります。対して、Inputについては設定されていません。(リージョンやアカウントが違えばJSONに記載のあるInputを使うことはできませんし、また同一リージョンでも既存Inputが使用中であれば重複してアタッチすることはできません。InputについてはJSONをImportした後で自分で設定する、としたほうがよいですね。)

その他確認できた項目として、Output groupsの各項目の出力先については設定がそのまま残っていました。例えばHLS group destinationについてはMediaStoreを設定していましたが、こちらのように。

またArchive設定についても出力先S3バケット、パスが残っていました。

まとめ

AWS Elemental MediaLiveに新しく追加されたチャンネル設定のJSONでのExport/Import機能を使い、チャンネル設定をオレゴンリージョンから東京リージョンに移してみました。MediaLiveでは出力設定なども細く設定できますが、その分同じ設定を複製する、といったことがが手動でやる場合は大変になります。(し、なるべくなら手動ではやりたくないですよね。)MediaLiveの利便性を高めるすてきなアップデートだと思います。引き続きMediaLive含めたAWS Media Servicesの機能アップデートに注目していきたいと思います!