Amazon.CDK.AWS.MediaPackageV2.Alpha
The CDK construct library for MediaPackageV2 (Stability: Experimental)
Install
| Product | Versions |
|---|---|
| .NET |
README
AWS::MediaPackageV2 Construct Library
The APIs of higher level constructs in this module are experimental and under active development. They are subject to non-backward compatible changes or removal in any future version. These are not subject to the Semantic Versioning model and breaking changes will be announced in the release notes. This means that while you may use them, you may need to update your source code when upgrading to a newer version of this package.
AWS Elemental MediaPackage V2
MediaPackage delivers high-quality video without concern for capacity and makes it easier to implement popular DVR features such as start over, pause, and rewind. Your content will be protected with comprehensive support for DRM. The service seamlessly integrates with other AWS media services as a complete set of tools for cloud-based video processing and delivery.
This package contains constructs for working with AWS Elemental MediaPackage V2. Allowing you to define AWS Elemental MediaPackage V2 Channel Groups, Channels, Origin Endpoints, Channel Policies and Origin Endpoint Policies.
For further information on AWS Elemental MediaPackage V2, see the documentation.
The following example creates an AWS Elemental MediaPackage V2 Channel Group, Channel and Origin Endpoint:
Stack stack;
var group = new ChannelGroup(stack, "MyChannelGroup", new ChannelGroupProps {
ChannelGroupName = "my-test-channel-group"
});
var channel = new Channel(stack, "MyChannel", new ChannelProps {
ChannelGroup = group,
ChannelName = "my-testchannel",
Input = InputConfiguration.Cmaf()
});
var endpoint = new OriginEndpoint(stack, "MyOriginEndpoint", new OriginEndpointProps {
Channel = channel,
OriginEndpointName = "my-test-endpoint",
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration {
ManifestName = "index"
}) }
});
Using Factory Methods
Stack stack;
// Create a channel group
var group = new ChannelGroup(stack, "MyChannelGroup", new ChannelGroupProps {
ChannelGroupName = "my-channel-group"
});
// Add a channel using the factory method
var channel = group.AddChannel("MyChannel", new ChannelOptions {
ChannelName = "my-channel",
Input = InputConfiguration.Cmaf()
});
// Add an origin endpoint using the factory method
var endpoint = channel.AddOriginEndpoint("MyEndpoint", new OriginEndpointOptions {
OriginEndpointName = "my-endpoint",
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "index" }) }
});
Channel Group
A channel group is the top-level resource that consists of channels and origin endpoints associated with it.
The following code creates a Channel Group:
Stack stack;
var group = new ChannelGroup(stack, "MyChannelGroup", new ChannelGroupProps {
ChannelGroupName = "my-test-channel-group"
});
The following code imports an existing channel group using the name attribute:
Stack stack;
var channelGroup = ChannelGroup.FromChannelGroupAttributes(stack, "ImportedChannelGroup", new ChannelGroupAttributes {
ChannelGroupName = "MyChannelGroup"
});
You can also import from an ARN, which automatically extracts the name and region:
Stack stack;
var channelGroup = ChannelGroup.FromChannelGroupArn(stack, "ImportedChannelGroup", "arn:aws:mediapackagev2:us-west-2:123456789012:channelGroup/MyChannelGroup");
For cross-region imports, pass the region parameter to ensure the correct ARN is constructed:
Stack stack;
var channelGroup = ChannelGroup.FromChannelGroupAttributes(stack, "ImportedChannelGroup", new ChannelGroupAttributes {
ChannelGroupName = "MyChannelGroup",
Region = "us-west-2"
});
Channel
A channel is part of a channel group and represents the entry point for a content stream into MediaPackage.
Input Configuration
Channels support two input types: HLS and CMAF.
Stack stack;
ChannelGroup group;
var hlsChannel = new Channel(stack, "HlsChannel", new ChannelProps {
ChannelGroup = group,
Input = InputConfiguration.Hls()
});
var cmafChannel = new Channel(stack, "CmafChannel", new ChannelProps {
ChannelGroup = group,
Input = InputConfiguration.Cmaf(new CmafInputProps {
InputSwitchConfiguration = new InputSwitchConfiguration {
MqcsInputSwitching = true
},
OutputHeaders = new [] { HeadersCMSD.MQCS }
})
});
var simpleCmafChannel = new Channel(stack, "SimpleCmafChannel", new ChannelProps {
ChannelGroup = group,
Input = InputConfiguration.Cmaf(new CmafInputProps {
OutputHeaders = new [] { HeadersCMSD.MQCS }
})
});
Importing an Existing Channel
The following code imports an existing channel using the name attributes:
Stack stack;
var channel = Channel.FromChannelAttributes(stack, "ImportedChannel", new ChannelAttributes {
ChannelName = "MyChannel",
ChannelGroupName = "MyChannelGroup"
});
You can also import from an ARN:
Stack stack;
var channel = Channel.FromChannelArn(stack, "ImportedChannel", "arn:aws:mediapackagev2:us-west-2:123456789012:channelGroup/MyGroup/channel/MyChannel");
Imported channels expose a region property, which is parsed from the ARN or falls back to the importing stack's region.
Channel Resource Policy
The following code creates a resource policy directly on the channel. This will automatically create a policy on the first call:
Channel channel;
channel.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps {
Sid = "AllowMediaLiveRoleToAccessEmpChannel",
Principals = new [] { new ArnPrincipal("arn:aws:iam::AccountID:role/MediaLiveAccessRole") },
Effect = Effect.ALLOW,
Actions = new [] { "mediapackagev2:PutObject" },
Resources = new [] { channel.ChannelArn }
}));
Origin Endpoint
Stack stack;
Channel channel;
new OriginEndpoint(stack, "myendpoint", new OriginEndpointProps {
Channel = channel,
OriginEndpointName = "my-test-endpoint",
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration {
ManifestName = "index"
}) }
});
The following code imports an existing origin endpoint using the name attributes:
Stack stack;
var originEndpoint = OriginEndpoint.FromOriginEndpointAttributes(stack, "ImportedOriginEndpoint", new OriginEndpointAttributes {
ChannelGroupName = "MyChannelGroup",
ChannelName = "MyChannel",
OriginEndpointName = "MyExampleOriginEndpoint"
});
You can also import from an ARN:
Stack stack;
var originEndpoint = OriginEndpoint.FromOriginEndpointArn(stack, "ImportedOriginEndpoint", "arn:aws:mediapackagev2:us-west-2:123456789012:channelGroup/MyGroup/channel/MyChannel/originEndpoint/MyEndpoint");
The following code creates a resource policy on the origin endpoint. This will automatically create a policy on the first call:
OriginEndpoint origin;
origin.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps {
Sid = "AllowRequestsFromCloudFront",
Principals = new [] { new ServicePrincipal("cloudfront.amazonaws.com") },
Effect = Effect.ALLOW,
Actions = new [] { "mediapackagev2:GetHeadObject", "mediapackagev2:GetObject" },
Resources = new [] { origin.OriginEndpointArn },
Conditions = new Dictionary<string, object> {
{ "StringEquals", new Dictionary<string, string> {
{ "aws:SourceArn", "arn:aws:cloudfront::123456789012:distribution/AAAAAAAAA" }
} }
}
}));
CDN Authorization
MediaPackage V2 supports two ways to lock an origin endpoint to your CDN:
- AWS Signature Version 4 (SigV4) — the CDN signs requests with an IAM role. For Amazon CloudFront, see CloudFront Integration. See the SigV4 authentication guide.
- Header-based CDN authorization — the CDN attaches a shared secret in a request header that MediaPackage validates. Use this when your CDN doesn't support SigV4. See the CDN authorization guide.
To configure header-based authorization, set cdnAuth on the OriginEndpoint
props. The L2 auto-creates the endpoint policy with:
- a
PolicyStatementrequiring themediapackagev2:RequestHasMatchingCdnAuthHeadercondition on everyGetObjectrequest - the
CdnAuthConfigurationblock that references the secrets and the read role
If you don't supply a role, one is created with the needed Secrets Manager and KMS permissions.
using Amazon.CDK.AWS.SecretsManager;
Channel channel;
ISecret mySecret;
new OriginEndpoint(this, "OriginEndpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Ts(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "index" }) },
CdnAuth = new CdnAuthConfiguration {
Secrets = new [] { mySecret }
}
});
You can still call addToResourcePolicy() to add extra statements (e.g. a
harvester allow); they're appended to the auto-created policy alongside the
gating statement.
Granting Permissions
Granting Ingest Access to MediaLive
To allow AWS Elemental MediaLive to ingest content into a MediaPackage channel, use the grants.ingest() method:
Channel channel;
IRole mediaLiveRole;
// Grant MediaLive permission to ingest content
channel.Grants.Ingest(mediaLiveRole);
CloudFront Integration
MediaPackage origin endpoints are designed to be used with Content Delivery Network (CDN) like Amazon CloudFront distributions. CloudFront provides caching, DDoS protection, and global content delivery for your streaming content.
The simplest way to connect CloudFront to a MediaPackage V2 endpoint is with MediaPackageV2Origin, which automatically creates an Origin Access Control (OAC) and wires the endpoint policy:
OriginEndpoint endpoint;
ChannelGroup group;
new Distribution(this, "Distribution", new DistributionProps {
DefaultBehavior = new BehaviorOptions {
Origin = new MediaPackageV2Origin(endpoint, new MediaPackageV2OriginProps {
ChannelGroup = group
})
}
});
This handles OAC creation, HTTPS-only origin config, and the IAM policy granting CloudFront access to the endpoint (including GetHeadObject for MQAR support).
For more control, you can manually configure the policy and OAC:
OriginEndpoint originEndpoint;
Distribution distribution;
originEndpoint.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps {
Sid = "AllowCloudFrontServicePrincipal",
Principals = new [] { new ServicePrincipal("cloudfront.amazonaws.com") },
Effect = Effect.ALLOW,
Actions = new [] { "mediapackagev2:GetObject", "mediapackagev2:GetHeadObject" },
Resources = new [] { originEndpoint.OriginEndpointArn },
Conditions = new Dictionary<string, object> {
{ "StringEquals", new Dictionary<string, string> {
{ "aws:SourceArn", distribution.DistributionArn }
} }
}
}));
Graduation plan:
MediaPackageV2Origincurrently lives in this alpha module. When MediaPackage V2 graduates to stable, it will move toaws-cloudfront-originsalongsideS3BucketOriginand other origin helpers.
Manifest Configuration
MediaPackage V2 supports multiple manifest formats: HLS, Low-Latency HLS (LL-HLS), DASH, and Microsoft Smooth Streaming (MSS).
HLS Manifests
Channel channel;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration {
ManifestName = "index",
ManifestWindow = Duration.Seconds(60),
ProgramDateTimeInterval = Duration.Seconds(60),
ScteAdMarkerHls = AdMarkerHls.DATERANGE
}) }
});
Low-Latency HLS Manifests
Channel channel;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.LowLatencyHLS(new LowLatencyHlsManifestConfiguration {
ManifestName = "index",
ManifestWindow = Duration.Seconds(30),
ProgramDateTimeInterval = Duration.Seconds(5),
ChildManifestName = "child"
}) }
});
DASH Manifests
Channel channel;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Dash(new DashManifestConfiguration {
ManifestName = "index",
ManifestWindow = Duration.Seconds(60),
MinBufferTime = Duration.Seconds(30),
MinUpdatePeriod = Duration.Seconds(10),
SegmentTemplateFormat = SegmentTemplateFormat.NUMBER_WITH_TIMELINE,
PeriodTriggers = new [] { DashPeriodTriggers.AVAILS, DashPeriodTriggers.DRM_KEY_ROTATION }
}) }
});
MSS Manifests
Channel channel;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Ism(),
Manifests = new [] { Manifest.Mss(new MssManifestConfiguration {
ManifestName = "index",
ManifestWindow = Duration.Seconds(60),
ManifestLayout = MssManifestLayout.COMPACT
}) }
});
Multiple Manifests
You can configure multiple manifest formats for a single origin endpoint:
Channel channel;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "hls" }), Manifest.Dash(new DashManifestConfiguration { ManifestName = "dash" }) }
});
| Segment type | Supported manifests |
|---|---|
| Segment.cmaf() | HLS, LL-HLS, DASH |
| Segment.ts() | HLS, LL-HLS |
| Segment.ism() | MSS |
Each origin endpoint has a single segment configuration. If you need segments with different configurations, use multiple origin endpoints on the same channel.
@see https://docs.aws.amazon.com/mediapackage/latest/userguide/endpoints-create.html
Manifest Filtering
Manifest filters control which variants are included in the manifest. Filters are type-safe and validated against the MediaPackage manifest filtering rules.
| Filter | Method |
|---|---|
| Audio / video bitrate | bitrate(), bitrateRange(), bitrateCombo() |
| Audio channels, sample rate, video height, framerate, trickplay height | numeric(), numericList(), numericRange(), numericCombo() |
| Audio codec | audioCodec(), audioCodecList() |
| Video codec | videoCodec(), videoCodecList() |
| Video dynamic range | videoDynamicRange(), videoDynamicRangeList() |
| Trickplay type | trickplayType(), trickplayTypeList() |
| Audio / subtitle language | text(), textList() |
| Advanced patterns | custom() |
The following example creates an HD streaming endpoint that serves only H.264/H.265 content between 1–5 Mbps with stereo audio in English or French:
Channel channel;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration {
ManifestName = "index",
FilterConfiguration = new FilterConfiguration {
ManifestFilter = new [] { ManifestFilter.BitrateRange(BitrateFilterKey.VIDEO_BITRATE, Bitrate.Mbps(1), Bitrate.Mbps(5)), ManifestFilter.NumericRange(NumericFilterKey.VIDEO_HEIGHT, 720, 1080), ManifestFilter.VideoCodecList(new [] { VideoCodec.H264, VideoCodec.H265 }), ManifestFilter.Numeric(NumericFilterKey.AUDIO_CHANNELS, 2), ManifestFilter.TextList(TextFilterKey.AUDIO_LANGUAGE, new [] { "en-US", "fr" }) },
TimeDelay = Duration.Seconds(30)
}
}) }
});
For advanced patterns that combine ranges and single values, use numericCombo() or bitrateCombo():
Channel channel;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration {
ManifestName = "index",
FilterConfiguration = new FilterConfiguration {
ManifestFilter = new [] { ManifestFilter.NumericCombo(NumericFilterKey.VIDEO_HEIGHT, new [] { NumericExpression.Range(240, 360), NumericExpression.Range(720, 1080), NumericExpression.Value(1440) }) }
}
}) }
});
DRM Settings
You can exclude session keys from HLS and LL-HLS multivariant playlists using the drmSettings filter configuration. This improves compatibility with legacy HLS clients and provides more granular access control:
Channel channel;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration {
ManifestName = "index",
FilterConfiguration = new FilterConfiguration {
DrmSettings = new [] { DrmSettingsKey.EXCLUDE_SESSION_KEYS }
}
}) }
});
Start Tag Configuration
Configure where playback should start in HLS and LL-HLS manifests using the EXT-X-START tag:
Channel channel;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration {
ManifestName = "index",
StartTag = StartTag.Of(10)
}) }
});
Segment Configuration
Configure segment settings for your origin endpoint.
Channel channel;
new OriginEndpoint(this, "TsEndpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Ts(new TsSegmentProps {
Duration = Duration.Seconds(6),
Name = "segment",
IncludeDvbSubtitles = true,
UseAudioRenditionGroup = true,
IncludeIframeOnlyStreams = false,
ScteFilter = new [] { ScteMessageType.BREAK, ScteMessageType.DISTRIBUTOR_ADVERTISEMENT }
}),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "index" }) }
});
new OriginEndpoint(this, "CmafEndpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(new CmafSegmentProps {
Duration = Duration.Seconds(6),
Name = "segment",
IncludeIframeOnlyStreams = true,
ScteFilter = new [] { ScteMessageType.DISTRIBUTOR_ADVERTISEMENT }
}),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "index" }) }
});
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "index" }) }
});
Encryption and DRM
Protect your content with encryption using SPEKE (Secure Packager and Encoder Key Exchange). Each container type has its own encryption class with type-safe options:
CMAF Encryption
Channel channel;
IRole spekeRole;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(new CmafSegmentProps {
Encryption = CmafEncryption.Speke(new CmafSpekeEncryptionProps {
Method = CmafEncryptionMethod.CBCS,
DrmSystems = new [] { CmafDrmSystem.FAIRPLAY, CmafDrmSystem.WIDEVINE },
ResourceId = "my-content-id",
Url = "https://example.com/speke",
Role = spekeRole,
KeyRotationInterval = Duration.Seconds(300),
AudioPreset = PresetSpeke20Audio.PRESET_AUDIO_2,
VideoPreset = PresetSpeke20Video.PRESET_VIDEO_2
})
}),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "index" }) }
});
TS Encryption
Channel channel;
IRole spekeRole;
new OriginEndpoint(this, "TsEndpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Ts(new TsSegmentProps {
Encryption = TsEncryption.Speke(new TsSpekeEncryptionProps {
Method = TsEncryptionMethod.SAMPLE_AES,
ResourceId = "my-content-id",
Url = "https://example.com/speke",
Role = spekeRole
})
}),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "index" }) }
});
TS encryption defaults the DRM system based on the method: FairPlay for SAMPLE_AES, Clear Key AES 128 for AES_128. You can override this with the drmSystems property using TsDrmSystem.
Content Key Encryption
You can add content key encryption by providing a certificate imported into AWS Certificate Manager. Your DRM key provider must support content key encryption for this to work:
Channel channel;
IRole spekeRole;
ICertificate certificate;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(new CmafSegmentProps {
Encryption = CmafEncryption.Speke(new CmafSpekeEncryptionProps {
Method = CmafEncryptionMethod.CBCS,
DrmSystems = new [] { CmafDrmSystem.FAIRPLAY },
ResourceId = "my-content-id",
Url = "https://example.com/speke",
Role = spekeRole,
Certificate = certificate
})
}),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "index" }) }
});
Excluding Segment DRM Metadata
For CMAF content, you can exclude DRM metadata from segments:
Channel channel;
IRole spekeRole;
new OriginEndpoint(this, "Endpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Cmaf(new CmafSegmentProps {
Encryption = CmafEncryption.Speke(new CmafSpekeEncryptionProps {
Method = CmafEncryptionMethod.CBCS,
DrmSystems = new [] { CmafDrmSystem.FAIRPLAY },
ResourceId = "my-content-id",
Url = "https://example.com/speke",
Role = spekeRole,
ExcludeSegmentDrmMetadata = true
})
}),
Manifests = new [] { Manifest.Hls(new HlsManifestConfiguration { ManifestName = "index" }) }
});
ISM (Smooth Streaming) Encryption
ISM endpoints use CENC encryption with PlayReady. Audio and video presets are always SHARED, and key rotation is not supported. The DRM system defaults to PlayReady:
Channel channel;
IRole spekeRole;
new OriginEndpoint(this, "IsmEndpoint", new OriginEndpointProps {
Channel = channel,
Segment = Segment.Ism(new IsmSegmentProps {
Encryption = IsmEncryption.Speke(new IsmSpekeEncryptionProps {
ResourceId = "my-content-id",
Url = "https://example.com/speke",
Role = spekeRole
})
}),
Manifests = new [] { Manifest.Mss(new MssManifestConfiguration { ManifestName = "index" }) }
});
CloudWatch Metrics
MediaPackage V2 resources expose CloudWatch metrics for monitoring. You can create alarms and dashboards using these metrics:
ChannelGroup channelGroup;
Channel channel;
OriginEndpoint endpoint;
// Create a CloudWatch alarm on channel group egress bytes
var alarm = channelGroup.MetricEgressBytes().CreateAlarm(this, "HighEgress", new CreateAlarmOptions {
Threshold = 1000,
EvaluationPeriods = 1
});
// Monitor channel ingress response time
channel.MetricIngressResponseTime().CreateAlarm(this, "SlowIngress", new CreateAlarmOptions {
Threshold = 1000,
EvaluationPeriods = 2
});
// Track origin endpoint request count
var requestMetric = endpoint.MetricEgressRequestCount(new MetricOptions {
Statistic = "sum",
Period = Duration.Minutes(5)
});
Available metrics include:
metricIngressBytes()- Bytes ingestedmetricEgressBytes()- Bytes deliveredmetricIngressResponseTime()- Ingress response time (average)metricEgressResponseTime()- Egress response time (average)metricIngressRequestCount()- Number of ingress requestsmetricEgressRequestCount()- Number of egress requests
All metrics support standard CloudWatch metric options for customizing period, statistic, and dimensions.
Changes from Previous Version
Adoption Assessment
A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.
Related Guides & Workflows
Learn how to evaluate, integrate, or audit this package in your .NET project.