AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Amazon Transcribe Live Call Analytics with Agent Assist - Amazon Chime SDK Voice Connector Call Transcriber Lambda Parameters: AudioFilePrefix: Type: String Default: lca-audio-recordings/ Description: >- The Amazon S3 prefix where the merged output audio files will be saved (must end in "/") CallAnalyticsPrefix: Type: String Default: lca-call-analytics/ Description: The Amazon S3 prefix where the post-call analytics files will be saved, when using analytics api mode (must end in "/") KinesisDataStreamName: Type: String Description: >- Name of Kinesis Data Stream to publish events to KinesisDataStreamArn: Type: String Description: >- Arn of Kinesis Data Stream to publish events to S3BucketName: Type: String Description: >- S3 Bucket name for recordings TranscribeApiMode: Type: String Default: analytics AllowedValues: - standard - analytics Description: Set the default operational mode for Transcribe IsPartialTranscriptEnabled: Type: String Default: 'true' Description: >- Enable partial transcripts to receive low latency evolving transcriptions for each conversation turn. Set to false to process only the final version of each conversation turn. AllowedValues: - 'true' - 'false' IsContentRedactionEnabled: Type: String Default: 'false' Description: >- Enable content redaction from Amazon Transcribe transcription output. This is only used when the 'en-US' language is selected in the TranscribeLanguageCode parameter. AllowedValues: - 'true' - 'false' TranscribeContentRedactionType: Type: String Default: PII Description: >- Type of content redaction from Amazon Transcribe transcription output AllowedValues: - PII TranscribeLanguageCode: Type: String Description: >- Language code to be used for Amazon Transcribe Default: en-US AllowedValues: - en-US - es-US - en-GB - fr-CA - fr-FR - en-AU - it-IT - de-DE - pt-BR - ja-JP - ko-KR - zh-CN TranscribePiiEntityTypes: Type: String # yamllint disable rule:line-length Default: BANK_ACCOUNT_NUMBER,BANK_ROUTING,CREDIT_DEBIT_NUMBER,CREDIT_DEBIT_CVV,CREDIT_DEBIT_EXPIRY,PIN,EMAIL,ADDRESS,NAME,PHONE,SSN # yamllint enable rule:line-length Description: >- Select the PII entity types you want to identify or redact. Remove the values that you don't want to redact from the default. DO NOT ADD CUSTOM VALUES HERE. CustomVocabularyName: Type: String Default: '' Description: >- The name of the vocabulary to use when processing the transcription job. Leave blank if no custom vocabulary to be used. If yes, the custom vocabulary must pre-exist in your account. CustomLanguageModelName: Type: String Default: '' Description: >- The name of the custom language model to use when processing the transcription job. Leave blank if no custom language model is to be used. If specified, the custom language model must pre-exist in your account, match the Language Code selected above, and use the 'Narrow Band' base model. SiprecLambdaHookFunctionArn: Default: '' Type: String AllowedPattern: '^(|arn:aws:lambda:.*)$' Description: > (Optional) Used only when CallAudioSource is set to 'Chime Voice Connector (SIPREC)'. If present, the specified Lambda function is invoked at the start of each call. The call start event from Amazon Chime SDK Voice Connector (containing SIPREC headers) is provided as input. The function must return a True/False flag to indicate if the call should be processed or ignored, a mapped CallId, an AgentId, and may be extended to support additional features in future. VoiceConnectorId: Type: String Default: '' Description: >- Voice connector Id for setting up EventBridge Rule to restrict events to specific Amazon Chime SDK Voice Connector. Resources: ########################################################################## # NodeJS Transcriber Lambda Layer ########################################################################## TranscriberLambdaLayer: Type: AWS::Serverless::LayerVersion Properties: CompatibleRuntimes: - nodejs14.x - nodejs16.x - nodejs18.x Description: > This is a layer with shared nodejs libraries for the LCA call transcriber and call analytics initialization Lambdas. ContentUri: ../lambda_layers/node_transcriber_layer/transcriber-layer.zip ########################################################################## # Call Transcriber ########################################################################## TranscriberCallEventTable: Type: AWS::DynamoDB::Table DeletionPolicy: Delete UpdateReplacePolicy: Delete Properties: AttributeDefinitions: # primary key attributes - AttributeName: PK AttributeType: S - AttributeName: SK AttributeType: S KeySchema: - AttributeName: PK KeyType: HASH - AttributeName: SK KeyType: RANGE BillingMode: PAY_PER_REQUEST PointInTimeRecoverySpecification: PointInTimeRecoveryEnabled: true SSESpecification: SSEEnabled: true TimeToLiveSpecification: AttributeName: ExpiresAfter Enabled: true StreamSpecification: StreamViewType: NEW_IMAGE CallTranscriberFunction: Type: AWS::Serverless::Function Properties: Architectures: - arm64 Description: >- AWS Lambda Function that will be triggered when a new call starts. This will read from the KVS streams, stitch the channels together, send audio to transcribe, and store the transcriptions in DynamoDB Handler: index.handler Layers: # periodically update the Lambda Insights Layer # https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html - !Sub 'arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension-Arm64:2' - !Ref TranscriberLambdaLayer Role: !GetAtt CallTranscriberFunctionRole.Arn Runtime: nodejs14.x MemorySize: 768 Timeout: 900 Tracing: Active Environment: Variables: TRANSCRIBE_API_MODE: !Ref TranscribeApiMode BUFFER_SIZE: '128' LAMBDA_INVOKE_TIMEOUT: '720000' KINESIS_STREAM_NAME: !Ref KinesisDataStreamName TRANSCRIBER_CALL_EVENT_TABLE_NAME: !Ref TranscriberCallEventTable REGION: !Ref AWS::Region OUTPUT_BUCKET: !Ref S3BucketName RAW_FILE_PREFIX: 'lca-audio-raw/' RECORDING_FILE_PREFIX: !Ref AudioFilePrefix CALL_ANALYTICS_FILE_PREFIX: !Ref CallAnalyticsPrefix TCA_DATA_ACCESS_ROLE_ARN: !GetAtt TcaDataAccessRole.Arn POST_CALL_CONTENT_REDACTION_OUTPUT: 'redacted' TEMP_FILE_PATH: '/tmp/' SAVE_PARTIAL_TRANSCRIPTS: !Ref IsPartialTranscriptEnabled IS_CONTENT_REDACTION_ENABLED: !If - ShouldEnableContentRedaction - 'true' - 'false' TRANSCRIBE_LANGUAGE_CODE: !Ref TranscribeLanguageCode CONTENT_REDACTION_TYPE: !Ref TranscribeContentRedactionType PII_ENTITY_TYPES: !Ref TranscribePiiEntityTypes CUSTOM_VOCABULARY_NAME: !Ref CustomVocabularyName CUSTOM_LANGUAGE_MODEL_NAME: !Ref CustomLanguageModelName LAMBDA_HOOK_FUNCTION_ARN: !Ref SiprecLambdaHookFunctionArn CodeUri: ../lambda_functions/call_transcriber Metadata: cfn_nag: rules_to_suppress: - id: W89 reason: Customer can use VPC if desired CallTranscriberFunctionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: # CloudWatch Insights Managed Policy - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess Policies: - PolicyName: lambda-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - iam:PassRole Resource: - !GetAtt TcaDataAccessRole.Arn - Effect: Allow Action: - transcribe:DeleteTranscriptionJob - transcribe:GetTranscriptionJob - transcribe:GetVocabulary - transcribe:ListTranscriptionJobs - transcribe:ListVocabularies - transcribe:StartStreamTranscription - transcribe:StartCallAnalyticsStreamTranscription - transcribe:StartTranscriptionJob Resource: '*' - Action: - 'kinesisvideo:Describe*' - 'kinesisvideo:Get*' - 'kinesisvideo:List*' Effect: 'Allow' Resource: '*' - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:\ ${AWS::AccountId}:log-group:/aws/lambda/*" - Effect: Allow Action: - dynamodb:Query - dynamodb:Scan - dynamodb:GetItem - dynamodb:PutItem - dynamodb:UpdateItem Resource: - !GetAtt TranscriberCallEventTable.Arn - Action: - kinesis:PutRecord Effect: Allow Resource: - !Ref KinesisDataStreamArn - Effect: Allow Action: - s3:GetObject - s3:ListBucket - s3:PutObject - s3:DeleteObject Resource: - !Sub - 'arn:aws:s3:::${bucket}' - bucket: !Ref S3BucketName - !Sub - 'arn:aws:s3:::${bucket}/*' - bucket: !Ref S3BucketName - !If - ShouldEnableLambdaHook - Effect: Allow Action: - lambda:InvokeFunction Resource: !Sub '${SiprecLambdaHookFunctionArn}' - Ref: AWS::NoValue TcaDataAccessRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - transcribe.streaming.amazonaws.com Action: - sts:AssumeRole Path: / Policies: - PolicyName: tca-post-call-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - s3:GetObject - s3:ListBucket - s3:PutObject - s3:DeleteObject Resource: - !Sub - 'arn:aws:s3:::${bucket}' - bucket: !Ref S3BucketName - !Sub - 'arn:aws:s3:::${bucket}/*' - bucket: !Ref S3BucketName Metadata: cfn_nag: rules_to_suppress: - id: W11 reason: >- Transcribe does not support resource-level permissions and KVS streams are dynamic AllowEventBridgeToCallTranscriberFunctionLambdaFromChimeVC: Type: 'AWS::Lambda::Permission' Properties: FunctionName: !Ref CallTranscriberFunction Action: 'lambda:InvokeFunction' Principal: events.amazonaws.com SourceArn: !GetAtt EventBridgeRuleToTriggerCallTranscriberLambdaFromChimeVC.Arn SourceAccount: !Ref AWS::AccountId EventBridgeRuleToTriggerCallTranscriberLambdaFromChimeVC: Type: AWS::Events::Rule Properties: Description: 'This rule is triggered when the ChimeVC streaming status changes' EventPattern: detail: voiceConnectorId: - !Ref VoiceConnectorId detail-type: - 'Chime VoiceConnector Streaming Status' source: - aws.chime Targets: - Id: CallTranscriberTarget Arn: !GetAtt CallTranscriberFunction.Arn State: 'ENABLED' AllowEventBridgeToCallTranscriberFunctionLambdFromIVR: Type: 'AWS::Lambda::Permission' Properties: FunctionName: !Ref CallTranscriberFunction Action: 'lambda:InvokeFunction' Principal: events.amazonaws.com SourceArn: !GetAtt EventBridgeRuleToTriggerCallTranscriberLambdaFromIVR.Arn SourceAccount: !Ref AWS::AccountId EventBridgeRuleToTriggerCallTranscriberLambdaFromIVR: Type: AWS::Events::Rule Properties: Description: 'This rule is triggered when a START_CALL_PROCESSING event is sent from IVR' EventPattern: detail-type: - 'START_CALL_PROCESSING' source: - lca-solution Targets: - Id: CallTranscriberTarget Arn: !GetAtt CallTranscriberFunction.Arn State: 'ENABLED' # Permission for Call Transcriber to invoke itself CallTranscriberPermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !Ref CallTranscriberFunction Principal: !GetAtt CallTranscriberFunctionRole.Arn Metadata: 'AWS::CloudFormation::Interface': ParameterGroups: - Label: default: Amazon S3 Configuration Parameters: - S3BucketName - AudioFilePrefix - MonoAudioFilePrefix ParameterLabels: S3BucketName: default: Call Audio Bucket Name AudioFilePrefix: default: Audio File Prefix IsContentRedactionEnabled: default: Enable Content Redaction TranscribeContentRedactionType: default: Type of Content Redaction TranscribeLanguageCode: default: Transcription Language Code TranscribePiiEntityTypes: default: Transcription PII Redaction Entity Types CustomVocabularyName: default: Transcription Custom Vocabulary Name Conditions: ShouldEnableContentRedaction: !And - !Equals [!Ref IsContentRedactionEnabled, 'true'] - !Equals [!Ref TranscribeLanguageCode, 'en-US'] ShouldEnableLambdaHook: !Not [!Equals [!Ref SiprecLambdaHookFunctionArn, '']] Outputs: CallTranscriberEventTableName: Value: !Ref TranscriberCallEventTable CallTranscriberEventTableArn: Value: !GetAtt TranscriberCallEventTable.Arn IsContentRedactionEnabled: Value: !If - ShouldEnableContentRedaction - 'true' - 'false'