forked from aws/aws-cdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ivs): support recording configuration for channel (aws#31899)
### Issue # (if applicable) Closes aws#31780. ### Reason for this change To use recording configuration for IVS channel. ### Description of changes * Add `RecordingConfiguration` Construct. * Add `recordingConfiguration` property to the Channel. ### Description of how you validated changes Add unit tests and integ test. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
- Loading branch information
Showing
19 changed files
with
1,751 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
export * from './channel'; | ||
export * from './playback-key-pair'; | ||
export * from './recording-configuration'; | ||
export * from './rendition-configuration'; | ||
export * from './stream-key'; | ||
export * from './thumbnail-configuration'; | ||
export * from './util'; | ||
|
||
// AWS::IVS CloudFormation Resources: |
210 changes: 210 additions & 0 deletions
210
packages/@aws-cdk/aws-ivs-alpha/lib/recording-configuration.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
import { CfnRecordingConfiguration } from 'aws-cdk-lib/aws-ivs'; | ||
import { IBucket } from 'aws-cdk-lib/aws-s3'; | ||
import { Duration, Fn, IResource, Resource, Stack, Token } from 'aws-cdk-lib/core'; | ||
import { Construct } from 'constructs'; | ||
import { RenditionConfiguration } from './rendition-configuration'; | ||
import { ThumbnailConfiguration } from './thumbnail-configuration'; | ||
|
||
/** | ||
* Properties of the IVS Recording configuration | ||
*/ | ||
export interface RecordingConfigurationProps { | ||
/** | ||
* S3 bucket where recorded videos will be stored. | ||
*/ | ||
readonly bucket: IBucket; | ||
|
||
/** | ||
* The name of the Recording configuration. | ||
* The value does not need to be unique. | ||
* | ||
* @default - auto generate | ||
*/ | ||
readonly recordingConfigurationName?: string; | ||
|
||
/** | ||
* If a broadcast disconnects and then reconnects within the specified interval, | ||
* the multiple streams will be considered a single broadcast and merged together. | ||
* | ||
* `recordingReconnectWindow` must be between 0 and 300 seconds | ||
* | ||
* @default - 0 seconds (means disabled) | ||
*/ | ||
readonly recordingReconnectWindow?: Duration; | ||
|
||
/** | ||
* A rendition configuration describes which renditions should be recorded for a stream. | ||
* | ||
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ivs-recordingconfiguration-renditionconfiguration.html | ||
* | ||
* @default - no rendition configuration | ||
*/ | ||
readonly renditionConfiguration?: RenditionConfiguration; | ||
|
||
/** | ||
* A thumbnail configuration enables/disables the recording of thumbnails for a live session and controls the interval at which thumbnails are generated for the live session. | ||
* | ||
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ivs-recordingconfiguration-thumbnailconfiguration.html | ||
* | ||
* @default - no thumbnail configuration | ||
*/ | ||
readonly thumbnailConfiguration?:ThumbnailConfiguration; | ||
} | ||
|
||
/** | ||
* Represents the IVS Recording configuration. | ||
*/ | ||
export interface IRecordingConfiguration extends IResource { | ||
/** | ||
* The ID of the Recording configuration. | ||
* @attribute | ||
*/ | ||
readonly recordingConfigurationId: string; | ||
|
||
/** | ||
* The ARN of the Recording configuration. | ||
* @attribute | ||
*/ | ||
readonly recordingConfigurationArn: string; | ||
} | ||
|
||
/** | ||
* The IVS Recording configuration | ||
* | ||
* @resource AWS::IVS::RecordingConfiguration | ||
*/ | ||
export class RecordingConfiguration extends Resource implements IRecordingConfiguration { | ||
/** | ||
* Imports an IVS Recording Configuration from attributes. | ||
*/ | ||
public static fromRecordingConfigurationId(scope: Construct, id: string, | ||
recordingConfigurationId: string): IRecordingConfiguration { | ||
|
||
class Import extends Resource implements IRecordingConfiguration { | ||
public readonly recordingConfigurationId = recordingConfigurationId; | ||
public readonly recordingConfigurationArn = Stack.of(this).formatArn({ | ||
resource: 'recording-configuration', | ||
service: 'ivs', | ||
resourceName: recordingConfigurationId, | ||
}); | ||
} | ||
|
||
return new Import(scope, id); | ||
} | ||
|
||
/** | ||
* Imports an IVS Recording Configuration from its ARN | ||
*/ | ||
public static fromArn(scope: Construct, id: string, recordingConfigurationArn: string): IRecordingConfiguration { | ||
const resourceParts = Fn.split('/', recordingConfigurationArn); | ||
|
||
if (!resourceParts || resourceParts.length < 2) { | ||
throw new Error(`Unexpected ARN format: ${recordingConfigurationArn}`); | ||
} | ||
|
||
const recordingConfigurationId = Fn.select(1, resourceParts); | ||
|
||
class Import extends Resource implements IRecordingConfiguration { | ||
public readonly recordingConfigurationId = recordingConfigurationId; | ||
public readonly recordingConfigurationArn = recordingConfigurationArn; | ||
} | ||
|
||
return new Import(scope, id); | ||
} | ||
|
||
/** | ||
* The ID of the Recording configuration. | ||
* @attribute | ||
*/ | ||
readonly recordingConfigurationId: string; | ||
|
||
/** | ||
* The ARN of the Recording configuration. | ||
* @attribute | ||
*/ | ||
readonly recordingConfigurationArn: string; | ||
|
||
private readonly props: RecordingConfigurationProps; | ||
|
||
public constructor(scope: Construct, id: string, props: RecordingConfigurationProps) { | ||
super(scope, id, { | ||
physicalName: props.recordingConfigurationName, | ||
}); | ||
|
||
this.props = props; | ||
|
||
this.validateRecordingConfigurationName(); | ||
this.validateRecordingReconnectWindowSeconds(); | ||
|
||
const resource = new CfnRecordingConfiguration(this, 'Resource', { | ||
destinationConfiguration: { | ||
s3: { | ||
bucketName: this.props.bucket.bucketName, | ||
}, | ||
}, | ||
name: this.props.recordingConfigurationName, | ||
recordingReconnectWindowSeconds: this.props.recordingReconnectWindow?.toSeconds(), | ||
renditionConfiguration: this._renderRenditionConfiguration(), | ||
thumbnailConfiguration: this._renderThumbnailConfiguration(), | ||
}); | ||
|
||
this.recordingConfigurationId = resource.ref; | ||
this.recordingConfigurationArn = resource.attrArn; | ||
} | ||
|
||
private _renderRenditionConfiguration(): CfnRecordingConfiguration.RenditionConfigurationProperty | undefined { | ||
if (!this.props.renditionConfiguration) { | ||
return; | ||
} | ||
|
||
return { | ||
renditions: this.props.renditionConfiguration.renditions, | ||
renditionSelection: this.props.renditionConfiguration.renditionSelection, | ||
}; | ||
}; | ||
|
||
private _renderThumbnailConfiguration(): CfnRecordingConfiguration.ThumbnailConfigurationProperty | undefined { | ||
if (!this.props.thumbnailConfiguration) { | ||
return; | ||
} | ||
|
||
return { | ||
recordingMode: this.props.thumbnailConfiguration.recordingMode, | ||
resolution: this.props.thumbnailConfiguration.resolution, | ||
storage: this.props.thumbnailConfiguration.storage, | ||
targetIntervalSeconds: this.props.thumbnailConfiguration.targetInterval?.toSeconds(), | ||
}; | ||
}; | ||
|
||
private validateRecordingConfigurationName(): undefined { | ||
const recordingConfigurationName = this.props.recordingConfigurationName; | ||
|
||
if (recordingConfigurationName == undefined || Token.isUnresolved(recordingConfigurationName)) { | ||
return; | ||
} | ||
|
||
if (!/^[a-zA-Z0-9-_]*$/.test(recordingConfigurationName)) { | ||
throw new Error(`\`recordingConfigurationName\` must consist only of alphanumeric characters, hyphens or underbars, got: ${recordingConfigurationName}.`); | ||
} | ||
|
||
if (recordingConfigurationName.length > 128) { | ||
throw new Error(`\`recordingConfigurationName\` must be less than or equal to 128 characters, got: ${recordingConfigurationName.length} characters.`); | ||
} | ||
}; | ||
|
||
private validateRecordingReconnectWindowSeconds(): undefined { | ||
const recordingReconnectWindow = this.props.recordingReconnectWindow; | ||
|
||
if (recordingReconnectWindow === undefined || Token.isUnresolved(recordingReconnectWindow)) { | ||
return; | ||
} | ||
|
||
if (0 < recordingReconnectWindow.toMilliseconds() && recordingReconnectWindow.toMilliseconds() < Duration.seconds(1).toMilliseconds()) { | ||
throw new Error(`\`recordingReconnectWindow\` must be between 0 and 300 seconds, got ${recordingReconnectWindow.toMilliseconds()} milliseconds.`); | ||
} | ||
|
||
if (recordingReconnectWindow.toSeconds() > 300) { | ||
throw new Error(`\`recordingReconnectWindow\` must be between 0 and 300 seconds, got ${recordingReconnectWindow.toSeconds()} seconds.`); | ||
} | ||
}; | ||
} |
55 changes: 55 additions & 0 deletions
55
packages/@aws-cdk/aws-ivs-alpha/lib/rendition-configuration.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { Resolution } from './util'; | ||
|
||
/** | ||
* Rendition selection mode. | ||
*/ | ||
export enum RenditionSelection { | ||
/** | ||
* Record all available renditions. | ||
*/ | ||
ALL = 'ALL', | ||
|
||
/** | ||
* Does not record any video. This option is useful if you just want to record thumbnails. | ||
*/ | ||
NONE = 'NONE', | ||
|
||
/** | ||
* Select a subset of video renditions to record. | ||
*/ | ||
CUSTOM = 'CUSTOM', | ||
} | ||
|
||
/** | ||
* Rendition configuration for IVS Recording configuration | ||
*/ | ||
export class RenditionConfiguration { | ||
/** | ||
* Record all available renditions. | ||
*/ | ||
public static all(): RenditionConfiguration { | ||
return new RenditionConfiguration(RenditionSelection.ALL); | ||
} | ||
|
||
/** | ||
* Does not record any video. | ||
*/ | ||
public static none(): RenditionConfiguration { | ||
return new RenditionConfiguration(RenditionSelection.NONE); | ||
} | ||
|
||
/** | ||
* Record a subset of video renditions. | ||
* | ||
* @param renditions A list of which renditions are recorded for a stream. | ||
*/ | ||
public static custom(renditions: Resolution[]): RenditionConfiguration { | ||
return new RenditionConfiguration(RenditionSelection.CUSTOM, renditions); | ||
} | ||
|
||
/** | ||
* @param renditionSelection The set of renditions are recorded for a stream. | ||
* @param renditions A list of which renditions are recorded for a stream. If you do not specify this property, no resolution is selected. | ||
*/ | ||
private constructor(public readonly renditionSelection: RenditionSelection, public readonly renditions?: Resolution[]) { } | ||
} |
Oops, something went wrong.