Skip to content

Latest commit

 

History

History
410 lines (384 loc) · 10.9 KB

MEDIAINSIGHTS.MD

File metadata and controls

410 lines (384 loc) · 10.9 KB

Amazon Chime SDK Media Insights Resources

Example

This example includes

Constructs used by Amazon Chime SDK call analytics configurations

const kinesisDataStream = new Stream(this, 'kinesisDataStream', {
  encryption: StreamEncryption.UNENCRYPTED,
  streamName: 'ChimeSDKMediaResourcesExample',
  shardCount: 4,
});

const lambdaSink = new Function(this, 'lambdaSink', {
  runtime: Runtime.PYTHON_3_9,
  code: Code.fromAsset('src/resources/mediaInsightPipelineSink'),
  handler: 'index.handler',
  architecture: Architecture.ARM_64,
});

const s3SinkBucket = new Bucket(this, 's3SinkBucket', {
  publicReadAccess: false,
  removalPolicy: RemovalPolicy.DESTROY,
  autoDeleteObjects: true,
});

const snsTopicSink = new Topic(this, 'snsTopicSink', {});

const sqsQueueSink = new Queue(this, 'sqsQueueSink', {});

IAM Policies and Role used by Amazon Chime SDK call analytics configurations

const kdsSinkPolicy = new PolicyDocument({
  statements: [
    new PolicyStatement({
      resources: [
        `arn:aws:kinesis:${Stack.of(this).region}:${
          Stack.of(this).account
        }:stream/${kinesisDataStream.streamName}`,
      ],
      actions: ['kinesis:PutRecord'],
    }),
    new PolicyStatement({
      resources: [
        `arn:aws:kms:${Stack.of(this).region}:${Stack.of(this).account}:key/*`,
      ],
      actions: ['kms:GenerateDataKey'],
      conditions: {
        StringLike: { 'aws:ResourceTag/AWSServiceName': 'ChimeSDK' },
      },
    }),
  ],
});

const s3SinkPolicy = new PolicyDocument({
  statements: [
    new PolicyStatement({
      resources: [s3SinkBucket.bucketArn],
      actions: ['s3:PutObject', 's3:PutObjectAcl', 's3:PutObjectTagging'],
    }),
    new PolicyStatement({
      resources: [
        `arn:aws:kinesisvideo:${Stack.of(this).region}:${
          Stack.of(this).account
        }:stream/*`,
      ],
      actions: [
        'kinesisvideo:GetDataEndpoint',
        'kinesisvideo:ListFragments',
        'kinesisvideo:GetMediaForFragmentList',
      ],
      conditions: {
        StringLike: { 'aws:ResourceTag/AWSServiceName': 'ChimeSDK' },
      },
    }),
    new PolicyStatement({
      resources: [
        `arn:aws:kinesisvideo:${Stack.of(this).region}:${
          Stack.of(this).account
        }:stream/Chime*`,
      ],
      actions: [
        'kinesisvideo:ListFragments',
        'kinesisvideo:GetMediaForFragmentList',
      ],
    }),
    new PolicyStatement({
      resources: [
        `arn:aws:kms:${Stack.of(this).region}:${Stack.of(this).account}:key/*`,
      ],
      actions: ['kms:GenerateDataKey'],
      conditions: {
        StringLike: { 'aws:ResourceTag/AWSServiceName': 'ChimeSDK' },
      },
    }),
  ],
});

const transcribeCallAnalyticsRole = new Role(
  this,
  'transcribeCallAnalyticsRole',
  {
    assumedBy: new PrincipalWithConditions(
      new ServicePrincipal('transcribe.streaming.amazonaws.com'),
      {
        StringEquals: {
          'aws:SourceAccount': Stack.of(this).account,
        },
        ArnLike: {
          'aws:SourceArn': `arn:aws:transcribe:*:${Stack.of(this).account}:*`,
        },
      },
    ),
    inlinePolicies: {
      ['s3OutputPolicy']: new PolicyDocument({
        statements: [
          new PolicyStatement({
            resources: [s3SinkBucket.bucketArn],
            actions: ['s3:PutObject'],
          }),
        ],
      }),
    },
  },
);

const amazonTranscribeCallAnalyticsProcessorPolicy = new PolicyDocument({
  statements: [
    new PolicyStatement({
      resources: [
        `arn:aws:iam::${Stack.of(this).account}:role/${
          transcribeCallAnalyticsRole.roleName
        }`,
      ],
      actions: ['iam:PassRole'],
      conditions: {
        StringEquals: {
          'iam:PassedToService': 'transcribe.streaming.amazonaws.com',
        },
      },
    }),
  ],
});

const lambdaSinkPolicy = new PolicyDocument({
  statements: [
    new PolicyStatement({
      actions: ['lambda:InvokeFunction', 'lambda:GetPolicy'],
      resources: [lambdaSink.functionArn],
    }),
  ],
});

const sqsSinkPolicy = new PolicyDocument({
  statements: [
    new PolicyStatement({
      actions: ['sqs:SendMessage', 'sqs:GetQueueAttributes'],
      resources: [sqsQueueSink.queueArn],
    }),
    new PolicyStatement({
      resources: [
        `arn:aws:kms:${Stack.of(this).region}:${Stack.of(this).account}:key/*`,
      ],
      actions: ['kms:GenerateDataKey', 'kms:Decrypt'],
      conditions: {
        StringLike: { 'aws:ResourceTag/AWSServiceName': 'ChimeSDK' },
      },
    }),
  ],
});

const snsTopicSinkPolicy = new PolicyDocument({
  statements: [
    new PolicyStatement({
      actions: ['sns:Publish', 'sns:GetTopicAttributes'],
      resources: [snsTopicSink.topicArn],
    }),
    new PolicyStatement({
      resources: [
        `arn:aws:kms:${Stack.of(this).region}:${Stack.of(this).account}:key/*`,
      ],
      actions: ['kms:GenerateDataKey', 'kms:Decrypt'],
      conditions: {
        StringLike: { 'aws:ResourceTag/AWSServiceName': 'ChimeSDK' },
      },
    }),
  ],
});

const resourceAccessRole = new Role(this, 'resourceAccessRole', {
  assumedBy: new PrincipalWithConditions(
    new ServicePrincipal('mediapipelines.chime.amazonaws.com'),
    {
      StringEquals: {
        'aws:SourceAccount': Stack.of(this).account,
      },
      ArnLike: {
        'aws:SourceArn': `arn:aws:chime:*:${Stack.of(this).account}:*`,
      },
    },
  ),
  inlinePolicies: {
    ['mediaInsightsPolicy']: new PolicyDocument({
      statements: [
        new PolicyStatement({
          resources: ['*'],
          actions: [
            'transcribe:StartCallAnalyticsStreamTranscription',
            'transcribe:StartStreamTranscription',
          ],
        }),
        new PolicyStatement({
          resources: [
            `arn:aws:kinesisvideo:${Stack.of(this).region}:${
              Stack.of(this).account
            }:stream/Chime*`,
          ],
          actions: ['kinesisvideo:GetDataEndpoint', 'kinesisvideo:GetMedia'],
        }),
        new PolicyStatement({
          resources: [
            `arn:aws:kinesisvideo:${Stack.of(this).region}:${
              Stack.of(this).account
            }:stream/*`,
          ],
          actions: ['kinesisvideo:GetDataEndpoint', 'kinesisvideo:GetMedia'],
          conditions: {
            StringLike: { 'aws:ResourceTag/AWSServiceName': 'ChimeSDK' },
          },
        }),
        new PolicyStatement({
          resources: [
            `arn:aws:kms:${Stack.of(this).region}:${
              Stack.of(this).account
            }:key/*`,
          ],
          actions: ['kms:Decrypt'],
          conditions: {
            StringLike: { 'aws:ResourceTag/AWSServiceName': 'ChimeSDK' },
          },
        }),
      ],
    }),
    ['lambdaSinkPolicy']: lambdaSinkPolicy,
    ['sqsSinkPolicy']: sqsSinkPolicy,
    ['snsTopicSinkPolicy']: snsTopicSinkPolicy,
    ['amazonTranscribeCallAnalyticsProcessorPolicy']:
      amazonTranscribeCallAnalyticsProcessorPolicy,
    ['kinesisDataStreamSinkPolicy']: kdsSinkPolicy,
    ['s3RecordingSinkPolicy']: s3SinkPolicy,
  },
});

Voice Analytics Configuration

const voiceAnalyticsConfiguration = new MediaInsightsPipeline(
  this,
  'voiceAnalyticsConfiguration',
  {
    resourceAccessRoleArn: resourceAccessRole.roleArn,
    mediaInsightsPipelineConfigurationName:
      'voiceAnalyticsConfigurationExample',
    elements: [
      {
        type: ElementsType.VOICE_ANALYTICS_PROCESSOR,
        voiceAnalyticsProcessorConfiguration: {
          speakerSearchStatus: SpeakerSearchStatus.ENABLED,
          voiceToneAnalysisStatus: VoiceToneAnalysisStatus.ENABLED,
        },
      },
      {
        type: ElementsType.LAMBDA_FUNCTION_SINK,
        lambdaFunctionSinkConfiguration: {
          insightsTarget: lambdaSink.functionArn,
        },
      },
      {
        type: ElementsType.SQS_QUEUE_SINK,
        sqsQueueSinkConfiguration: {
          insightsTarget: sqsQueueSink.queueArn,
        },
      },
      {
        type: ElementsType.SNS_TOPICS_SINK,
        snsTopicSinkConfiguration: {
          insightsTarget: snsTopicSink.topicArn,
        },
      },
      {
        type: ElementsType.KINESIS_DATA_STREAM_SINK,
        kinesisDataStreamSinkConfiguration: {
          insightsTarget: kinesisDataStream.streamArn,
        },
      },
    ],
  },
);

Transcribe Call Analytics Configuration

const transcribeCallAnalyticsConfiguration = new MediaInsightsPipeline(
  this,
  'transcribeCallAnalyticsConfiguration',
  {
    resourceAccessRoleArn: resourceAccessRole.roleArn,
    mediaInsightsPipelineConfigurationName:
      'transcribeCallAnalyticsConfigurationExample',
    elements: [
      {
        type: ElementsType.AMAZON_TRANSCRIPT_CALL_ANALYTICS_PROCESS,
        amazonTranscribeCallAnalyticsProcessorConfiguration: {
          languageCode: LanguageCode.EN_US,
        },
      },
      {
        type: ElementsType.KINESIS_DATA_STREAM_SINK,
        kinesisDataStreamSinkConfiguration: {
          insightsTarget: kinesisDataStream.streamArn,
        },
      },
    ],
    realTimeAlertConfiguration: {
      disabled: false,
      rules: [
        {
          type: RulesType.SENTIMENT,
          sentimentConfiguration: {
            ruleName: 'sentimentRuleName',
            sentimentType: SentimentType.NEGATIVE,
            timePeriod: 60,
          },
        },
        {
          type: RulesType.ISSUE_DETECTION,
          issueDetectionConfiguration: {
            ruleName: 'issueDetectionRuleName',
          },
        },
        {
          type: RulesType.KEYWORD_MATCH,
          keywordMatchConfiguration: {
            ruleName: 'keywordMatchRuleName',
            keywords: ['keyword'],
          },
        },
      ],
    },
  },
);

Recording Call Analytics Configuration

const s3RecordingSinkConfiguration = new MediaInsightsPipeline(
  this,
  's3RecordingSinkConfiguration',
  {
    resourceAccessRoleArn: resourceAccessRole.roleArn,
    mediaInsightsPipelineConfigurationName:
      's3RecordingSinkConfigurationExample',
    elements: [
      {
        type: ElementsType.S3_RECORDING_SINK,
        s3RecordingSinkConfiguration: {
          destination: s3SinkBucket.bucketArn,
        },
      },
    ],
  },
);

Amazon Chime SDK Voice Connector association

new ChimeVoiceConnector(this, 'voiceConnector', {
  encryption: false,
  region: 'us-east-1',
  termination: {
    terminationCidrs: ['198.51.100.0/27'],
    callingRegions: ['US'],
    cps: 1,
  },
  streaming: {
    enabled: true,
    dataRetention: 24,
    notificationTargets: [NotificationTargetType.EVENTBRIDGE],
    mediaInsightsConfiguration: {
      configurationArn:
        voiceAnalyticsConfiguration.mediaInsightsPipelineConfigurationArn,
      disabled: false,
    },
  },
  loggingConfiguration: {
    enableSIPLogs: true,
    enableMediaMetricLogs: true,
  },
});