この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、大前です。
最近 CDK への入門がてら MediaLive を CDK で作っていたりするのですが、MediaLive はパラメータ数が膨大でなかなか大変です。
そこで、MediaLive のカスタムテンプレートのダウンロード機能を利用し、CDK で MediaLive を構築するためのソースコードをちょっと楽して作ってみました。今回は CDK を例に挙げていますが、CloudFormation などでも活用できるかと思います。
MediaLive のパラメータの多さに心挫ける
MediaLive を構成する要素は Input
、InputSecurityGroup
、Channel
の 3つですが、このうち Channel
のパラメータ数が膨大で、「MediaLive もいっちょ IaC しちゃいますか〜〜」とか思いながらドキュメントを覗くと心を打ち砕かれます。以下に CDK の公式ドキュメントに乗っている MediaLive Channel 作成のサンプルコードを載せておきます。開いてみるとこの気持ちが伝わると思います。
Example - class CfnChannel (construct)
// The code below shows an example of how to instantiate this type.
// The values are placeholders you should change.
import { aws_medialive as medialive } from 'aws-cdk-lib';
declare const tags: any;
const cfnChannel = new medialive.CfnChannel(this, 'MyCfnChannel', /* all optional props */ {
cdiInputSpecification: {
resolution: 'resolution',
},
channelClass: 'channelClass',
destinations: [{
id: 'id',
mediaPackageSettings: [{
channelId: 'channelId',
}],
multiplexSettings: {
multiplexId: 'multiplexId',
programName: 'programName',
},
settings: [{
passwordParam: 'passwordParam',
streamName: 'streamName',
url: 'url',
username: 'username',
}],
}],
encoderSettings: {
audioDescriptions: [{
audioNormalizationSettings: {
algorithm: 'algorithm',
algorithmControl: 'algorithmControl',
targetLkfs: 123,
},
audioSelectorName: 'audioSelectorName',
audioType: 'audioType',
audioTypeControl: 'audioTypeControl',
audioWatermarkingSettings: {
nielsenWatermarksSettings: {
nielsenCbetSettings: {
cbetCheckDigitString: 'cbetCheckDigitString',
cbetStepaside: 'cbetStepaside',
csid: 'csid',
},
nielsenDistributionType: 'nielsenDistributionType',
nielsenNaesIiNwSettings: {
checkDigitString: 'checkDigitString',
sid: 123,
},
},
},
codecSettings: {
aacSettings: {
bitrate: 123,
codingMode: 'codingMode',
inputType: 'inputType',
profile: 'profile',
rateControlMode: 'rateControlMode',
rawFormat: 'rawFormat',
sampleRate: 123,
spec: 'spec',
vbrQuality: 'vbrQuality',
},
ac3Settings: {
bitrate: 123,
bitstreamMode: 'bitstreamMode',
codingMode: 'codingMode',
dialnorm: 123,
drcProfile: 'drcProfile',
lfeFilter: 'lfeFilter',
metadataControl: 'metadataControl',
},
eac3Settings: {
attenuationControl: 'attenuationControl',
bitrate: 123,
bitstreamMode: 'bitstreamMode',
codingMode: 'codingMode',
dcFilter: 'dcFilter',
dialnorm: 123,
drcLine: 'drcLine',
drcRf: 'drcRf',
lfeControl: 'lfeControl',
lfeFilter: 'lfeFilter',
loRoCenterMixLevel: 123,
loRoSurroundMixLevel: 123,
ltRtCenterMixLevel: 123,
ltRtSurroundMixLevel: 123,
metadataControl: 'metadataControl',
passthroughControl: 'passthroughControl',
phaseControl: 'phaseControl',
stereoDownmix: 'stereoDownmix',
surroundExMode: 'surroundExMode',
surroundMode: 'surroundMode',
},
mp2Settings: {
bitrate: 123,
codingMode: 'codingMode',
sampleRate: 123,
},
passThroughSettings: { },
wavSettings: {
bitDepth: 123,
codingMode: 'codingMode',
sampleRate: 123,
},
},
languageCode: 'languageCode',
languageCodeControl: 'languageCodeControl',
name: 'name',
remixSettings: {
channelMappings: [{
inputChannelLevels: [{
gain: 123,
inputChannel: 123,
}],
outputChannel: 123,
}],
channelsIn: 123,
channelsOut: 123,
},
streamName: 'streamName',
}],
availBlanking: {
availBlankingImage: {
passwordParam: 'passwordParam',
uri: 'uri',
username: 'username',
},
state: 'state',
},
availConfiguration: {
availSettings: {
scte35SpliceInsert: {
adAvailOffset: 123,
noRegionalBlackoutFlag: 'noRegionalBlackoutFlag',
webDeliveryAllowedFlag: 'webDeliveryAllowedFlag',
},
scte35TimeSignalApos: {
adAvailOffset: 123,
noRegionalBlackoutFlag: 'noRegionalBlackoutFlag',
webDeliveryAllowedFlag: 'webDeliveryAllowedFlag',
},
},
},
blackoutSlate: {
blackoutSlateImage: {
passwordParam: 'passwordParam',
uri: 'uri',
username: 'username',
},
networkEndBlackout: 'networkEndBlackout',
networkEndBlackoutImage: {
passwordParam: 'passwordParam',
uri: 'uri',
username: 'username',
},
networkId: 'networkId',
state: 'state',
},
captionDescriptions: [{
captionSelectorName: 'captionSelectorName',
destinationSettings: {
aribDestinationSettings: { },
burnInDestinationSettings: {
alignment: 'alignment',
backgroundColor: 'backgroundColor',
backgroundOpacity: 123,
font: {
passwordParam: 'passwordParam',
uri: 'uri',
username: 'username',
},
fontColor: 'fontColor',
fontOpacity: 123,
fontResolution: 123,
fontSize: 'fontSize',
outlineColor: 'outlineColor',
outlineSize: 123,
shadowColor: 'shadowColor',
shadowOpacity: 123,
shadowXOffset: 123,
shadowYOffset: 123,
teletextGridControl: 'teletextGridControl',
xPosition: 123,
yPosition: 123,
},
dvbSubDestinationSettings: {
alignment: 'alignment',
backgroundColor: 'backgroundColor',
backgroundOpacity: 123,
font: {
passwordParam: 'passwordParam',
uri: 'uri',
username: 'username',
},
fontColor: 'fontColor',
fontOpacity: 123,
fontResolution: 123,
fontSize: 'fontSize',
outlineColor: 'outlineColor',
outlineSize: 123,
shadowColor: 'shadowColor',
shadowOpacity: 123,
shadowXOffset: 123,
shadowYOffset: 123,
teletextGridControl: 'teletextGridControl',
xPosition: 123,
yPosition: 123,
},
ebuTtDDestinationSettings: {
copyrightHolder: 'copyrightHolder',
fillLineGap: 'fillLineGap',
fontFamily: 'fontFamily',
styleControl: 'styleControl',
},
embeddedDestinationSettings: { },
embeddedPlusScte20DestinationSettings: { },
rtmpCaptionInfoDestinationSettings: { },
scte20PlusEmbeddedDestinationSettings: { },
scte27DestinationSettings: { },
smpteTtDestinationSettings: { },
teletextDestinationSettings: { },
ttmlDestinationSettings: {
styleControl: 'styleControl',
},
webvttDestinationSettings: {
styleControl: 'styleControl',
},
},
languageCode: 'languageCode',
languageDescription: 'languageDescription',
name: 'name',
}],
featureActivations: {
inputPrepareScheduleActions: 'inputPrepareScheduleActions',
},
globalConfiguration: {
initialAudioGain: 123,
inputEndAction: 'inputEndAction',
inputLossBehavior: {
blackFrameMsec: 123,
inputLossImageColor: 'inputLossImageColor',
inputLossImageSlate: {
passwordParam: 'passwordParam',
uri: 'uri',
username: 'username',
},
inputLossImageType: 'inputLossImageType',
repeatFrameMsec: 123,
},
outputLockingMode: 'outputLockingMode',
outputTimingSource: 'outputTimingSource',
supportLowFramerateInputs: 'supportLowFramerateInputs',
},
motionGraphicsConfiguration: {
motionGraphicsInsertion: 'motionGraphicsInsertion',
motionGraphicsSettings: {
htmlMotionGraphicsSettings: { },
},
},
nielsenConfiguration: {
distributorId: 'distributorId',
nielsenPcmToId3Tagging: 'nielsenPcmToId3Tagging',
},
outputGroups: [{
name: 'name',
outputGroupSettings: {
archiveGroupSettings: {
archiveCdnSettings: {
archiveS3Settings: {
cannedAcl: 'cannedAcl',
},
},
destination: {
destinationRefId: 'destinationRefId',
},
rolloverInterval: 123,
},
frameCaptureGroupSettings: {
destination: {
destinationRefId: 'destinationRefId',
},
frameCaptureCdnSettings: {
frameCaptureS3Settings: {
cannedAcl: 'cannedAcl',
},
},
},
hlsGroupSettings: {
adMarkers: ['adMarkers'],
baseUrlContent: 'baseUrlContent',
baseUrlContent1: 'baseUrlContent1',
baseUrlManifest: 'baseUrlManifest',
baseUrlManifest1: 'baseUrlManifest1',
captionLanguageMappings: [{
captionChannel: 123,
languageCode: 'languageCode',
languageDescription: 'languageDescription',
}],
captionLanguageSetting: 'captionLanguageSetting',
clientCache: 'clientCache',
codecSpecification: 'codecSpecification',
constantIv: 'constantIv',
destination: {
destinationRefId: 'destinationRefId',
},
directoryStructure: 'directoryStructure',
discontinuityTags: 'discontinuityTags',
encryptionType: 'encryptionType',
hlsCdnSettings: {
hlsAkamaiSettings: {
connectionRetryInterval: 123,
filecacheDuration: 123,
httpTransferMode: 'httpTransferMode',
numRetries: 123,
restartDelay: 123,
salt: 'salt',
token: 'token',
},
hlsBasicPutSettings: {
connectionRetryInterval: 123,
filecacheDuration: 123,
numRetries: 123,
restartDelay: 123,
},
hlsMediaStoreSettings: {
connectionRetryInterval: 123,
filecacheDuration: 123,
mediaStoreStorageClass: 'mediaStoreStorageClass',
numRetries: 123,
restartDelay: 123,
},
hlsS3Settings: {
cannedAcl: 'cannedAcl',
},
hlsWebdavSettings: {
connectionRetryInterval: 123,
filecacheDuration: 123,
httpTransferMode: 'httpTransferMode',
numRetries: 123,
restartDelay: 123,
},
},
hlsId3SegmentTagging: 'hlsId3SegmentTagging',
iFrameOnlyPlaylists: 'iFrameOnlyPlaylists',
incompleteSegmentBehavior: 'incompleteSegmentBehavior',
indexNSegments: 123,
inputLossAction: 'inputLossAction',
ivInManifest: 'ivInManifest',
ivSource: 'ivSource',
keepSegments: 123,
keyFormat: 'keyFormat',
keyFormatVersions: 'keyFormatVersions',
keyProviderSettings: {
staticKeySettings: {
keyProviderServer: {
passwordParam: 'passwordParam',
uri: 'uri',
username: 'username',
},
staticKeyValue: 'staticKeyValue',
},
},
manifestCompression: 'manifestCompression',
manifestDurationFormat: 'manifestDurationFormat',
minSegmentLength: 123,
mode: 'mode',
outputSelection: 'outputSelection',
programDateTime: 'programDateTime',
programDateTimeClock: 'programDateTimeClock',
programDateTimePeriod: 123,
redundantManifest: 'redundantManifest',
segmentationMode: 'segmentationMode',
segmentLength: 123,
segmentsPerSubdirectory: 123,
streamInfResolution: 'streamInfResolution',
timedMetadataId3Frame: 'timedMetadataId3Frame',
timedMetadataId3Period: 123,
timestampDeltaMilliseconds: 123,
tsFileMode: 'tsFileMode',
},
mediaPackageGroupSettings: {
destination: {
destinationRefId: 'destinationRefId',
},
},
msSmoothGroupSettings: {
acquisitionPointId: 'acquisitionPointId',
audioOnlyTimecodeControl: 'audioOnlyTimecodeControl',
certificateMode: 'certificateMode',
connectionRetryInterval: 123,
destination: {
destinationRefId: 'destinationRefId',
},
eventId: 'eventId',
eventIdMode: 'eventIdMode',
eventStopBehavior: 'eventStopBehavior',
filecacheDuration: 123,
fragmentLength: 123,
inputLossAction: 'inputLossAction',
numRetries: 123,
restartDelay: 123,
segmentationMode: 'segmentationMode',
sendDelayMs: 123,
sparseTrackType: 'sparseTrackType',
streamManifestBehavior: 'streamManifestBehavior',
timestampOffset: 'timestampOffset',
timestampOffsetMode: 'timestampOffsetMode',
},
multiplexGroupSettings: { },
rtmpGroupSettings: {
adMarkers: ['adMarkers'],
authenticationScheme: 'authenticationScheme',
cacheFullBehavior: 'cacheFullBehavior',
cacheLength: 123,
captionData: 'captionData',
inputLossAction: 'inputLossAction',
restartDelay: 123,
},
udpGroupSettings: {
inputLossAction: 'inputLossAction',
timedMetadataId3Frame: 'timedMetadataId3Frame',
timedMetadataId3Period: 123,
},
},
outputs: [{
audioDescriptionNames: ['audioDescriptionNames'],
captionDescriptionNames: ['captionDescriptionNames'],
outputName: 'outputName',
outputSettings: {
archiveOutputSettings: {
containerSettings: {
m2TsSettings: {
absentInputAudioBehavior: 'absentInputAudioBehavior',
arib: 'arib',
aribCaptionsPid: 'aribCaptionsPid',
aribCaptionsPidControl: 'aribCaptionsPidControl',
audioBufferModel: 'audioBufferModel',
audioFramesPerPes: 123,
audioPids: 'audioPids',
audioStreamType: 'audioStreamType',
bitrate: 123,
bufferModel: 'bufferModel',
ccDescriptor: 'ccDescriptor',
dvbNitSettings: {
networkId: 123,
networkName: 'networkName',
repInterval: 123,
},
dvbSdtSettings: {
outputSdt: 'outputSdt',
repInterval: 123,
serviceName: 'serviceName',
serviceProviderName: 'serviceProviderName',
},
dvbSubPids: 'dvbSubPids',
dvbTdtSettings: {
repInterval: 123,
},
dvbTeletextPid: 'dvbTeletextPid',
ebif: 'ebif',
ebpAudioInterval: 'ebpAudioInterval',
ebpLookaheadMs: 123,
ebpPlacement: 'ebpPlacement',
ecmPid: 'ecmPid',
esRateInPes: 'esRateInPes',
etvPlatformPid: 'etvPlatformPid',
etvSignalPid: 'etvSignalPid',
fragmentTime: 123,
klv: 'klv',
klvDataPids: 'klvDataPids',
nielsenId3Behavior: 'nielsenId3Behavior',
nullPacketBitrate: 123,
patInterval: 123,
pcrControl: 'pcrControl',
pcrPeriod: 123,
pcrPid: 'pcrPid',
pmtInterval: 123,
pmtPid: 'pmtPid',
programNum: 123,
rateMode: 'rateMode',
scte27Pids: 'scte27Pids',
scte35Control: 'scte35Control',
scte35Pid: 'scte35Pid',
segmentationMarkers: 'segmentationMarkers',
segmentationStyle: 'segmentationStyle',
segmentationTime: 123,
timedMetadataBehavior: 'timedMetadataBehavior',
timedMetadataPid: 'timedMetadataPid',
transportStreamId: 123,
videoPid: 'videoPid',
},
rawSettings: { },
},
extension: 'extension',
nameModifier: 'nameModifier',
},
frameCaptureOutputSettings: {
nameModifier: 'nameModifier',
},
hlsOutputSettings: {
h265PackagingType: 'h265PackagingType',
hlsSettings: {
audioOnlyHlsSettings: {
audioGroupId: 'audioGroupId',
audioOnlyImage: {
passwordParam: 'passwordParam',
uri: 'uri',
username: 'username',
},
audioTrackType: 'audioTrackType',
segmentType: 'segmentType',
},
fmp4HlsSettings: {
audioRenditionSets: 'audioRenditionSets',
nielsenId3Behavior: 'nielsenId3Behavior',
timedMetadataBehavior: 'timedMetadataBehavior',
},
frameCaptureHlsSettings: { },
standardHlsSettings: {
audioRenditionSets: 'audioRenditionSets',
m3U8Settings: {
audioFramesPerPes: 123,
audioPids: 'audioPids',
ecmPid: 'ecmPid',
nielsenId3Behavior: 'nielsenId3Behavior',
patInterval: 123,
pcrControl: 'pcrControl',
pcrPeriod: 123,
pcrPid: 'pcrPid',
pmtInterval: 123,
pmtPid: 'pmtPid',
programNum: 123,
scte35Behavior: 'scte35Behavior',
scte35Pid: 'scte35Pid',
timedMetadataBehavior: 'timedMetadataBehavior',
timedMetadataPid: 'timedMetadataPid',
transportStreamId: 123,
videoPid: 'videoPid',
},
},
},
nameModifier: 'nameModifier',
segmentModifier: 'segmentModifier',
},
mediaPackageOutputSettings: { },
msSmoothOutputSettings: {
h265PackagingType: 'h265PackagingType',
nameModifier: 'nameModifier',
},
multiplexOutputSettings: {
destination: {
destinationRefId: 'destinationRefId',
},
},
rtmpOutputSettings: {
certificateMode: 'certificateMode',
connectionRetryInterval: 123,
destination: {
destinationRefId: 'destinationRefId',
},
numRetries: 123,
},
udpOutputSettings: {
bufferMsec: 123,
containerSettings: {
m2TsSettings: {
absentInputAudioBehavior: 'absentInputAudioBehavior',
arib: 'arib',
aribCaptionsPid: 'aribCaptionsPid',
aribCaptionsPidControl: 'aribCaptionsPidControl',
audioBufferModel: 'audioBufferModel',
audioFramesPerPes: 123,
audioPids: 'audioPids',
audioStreamType: 'audioStreamType',
bitrate: 123,
bufferModel: 'bufferModel',
ccDescriptor: 'ccDescriptor',
dvbNitSettings: {
networkId: 123,
networkName: 'networkName',
repInterval: 123,
},
dvbSdtSettings: {
outputSdt: 'outputSdt',
repInterval: 123,
serviceName: 'serviceName',
serviceProviderName: 'serviceProviderName',
},
dvbSubPids: 'dvbSubPids',
dvbTdtSettings: {
repInterval: 123,
},
dvbTeletextPid: 'dvbTeletextPid',
ebif: 'ebif',
ebpAudioInterval: 'ebpAudioInterval',
ebpLookaheadMs: 123,
ebpPlacement: 'ebpPlacement',
ecmPid: 'ecmPid',
esRateInPes: 'esRateInPes',
etvPlatformPid: 'etvPlatformPid',
etvSignalPid: 'etvSignalPid',
fragmentTime: 123,
klv: 'klv',
klvDataPids: 'klvDataPids',
nielsenId3Behavior: 'nielsenId3Behavior',
nullPacketBitrate: 123,
patInterval: 123,
pcrControl: 'pcrControl',
pcrPeriod: 123,
pcrPid: 'pcrPid',
pmtInterval: 123,
pmtPid: 'pmtPid',
programNum: 123,
rateMode: 'rateMode',
scte27Pids: 'scte27Pids',
scte35Control: 'scte35Control',
scte35Pid: 'scte35Pid',
segmentationMarkers: 'segmentationMarkers',
segmentationStyle: 'segmentationStyle',
segmentationTime: 123,
timedMetadataBehavior: 'timedMetadataBehavior',
timedMetadataPid: 'timedMetadataPid',
transportStreamId: 123,
videoPid: 'videoPid',
},
},
destination: {
destinationRefId: 'destinationRefId',
},
fecOutputSettings: {
columnDepth: 123,
includeFec: 'includeFec',
rowLength: 123,
},
},
},
videoDescriptionName: 'videoDescriptionName',
}],
}],
timecodeConfig: {
source: 'source',
syncThreshold: 123,
},
videoDescriptions: [{
codecSettings: {
frameCaptureSettings: {
captureInterval: 123,
captureIntervalUnits: 'captureIntervalUnits',
},
h264Settings: {
adaptiveQuantization: 'adaptiveQuantization',
afdSignaling: 'afdSignaling',
bitrate: 123,
bufFillPct: 123,
bufSize: 123,
colorMetadata: 'colorMetadata',
colorSpaceSettings: {
colorSpacePassthroughSettings: { },
rec601Settings: { },
rec709Settings: { },
},
entropyEncoding: 'entropyEncoding',
filterSettings: {
temporalFilterSettings: {
postFilterSharpening: 'postFilterSharpening',
strength: 'strength',
},
},
fixedAfd: 'fixedAfd',
flickerAq: 'flickerAq',
forceFieldPictures: 'forceFieldPictures',
framerateControl: 'framerateControl',
framerateDenominator: 123,
framerateNumerator: 123,
gopBReference: 'gopBReference',
gopClosedCadence: 123,
gopNumBFrames: 123,
gopSize: 123,
gopSizeUnits: 'gopSizeUnits',
level: 'level',
lookAheadRateControl: 'lookAheadRateControl',
maxBitrate: 123,
minIInterval: 123,
numRefFrames: 123,
parControl: 'parControl',
parDenominator: 123,
parNumerator: 123,
profile: 'profile',
qualityLevel: 'qualityLevel',
qvbrQualityLevel: 123,
rateControlMode: 'rateControlMode',
scanType: 'scanType',
sceneChangeDetect: 'sceneChangeDetect',
slices: 123,
softness: 123,
spatialAq: 'spatialAq',
subgopLength: 'subgopLength',
syntax: 'syntax',
temporalAq: 'temporalAq',
timecodeInsertion: 'timecodeInsertion',
},
h265Settings: {
adaptiveQuantization: 'adaptiveQuantization',
afdSignaling: 'afdSignaling',
alternativeTransferFunction: 'alternativeTransferFunction',
bitrate: 123,
bufSize: 123,
colorMetadata: 'colorMetadata',
colorSpaceSettings: {
colorSpacePassthroughSettings: { },
hdr10Settings: {
maxCll: 123,
maxFall: 123,
},
rec601Settings: { },
rec709Settings: { },
},
filterSettings: {
temporalFilterSettings: {
postFilterSharpening: 'postFilterSharpening',
strength: 'strength',
},
},
fixedAfd: 'fixedAfd',
flickerAq: 'flickerAq',
framerateDenominator: 123,
framerateNumerator: 123,
gopClosedCadence: 123,
gopSize: 123,
gopSizeUnits: 'gopSizeUnits',
level: 'level',
lookAheadRateControl: 'lookAheadRateControl',
maxBitrate: 123,
minIInterval: 123,
parDenominator: 123,
parNumerator: 123,
profile: 'profile',
qvbrQualityLevel: 123,
rateControlMode: 'rateControlMode',
scanType: 'scanType',
sceneChangeDetect: 'sceneChangeDetect',
slices: 123,
tier: 'tier',
timecodeInsertion: 'timecodeInsertion',
},
mpeg2Settings: {
adaptiveQuantization: 'adaptiveQuantization',
afdSignaling: 'afdSignaling',
colorMetadata: 'colorMetadata',
colorSpace: 'colorSpace',
displayAspectRatio: 'displayAspectRatio',
filterSettings: {
temporalFilterSettings: {
postFilterSharpening: 'postFilterSharpening',
strength: 'strength',
},
},
fixedAfd: 'fixedAfd',
framerateDenominator: 123,
framerateNumerator: 123,
gopClosedCadence: 123,
gopNumBFrames: 123,
gopSize: 123,
gopSizeUnits: 'gopSizeUnits',
scanType: 'scanType',
subgopLength: 'subgopLength',
timecodeInsertion: 'timecodeInsertion',
},
},
height: 123,
name: 'name',
respondToAfd: 'respondToAfd',
scalingBehavior: 'scalingBehavior',
sharpness: 123,
width: 123,
}],
},
inputAttachments: [{
automaticInputFailoverSettings: {
errorClearTimeMsec: 123,
failoverConditions: [{
failoverConditionSettings: {
audioSilenceSettings: {
audioSelectorName: 'audioSelectorName',
audioSilenceThresholdMsec: 123,
},
inputLossSettings: {
inputLossThresholdMsec: 123,
},
videoBlackSettings: {
blackDetectThreshold: 123,
videoBlackThresholdMsec: 123,
},
},
}],
inputPreference: 'inputPreference',
secondaryInputId: 'secondaryInputId',
},
inputAttachmentName: 'inputAttachmentName',
inputId: 'inputId',
inputSettings: {
audioSelectors: [{
name: 'name',
selectorSettings: {
audioHlsRenditionSelection: {
groupId: 'groupId',
name: 'name',
},
audioLanguageSelection: {
languageCode: 'languageCode',
languageSelectionPolicy: 'languageSelectionPolicy',
},
audioPidSelection: {
pid: 123,
},
audioTrackSelection: {
tracks: [{
track: 123,
}],
},
},
}],
captionSelectors: [{
languageCode: 'languageCode',
name: 'name',
selectorSettings: {
ancillarySourceSettings: {
sourceAncillaryChannelNumber: 123,
},
aribSourceSettings: { },
dvbSubSourceSettings: {
ocrLanguage: 'ocrLanguage',
pid: 123,
},
embeddedSourceSettings: {
convert608To708: 'convert608To708',
scte20Detection: 'scte20Detection',
source608ChannelNumber: 123,
source608TrackNumber: 123,
},
scte20SourceSettings: {
convert608To708: 'convert608To708',
source608ChannelNumber: 123,
},
scte27SourceSettings: {
ocrLanguage: 'ocrLanguage',
pid: 123,
},
teletextSourceSettings: {
outputRectangle: {
height: 123,
leftOffset: 123,
topOffset: 123,
width: 123,
},
pageNumber: 'pageNumber',
},
},
}],
deblockFilter: 'deblockFilter',
denoiseFilter: 'denoiseFilter',
filterStrength: 123,
inputFilter: 'inputFilter',
networkInputSettings: {
hlsInputSettings: {
bandwidth: 123,
bufferSegments: 123,
retries: 123,
retryInterval: 123,
scte35Source: 'scte35Source',
},
serverValidation: 'serverValidation',
},
scte35Pid: 123,
smpte2038DataPreference: 'smpte2038DataPreference',
sourceEndBehavior: 'sourceEndBehavior',
videoSelector: {
colorSpace: 'colorSpace',
colorSpaceSettings: {
hdr10Settings: {
maxCll: 123,
maxFall: 123,
},
},
colorSpaceUsage: 'colorSpaceUsage',
selectorSettings: {
videoSelectorPid: {
pid: 123,
},
videoSelectorProgramId: {
programId: 123,
},
},
},
},
}],
inputSpecification: {
codec: 'codec',
maximumBitrate: 'maximumBitrate',
resolution: 'resolution',
},
logLevel: 'logLevel',
name: 'name',
roleArn: 'roleArn',
tags: tags,
vpc: {
publicAddressAllocationIds: ['publicAddressAllocationIds'],
securityGroupIds: ['securityGroupIds'],
subnetIds: ['subnetIds'],
},
});
MediaLive Channel のパラメータを楽して埋めたい
膨大なパラメータをひとつひとつ調べて埋めて、リソース作成にトライして、失敗して、、、を繰り返していたらいくら時間があっても足りませんのでちょっと楽をして MediaLive Channel のパラメータを埋めてみます。
MediaLive には カスタムテンプレート という機能があり、これを利用することで、作成されている MediaLive Channel のパラメータをダウンロードすることができます。今回はこれを使って、MediaLive Channel を生成するソースコードを効率的に作成していきます。
やってみた
今回は以下の流れで進めます。
- MediaLive Input、MediaLive InputSecurityGroup を CDK で作成
- MediaLive Channel をコンソール上で作成
- 作成した MediaLive Channel のカスタムテンプレートをダウンロード
- MediaLive Channel を作成するための CDK ソースを作成
- CDK で MediaLive をデプロイ
1. MediaLive Input、MediaLive InputSecurityGroup を CDK で作成
まず、MediaLive の Input
と InputSecurityGroup
を CDK で作成します。次の手順で MediaLive Channel を作成するために、この 2つのリソースが必要です。
各種ドキュメントを参考に、RTMP PUSH を受け取るための Input を作成する以下のソースコードを作成しました。今回は同一ファイルに全てのリソースを含めていますが、必要に応じてファイル分割などを行ってください。
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as medialive from 'aws-cdk-lib/aws-medialive';
export class MediaworkloadStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// MediaLive Input SecurityGroup
const cfnInputSecurityGroup = new medialive.CfnInputSecurityGroup(this, 'MediaLiveInputSecurityGroup', {
tags: {
Name: 'MediaWL-SG'
},
whitelistRules: [
{
cidr: '10.0.0.0/16'
}
],
});
// MediaLive Input
const cfnInput = new medialive.CfnInput(this, 'MediaLiveInput', {
destinations: [
{
streamName: 'mediawl/stream-a',
},
{
streamName: 'mediawl/stream-b',
}
],
inputSecurityGroups: [ cfnInputSecurityGroup.ref ],
name: 'MediaWL-Input',
tags: {
Name: 'MediaWL-Input'
},
type: 'RTMP_PUSH',
})
}
}
この状態でデプロイを行います。
cdk deploy
下記画像の様に、MediaLive の Input と、Input Security Group が作成されていれば OK です。
2. MediaLive Channel をコンソール上で作成
続いて、コンソール上で MediaLive Channel を作成します。
MediaLive →「チャネルの作成」で下記の様な画面が開きますので、任意のチャネル名を入力します。
チャネル名を入力した後、そのまま少し下にスクロールすると「チャネルテンプレート」という設定項目があります。ここから Live event HLS
を選択します。選択後、「出力グループ」にいくつか設定が追加されるかと思います。
続いて、「入力アタッチメント」の横にある「追加」をクリックし、「入力」にて先ほど作成した Media Live Input リソースを選択し、「確認」をクリック。
最後に、「出力グループ」内の一番上にある文字列(今回は "1.HD(HLS)")をクリックし、「HLS グループ送信先」という項目をそれぞれ埋めます。本来は出力先のサービス等を示す URL を指定する必要がありますが、今回は検証目的であることと、後から変更も可能であることもあり適当な値を入れています。
一通り設定したら、画面下の「チャネルの作成」をクリックします。エラーなくチャネルが作成されたら、OK です。
3. 作成した MediaLive Channel のカスタムテンプレートをダウンロード
MediaLive Channel が作成されたら、作成された Channel の詳細画面を開き、右上の「アクション」→ 「カスタムテンプレートのダウンロード」をクリックします。
ダウンロードされた JSON ファイルの中身を確認すると、以下の様な構成になっていることがわかります。MediaLive Channel の CDK ドキュメント と見比べると、使いまわせそうなパラメータが沢山ありそうなことがわかるかと思います。
{
"name": "HTTP live streaming - clone",
"id": "1234567",
"arn": "arn:aws:medialive:ap-northeast-1:111122223333:channel:1234567",
"inputAttachments": [(省略)],
"state": "IDLE",
"pipelinesRunningCount": 0,
"destinations": [(省略)],
"egressEndpoints": [(省略)],
"encoderSettings": {(省略)},
"roleArn": "",
"inputSpecification": {(省略)},
"logLevel": "DISABLED",
"tags": {},
"channelClass": "STANDARD",
"pipelineDetails": [],
"maintenanceWindow": "FRIDAY_0400",
"maintenanceStatus": "",
"maintenance": {(省略)}
}
CDK のパラメータとして使える様に、上記 JSON に対して幾つかの処理をします。m3u8Settings
だけ、カスタムテンプレート内の表現が CDK 側で定義されている値とずれていたため、変換をかけています。
cat <ダウンロードしたJSONファイル> | sed -E "s/\"([a-zA-Z0-1]*)\":/\1:/g" > tmp.json
cat tmp.json | sed -E "s/\"/\'/g" > tmp.json
cat tmp.json | sed -E "s/m3u8Settings/m3U8Settings/g" > output.json
上記コマンドを実行すると、下記の様に CDK のソースコードにパラメータとしてそのまま使える形式になります。
{
name: 'HTTP live streaming - clone',
id: '1234567',
arn: 'arn:aws:medialive:ap-northeast-1:111122223333:channel:1234567',
inputAttachments: [(省略)],
state: 'IDLE',
pipelinesRunningCount: 0,
destinations: [(省略)],
egressEndpoints: [(省略)],
encoderSettings: {(省略)},
roleArn: '',
inputSpecification: {(省略)},
logLevel: 'DISABLED',
tags: {},
channelClass: 'STANDARD',
pipelineDetails: [],
maintenanceWindow: 'FRIDAY_0400',
maintenanceStatus: '',
maintenance: {(省略)}
}
4. MediaLive Channel を作成するための CDK ソースを作成
上記で取得したパラメータ一覧を CDK の CfnChannel パラメータに当てはめたものが下記のソースコードです。(長いので折りたたんでいます)
以下パラメータについて、上記で取得した値をそのままコピペで使っています。
- channelClass
- destinations
- encoderSettings
- inputSpecification
- logLevel
- name
- tags
- roleArn
一方で、ダウンロードしたカスタムテンプレートには入力(inputAttachments)に関する情報は含まれない形になるため、以下の記述だけ追加しています。
inputAttachments: [{
inputAttachmentName: 'MediaWL-Input',
inputId: cfnInput.ref,
}]
作成したスタックファイルはこちら
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as medialive from 'aws-cdk-lib/aws-medialive';
export class MediaworkloadStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// MediaLive Input SecurityGroup
const cfnInputSecurityGroup = new medialive.CfnInputSecurityGroup(this, 'MediaLiveInputSecurityGroup', {
tags: {
Name: 'MediaWL-SG'
},
whitelistRules: [
{
cidr: '10.0.0.0/16'
}
],
});
// MediaLive Input
const cfnInput = new medialive.CfnInput(this, 'MediaLiveInput', {
destinations: [
{
streamName: 'mediawl/stream-a',
},
{
streamName: 'mediawl/stream-b',
}
],
inputSecurityGroups: [ cfnInputSecurityGroup.ref ],
name: 'MediaWL-Input',
tags: {
Name: 'MediaWL-Input'
},
type: 'RTMP_PUSH',
})
// MediaLive Channel
const cfnChannel = new medialive.CfnChannel(this, 'MediaLiveChannel', {
channelClass: 'STANDARD',
destinations: [
{
id: 'destination1',
settings: [
{
url: 'http://example.com/main'
},
{
url: 'http://example.com/sby'
}
],
mediaPackageSettings: []
}
],
encoderSettings: {
audioDescriptions: [
{
audioSelectorName: 'default',
codecSettings: {
aacSettings: {
bitrate: 64000,
rawFormat: 'NONE',
spec: 'MPEG4'
}
},
audioTypeControl: 'FOLLOW_INPUT',
languageCodeControl: 'FOLLOW_INPUT',
name: 'audio_1_aac64'
},
{
audioSelectorName: 'default',
codecSettings: {
aacSettings: {
bitrate: 64000,
rawFormat: 'NONE',
spec: 'MPEG4'
}
},
audioTypeControl: 'FOLLOW_INPUT',
languageCodeControl: 'FOLLOW_INPUT',
name: 'audio_2_aac64'
},
{
audioSelectorName: 'default',
codecSettings: {
aacSettings: {
bitrate: 64000,
rawFormat: 'NONE',
spec: 'MPEG4'
}
},
audioTypeControl: 'FOLLOW_INPUT',
languageCodeControl: 'FOLLOW_INPUT',
name: 'audio_3_aac64'
},
{
audioSelectorName: 'default',
codecSettings: {
aacSettings: {
bitrate: 96000,
rawFormat: 'NONE',
spec: 'MPEG4'
}
},
audioTypeControl: 'FOLLOW_INPUT',
languageCodeControl: 'FOLLOW_INPUT',
name: 'audio_1_aac96'
},
{
audioSelectorName: 'default',
codecSettings: {
aacSettings: {
bitrate: 96000,
rawFormat: 'NONE',
spec: 'MPEG4'
}
},
audioTypeControl: 'FOLLOW_INPUT',
languageCodeControl: 'FOLLOW_INPUT',
name: 'audio_2_aac96'
},
{
audioSelectorName: 'default',
codecSettings: {
aacSettings: {
bitrate: 96000,
rawFormat: 'NONE',
spec: 'MPEG4'
}
},
audioTypeControl: 'FOLLOW_INPUT',
languageCodeControl: 'FOLLOW_INPUT',
name: 'audio_3_aac96'
},
{
audioSelectorName: 'default',
codecSettings: {
aacSettings: {
bitrate: 128000,
rawFormat: 'NONE',
spec: 'MPEG4'
}
},
audioTypeControl: 'FOLLOW_INPUT',
languageCodeControl: 'FOLLOW_INPUT',
name: 'audio_1_aac128'
},
{
audioSelectorName: 'default',
codecSettings: {
aacSettings: {
bitrate: 128000,
rawFormat: 'NONE',
spec: 'MPEG4'
}
},
audioTypeControl: 'FOLLOW_INPUT',
languageCodeControl: 'FOLLOW_INPUT',
name: 'audio_2_aac128'
},
{
audioSelectorName: 'default',
codecSettings: {
aacSettings: {
bitrate: 128000,
rawFormat: 'NONE',
spec: 'MPEG4'
}
},
audioTypeControl: 'FOLLOW_INPUT',
languageCodeControl: 'FOLLOW_INPUT',
name: 'audio_3_aac128'
}
],
outputGroups: [
{
outputGroupSettings: {
hlsGroupSettings: {
incompleteSegmentBehavior: 'AUTO',
discontinuityTags: 'INSERT',
adMarkers: [],
captionLanguageSetting: 'OMIT',
captionLanguageMappings: [],
hlsCdnSettings: {
hlsBasicPutSettings: {
numRetries: 5,
connectionRetryInterval: 30,
restartDelay: 5,
filecacheDuration: 300
}
},
inputLossAction: 'EMIT_OUTPUT',
manifestCompression: 'NONE',
destination: {
destinationRefId: 'destination1'
},
ivInManifest: 'INCLUDE',
ivSource: 'FOLLOWS_SEGMENT_NUMBER',
clientCache: 'ENABLED',
tsFileMode: 'SEGMENTED_FILES',
manifestDurationFormat: 'FLOATING_POINT',
segmentationMode: 'USE_SEGMENT_DURATION',
redundantManifest: 'DISABLED',
outputSelection: 'MANIFESTS_AND_SEGMENTS',
streamInfResolution: 'INCLUDE',
iFrameOnlyPlaylists: 'DISABLED',
indexNSegments: 10,
programDateTime: 'INCLUDE',
programDateTimePeriod: 600,
keepSegments: 21,
segmentLength: 6,
timedMetadataId3Frame: 'PRIV',
timedMetadataId3Period: 10,
hlsId3SegmentTagging: 'DISABLED',
codecSpecification: 'RFC_4281',
directoryStructure: 'SINGLE_DIRECTORY',
segmentsPerSubdirectory: 10000,
mode: 'LIVE',
programDateTimeClock: 'INITIALIZE_FROM_OUTPUT_TIMECODE'
}
},
name: 'TN2224',
outputs: [
{
outputSettings: {
hlsOutputSettings: {
nameModifier: '_960x540_2000k',
hlsSettings: {
standardHlsSettings: {
m3U8Settings: {
audioPids: '492-498',
ecmPid: '8182',
pcrControl: 'PCR_EVERY_PES_PACKET',
pmtPid: '480',
scte35Pid: '500',
scte35Behavior: 'NO_PASSTHROUGH',
timedMetadataPid: '502',
timedMetadataBehavior: 'NO_PASSTHROUGH',
videoPid: '481'
},
audioRenditionSets: 'program_audio'
}
}
}
},
videoDescriptionName: 'video_960_540',
audioDescriptionNames: [
'audio_2_aac96'
],
captionDescriptionNames: []
},
{
outputSettings: {
hlsOutputSettings: {
nameModifier: '_1280x720_3300k',
hlsSettings: {
standardHlsSettings: {
m3U8Settings: {
audioPids: '492-498',
ecmPid: '8182',
pcrControl: 'PCR_EVERY_PES_PACKET',
pmtPid: '480',
scte35Pid: '500',
scte35Behavior: 'NO_PASSTHROUGH',
timedMetadataPid: '502',
timedMetadataBehavior: 'NO_PASSTHROUGH',
videoPid: '481'
},
audioRenditionSets: 'program_audio'
}
}
}
},
videoDescriptionName: 'video_1280_720_1',
audioDescriptionNames: [
'audio_3_aac96'
],
captionDescriptionNames: []
},
{
outputSettings: {
hlsOutputSettings: {
nameModifier: '_1280x720_5000k',
hlsSettings: {
standardHlsSettings: {
m3U8Settings: {
audioPids: '492-498',
ecmPid: '8182',
pcrControl: 'PCR_EVERY_PES_PACKET',
pmtPid: '480',
scte35Pid: '500',
scte35Behavior: 'NO_PASSTHROUGH',
timedMetadataPid: '502',
timedMetadataBehavior: 'NO_PASSTHROUGH',
videoPid: '481'
},
audioRenditionSets: 'program_audio'
}
}
}
},
videoDescriptionName: 'video_1280_720_2',
audioDescriptionNames: [
'audio_1_aac128'
],
captionDescriptionNames: []
},
{
outputSettings: {
hlsOutputSettings: {
nameModifier: '_1280x720_6500k',
hlsSettings: {
standardHlsSettings: {
m3U8Settings: {
audioPids: '492-498',
ecmPid: '8182',
pcrControl: 'PCR_EVERY_PES_PACKET',
pmtPid: '480',
scte35Pid: '500',
scte35Behavior: 'NO_PASSTHROUGH',
timedMetadataPid: '502',
timedMetadataBehavior: 'NO_PASSTHROUGH',
videoPid: '481'
},
audioRenditionSets: 'program_audio'
}
}
}
},
videoDescriptionName: 'video_1280_720_3',
audioDescriptionNames: [
'audio_2_aac128'
],
captionDescriptionNames: []
},
{
outputSettings: {
hlsOutputSettings: {
nameModifier: '_1920x1080_8000k',
hlsSettings: {
standardHlsSettings: {
m3U8Settings: {
audioPids: '492-498',
ecmPid: '8182',
pcrControl: 'PCR_EVERY_PES_PACKET',
pmtPid: '480',
scte35Pid: '500',
scte35Behavior: 'NO_PASSTHROUGH',
timedMetadataPid: '502',
timedMetadataBehavior: 'NO_PASSTHROUGH',
videoPid: '481'
},
audioRenditionSets: 'program_audio'
}
}
}
},
videoDescriptionName: 'video_1920_1080',
audioDescriptionNames: [
'audio_3_aac128'
],
captionDescriptionNames: []
},
{
outputSettings: {
hlsOutputSettings: {
nameModifier: '_416x234_200k',
hlsSettings: {
standardHlsSettings: {
m3U8Settings: {
audioPids: '492-498',
ecmPid: '8182',
pcrControl: 'PCR_EVERY_PES_PACKET',
pmtPid: '480',
scte35Pid: '500',
scte35Behavior: 'NO_PASSTHROUGH',
timedMetadataPid: '502',
timedMetadataBehavior: 'NO_PASSTHROUGH',
videoPid: '481'
},
audioRenditionSets: 'program_audio'
}
}
}
},
videoDescriptionName: 'video_416_234',
audioDescriptionNames: [
'audio_1_aac64'
],
captionDescriptionNames: []
},
{
outputSettings: {
hlsOutputSettings: {
nameModifier: '_480x270_400k',
hlsSettings: {
standardHlsSettings: {
m3U8Settings: {
audioPids: '492-498',
ecmPid: '8182',
pcrControl: 'PCR_EVERY_PES_PACKET',
pmtPid: '480',
scte35Pid: '500',
scte35Behavior: 'NO_PASSTHROUGH',
timedMetadataPid: '502',
timedMetadataBehavior: 'NO_PASSTHROUGH',
videoPid: '481'
},
audioRenditionSets: 'program_audio'
}
}
}
},
videoDescriptionName: 'video_480_270',
audioDescriptionNames: [
'audio_2_aac64'
],
captionDescriptionNames: []
},
{
outputSettings: {
hlsOutputSettings: {
nameModifier: '_640x360_800k',
hlsSettings: {
standardHlsSettings: {
m3U8Settings: {
audioPids: '492-498',
ecmPid: '8182',
pcrControl: 'PCR_EVERY_PES_PACKET',
pmtPid: '480',
scte35Pid: '500',
scte35Behavior: 'NO_PASSTHROUGH',
timedMetadataPid: '502',
timedMetadataBehavior: 'NO_PASSTHROUGH',
videoPid: '481'
},
audioRenditionSets: 'program_audio'
}
}
}
},
videoDescriptionName: 'video_640_360',
audioDescriptionNames: [
'audio_3_aac64'
],
captionDescriptionNames: []
},
{
outputSettings: {
hlsOutputSettings: {
nameModifier: '_768x432_1200k',
hlsSettings: {
standardHlsSettings: {
m3U8Settings: {
audioPids: '492-498',
ecmPid: '8182',
pcrControl: 'PCR_EVERY_PES_PACKET',
pmtPid: '480',
scte35Pid: '500',
scte35Behavior: 'NO_PASSTHROUGH',
timedMetadataPid: '502',
timedMetadataBehavior: 'NO_PASSTHROUGH',
videoPid: '481'
},
audioRenditionSets: 'program_audio'
}
}
}
},
videoDescriptionName: 'video_768_432',
audioDescriptionNames: [
'audio_1_aac96'
],
captionDescriptionNames: []
}
]
}
],
timecodeConfig: {
source: 'SYSTEMCLOCK'
},
videoDescriptions: [
{
codecSettings: {
h264Settings: {
colorMetadata: 'INSERT',
adaptiveQuantization: 'HIGH',
bitrate: 200000,
entropyEncoding: 'CAVLC',
flickerAq: 'ENABLED',
framerateControl: 'SPECIFIED',
framerateNumerator: 15000,
framerateDenominator: 1001,
gopBReference: 'DISABLED',
gopNumBFrames: 0,
gopSize: 30,
gopSizeUnits: 'FRAMES',
level: 'H264_LEVEL_3',
lookAheadRateControl: 'HIGH',
parControl: 'INITIALIZE_FROM_SOURCE',
profile: 'BASELINE',
rateControlMode: 'CBR',
syntax: 'DEFAULT',
sceneChangeDetect: 'ENABLED',
spatialAq: 'ENABLED',
temporalAq: 'ENABLED'
}
},
height: 236,
name: 'video_416_234',
scalingBehavior: 'DEFAULT',
width: 416
},
{
codecSettings: {
h264Settings: {
colorMetadata: 'INSERT',
adaptiveQuantization: 'HIGH',
bitrate: 400000,
entropyEncoding: 'CAVLC',
flickerAq: 'ENABLED',
framerateControl: 'SPECIFIED',
framerateNumerator: 15000,
framerateDenominator: 1001,
gopBReference: 'DISABLED',
gopNumBFrames: 0,
gopSize: 30,
gopSizeUnits: 'FRAMES',
level: 'H264_LEVEL_3',
lookAheadRateControl: 'HIGH',
parControl: 'INITIALIZE_FROM_SOURCE',
profile: 'BASELINE',
rateControlMode: 'CBR',
syntax: 'DEFAULT',
sceneChangeDetect: 'ENABLED',
spatialAq: 'ENABLED',
temporalAq: 'ENABLED'
}
},
height: 272,
name: 'video_480_270',
scalingBehavior: 'DEFAULT',
width: 480
},
{
codecSettings: {
h264Settings: {
colorMetadata: 'INSERT',
adaptiveQuantization: 'HIGH',
bitrate: 800000,
entropyEncoding: 'CABAC',
flickerAq: 'ENABLED',
framerateControl: 'SPECIFIED',
framerateNumerator: 30000,
framerateDenominator: 1001,
gopBReference: 'ENABLED',
gopNumBFrames: 3,
gopSize: 60,
gopSizeUnits: 'FRAMES',
level: 'H264_LEVEL_3',
lookAheadRateControl: 'HIGH',
parControl: 'INITIALIZE_FROM_SOURCE',
profile: 'MAIN',
rateControlMode: 'CBR',
syntax: 'DEFAULT',
sceneChangeDetect: 'ENABLED',
spatialAq: 'ENABLED',
temporalAq: 'ENABLED'
}
},
height: 360,
name: 'video_640_360',
scalingBehavior: 'DEFAULT',
width: 640
},
{
codecSettings: {
h264Settings: {
colorMetadata: 'INSERT',
adaptiveQuantization: 'HIGH',
bitrate: 1200000,
entropyEncoding: 'CABAC',
flickerAq: 'ENABLED',
framerateControl: 'SPECIFIED',
framerateNumerator: 30000,
framerateDenominator: 1001,
gopBReference: 'ENABLED',
gopNumBFrames: 3,
gopSize: 60,
gopSizeUnits: 'FRAMES',
level: 'H264_LEVEL_4_1',
lookAheadRateControl: 'HIGH',
parControl: 'INITIALIZE_FROM_SOURCE',
profile: 'MAIN',
rateControlMode: 'CBR',
syntax: 'DEFAULT',
sceneChangeDetect: 'ENABLED',
spatialAq: 'ENABLED',
temporalAq: 'ENABLED'
}
},
height: 432,
name: 'video_768_432',
scalingBehavior: 'DEFAULT',
width: 768
},
{
codecSettings: {
h264Settings: {
colorMetadata: 'INSERT',
adaptiveQuantization: 'HIGH',
bitrate: 2200000,
entropyEncoding: 'CABAC',
flickerAq: 'ENABLED',
framerateControl: 'SPECIFIED',
framerateNumerator: 30000,
framerateDenominator: 1001,
gopBReference: 'ENABLED',
gopNumBFrames: 3,
gopSize: 60,
gopSizeUnits: 'FRAMES',
level: 'H264_LEVEL_4_1',
lookAheadRateControl: 'HIGH',
parControl: 'INITIALIZE_FROM_SOURCE',
profile: 'HIGH',
rateControlMode: 'CBR',
syntax: 'DEFAULT',
sceneChangeDetect: 'ENABLED',
spatialAq: 'ENABLED',
temporalAq: 'ENABLED'
}
},
height: 540,
name: 'video_960_540',
scalingBehavior: 'DEFAULT',
width: 960
},
{
codecSettings: {
h264Settings: {
colorMetadata: 'INSERT',
adaptiveQuantization: 'HIGH',
bitrate: 3300000,
entropyEncoding: 'CABAC',
flickerAq: 'ENABLED',
framerateControl: 'SPECIFIED',
framerateNumerator: 30000,
framerateDenominator: 1001,
gopBReference: 'ENABLED',
gopNumBFrames: 3,
gopSize: 60,
gopSizeUnits: 'FRAMES',
level: 'H264_LEVEL_4_1',
lookAheadRateControl: 'HIGH',
parControl: 'INITIALIZE_FROM_SOURCE',
profile: 'HIGH',
rateControlMode: 'CBR',
syntax: 'DEFAULT',
sceneChangeDetect: 'ENABLED',
spatialAq: 'ENABLED',
temporalAq: 'ENABLED'
}
},
height: 720,
name: 'video_1280_720_1',
scalingBehavior: 'DEFAULT',
width: 1280
},
{
codecSettings: {
h264Settings: {
colorMetadata: 'INSERT',
adaptiveQuantization: 'HIGH',
bitrate: 4700000,
entropyEncoding: 'CABAC',
flickerAq: 'ENABLED',
framerateControl: 'SPECIFIED',
framerateNumerator: 30000,
framerateDenominator: 1001,
gopBReference: 'ENABLED',
gopNumBFrames: 3,
gopSize: 60,
gopSizeUnits: 'FRAMES',
level: 'H264_LEVEL_4_1',
lookAheadRateControl: 'HIGH',
parControl: 'INITIALIZE_FROM_SOURCE',
profile: 'HIGH',
rateControlMode: 'CBR',
syntax: 'DEFAULT',
sceneChangeDetect: 'ENABLED',
spatialAq: 'ENABLED',
temporalAq: 'ENABLED'
}
},
height: 720,
name: 'video_1280_720_2',
scalingBehavior: 'DEFAULT',
width: 1280
},
{
codecSettings: {
h264Settings: {
colorMetadata: 'INSERT',
adaptiveQuantization: 'HIGH',
bitrate: 6200000,
entropyEncoding: 'CABAC',
flickerAq: 'ENABLED',
framerateControl: 'SPECIFIED',
framerateNumerator: 30000,
framerateDenominator: 1001,
gopBReference: 'ENABLED',
gopNumBFrames: 3,
gopSize: 60,
gopSizeUnits: 'FRAMES',
level: 'H264_LEVEL_4_1',
lookAheadRateControl: 'HIGH',
parControl: 'INITIALIZE_FROM_SOURCE',
profile: 'HIGH',
rateControlMode: 'CBR',
syntax: 'DEFAULT',
sceneChangeDetect: 'ENABLED',
spatialAq: 'ENABLED',
temporalAq: 'ENABLED'
}
},
height: 720,
name: 'video_1280_720_3',
scalingBehavior: 'DEFAULT',
width: 1280
},
{
codecSettings: {
h264Settings: {
colorMetadata: 'INSERT',
adaptiveQuantization: 'HIGH',
bitrate: 8000000,
entropyEncoding: 'CABAC',
flickerAq: 'ENABLED',
framerateControl: 'SPECIFIED',
framerateNumerator: 30000,
framerateDenominator: 1001,
gopBReference: 'DISABLED',
gopNumBFrames: 1,
gopSize: 60,
gopSizeUnits: 'FRAMES',
level: 'H264_LEVEL_4_1',
lookAheadRateControl: 'HIGH',
parControl: 'INITIALIZE_FROM_SOURCE',
profile: 'HIGH',
rateControlMode: 'CBR',
syntax: 'DEFAULT',
sceneChangeDetect: 'ENABLED',
spatialAq: 'ENABLED',
temporalAq: 'ENABLED'
}
},
height: 1080,
name: 'video_1920_1080',
scalingBehavior: 'DEFAULT',
width: 1920
}
]
},
inputAttachments: [{
inputAttachmentName: 'MediaWL-Input',
inputId: cfnInput.ref,
}],
inputSpecification: {
codec: 'AVC',
resolution: 'HD',
maximumBitrate: 'MAX_20_MBPS'
},
logLevel: 'DISABLED',
name: 'HTTP live streaming - clone',
roleArn: '',
tags: {},
});
}
}
5. CDK で MediaLive をデプロイ
最後に、作成したソースコードで MediaLive がデプロイできるか確認します。
先に、先ほど作成した MediaLive Channel は削除しておきましょう。
CDK で作成したリソースも削除します。
cdk destroy
リソースの削除が完了したら、デプロイをかけます。
cdk deploy
無事にリソースが作成できれば OK です。カスタムテンプレートをダウンロードすることで、パラメータをうまく流用することができました。
おわりに
パラメータの多い MediaLive Channel を IaC(今回は CDK)で管理しようとした際に、一つずつパラメータを調べていくのは大変です。今回紹介したカスタムテンプレートのダウンロード機能を利用すれば、コンソールで作成した MediaLive Channel の設定をそのまま持って来れます。
また、一度 MediaLive Channel を作成できる状態になってしまえば、細かいパラメータの調整やファイルの分割などは如何様にもできると思います。
MediaLive の IaC 管理でお困りの方のお役に立てれば幸いです。
以上、AWS 事業本部の大前でした。