Configure AWS Chime SDK Media Insights Pipelines

The aws:chimesdkmediapipelines/mediaInsightsPipelineConfiguration:MediaInsightsPipelineConfiguration resource, part of the Pulumi AWS provider, defines a media insights pipeline configuration that specifies how Chime SDK processes audio streams through transcription, analytics, and delivery to various sinks. This guide focuses on five capabilities: transcription with Call Analytics and standard Transcribe processors, PII redaction and post-call analytics storage, real-time alerting on keywords and sentiment, voice analytics for speaker identification, and multiple sink types for insights delivery.

Configurations reference IAM roles, Kinesis streams, Lambda functions, SNS topics, SQS queues, and S3 buckets that must exist separately. The examples are intentionally small. Combine them with your own IAM policies, streaming infrastructure, and notification targets.

Stream call analytics to Kinesis

Call analytics pipelines typically start by transcribing audio and streaming insights to Kinesis for real-time processing or downstream analytics.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.kinesis.Stream("example", {
    name: "example",
    shardCount: 2,
});
const mediaPipelinesAssumeRole = aws.iam.getPolicyDocument({
    statements: [{
        effect: "Allow",
        principals: [{
            type: "Service",
            identifiers: ["mediapipelines.chime.amazonaws.com"],
        }],
        actions: ["sts:AssumeRole"],
    }],
});
const callAnalyticsRole = new aws.iam.Role("call_analytics_role", {
    name: "CallAnalyticsRole",
    assumeRolePolicy: mediaPipelinesAssumeRole.then(mediaPipelinesAssumeRole => mediaPipelinesAssumeRole.json),
});
const myConfiguration = new aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration", {
    name: "MyBasicConfiguration",
    resourceAccessRoleArn: callAnalyticsRole.arn,
    elements: [
        {
            type: "AmazonTranscribeCallAnalyticsProcessor",
            amazonTranscribeCallAnalyticsProcessorConfiguration: {
                languageCode: "en-US",
            },
        },
        {
            type: "KinesisDataStreamSink",
            kinesisDataStreamSinkConfiguration: {
                insightsTarget: example.arn,
            },
        },
    ],
    tags: {
        Key1: "Value1",
        Key2: "Value2",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.kinesis.Stream("example",
    name="example",
    shard_count=2)
media_pipelines_assume_role = aws.iam.get_policy_document(statements=[{
    "effect": "Allow",
    "principals": [{
        "type": "Service",
        "identifiers": ["mediapipelines.chime.amazonaws.com"],
    }],
    "actions": ["sts:AssumeRole"],
}])
call_analytics_role = aws.iam.Role("call_analytics_role",
    name="CallAnalyticsRole",
    assume_role_policy=media_pipelines_assume_role.json)
my_configuration = aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration",
    name="MyBasicConfiguration",
    resource_access_role_arn=call_analytics_role.arn,
    elements=[
        {
            "type": "AmazonTranscribeCallAnalyticsProcessor",
            "amazon_transcribe_call_analytics_processor_configuration": {
                "language_code": "en-US",
            },
        },
        {
            "type": "KinesisDataStreamSink",
            "kinesis_data_stream_sink_configuration": {
                "insights_target": example.arn,
            },
        },
    ],
    tags={
        "Key1": "Value1",
        "Key2": "Value2",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/chimesdkmediapipelines"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kinesis"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := kinesis.NewStream(ctx, "example", &kinesis.StreamArgs{
			Name:       pulumi.String("example"),
			ShardCount: pulumi.Int(2),
		})
		if err != nil {
			return err
		}
		mediaPipelinesAssumeRole, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "Service",
							Identifiers: []string{
								"mediapipelines.chime.amazonaws.com",
							},
						},
					},
					Actions: []string{
						"sts:AssumeRole",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		callAnalyticsRole, err := iam.NewRole(ctx, "call_analytics_role", &iam.RoleArgs{
			Name:             pulumi.String("CallAnalyticsRole"),
			AssumeRolePolicy: pulumi.String(mediaPipelinesAssumeRole.Json),
		})
		if err != nil {
			return err
		}
		_, err = chimesdkmediapipelines.NewMediaInsightsPipelineConfiguration(ctx, "my_configuration", &chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs{
			Name:                  pulumi.String("MyBasicConfiguration"),
			ResourceAccessRoleArn: callAnalyticsRole.Arn,
			Elements: chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArray{
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("AmazonTranscribeCallAnalyticsProcessor"),
					AmazonTranscribeCallAnalyticsProcessorConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs{
						LanguageCode: pulumi.String("en-US"),
					},
				},
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("KinesisDataStreamSink"),
					KinesisDataStreamSinkConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs{
						InsightsTarget: example.Arn,
					},
				},
			},
			Tags: pulumi.StringMap{
				"Key1": pulumi.String("Value1"),
				"Key2": pulumi.String("Value2"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Kinesis.Stream("example", new()
    {
        Name = "example",
        ShardCount = 2,
    });

    var mediaPipelinesAssumeRole = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "mediapipelines.chime.amazonaws.com",
                        },
                    },
                },
                Actions = new[]
                {
                    "sts:AssumeRole",
                },
            },
        },
    });

    var callAnalyticsRole = new Aws.Iam.Role("call_analytics_role", new()
    {
        Name = "CallAnalyticsRole",
        AssumeRolePolicy = mediaPipelinesAssumeRole.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var myConfiguration = new Aws.ChimeSDKMediaPipelines.MediaInsightsPipelineConfiguration("my_configuration", new()
    {
        Name = "MyBasicConfiguration",
        ResourceAccessRoleArn = callAnalyticsRole.Arn,
        Elements = new[]
        {
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "AmazonTranscribeCallAnalyticsProcessor",
                AmazonTranscribeCallAnalyticsProcessorConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs
                {
                    LanguageCode = "en-US",
                },
            },
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "KinesisDataStreamSink",
                KinesisDataStreamSinkConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs
                {
                    InsightsTarget = example.Arn,
                },
            },
        },
        Tags = 
        {
            { "Key1", "Value1" },
            { "Key2", "Value2" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kinesis.Stream;
import com.pulumi.aws.kinesis.StreamArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.iam.Role;
import com.pulumi.aws.iam.RoleArgs;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Stream("example", StreamArgs.builder()
            .name("example")
            .shardCount(2)
            .build());

        final var mediaPipelinesAssumeRole = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("Service")
                    .identifiers("mediapipelines.chime.amazonaws.com")
                    .build())
                .actions("sts:AssumeRole")
                .build())
            .build());

        var callAnalyticsRole = new Role("callAnalyticsRole", RoleArgs.builder()
            .name("CallAnalyticsRole")
            .assumeRolePolicy(mediaPipelinesAssumeRole.json())
            .build());

        var myConfiguration = new MediaInsightsPipelineConfiguration("myConfiguration", MediaInsightsPipelineConfigurationArgs.builder()
            .name("MyBasicConfiguration")
            .resourceAccessRoleArn(callAnalyticsRole.arn())
            .elements(            
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("AmazonTranscribeCallAnalyticsProcessor")
                    .amazonTranscribeCallAnalyticsProcessorConfiguration(MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs.builder()
                        .languageCode("en-US")
                        .build())
                    .build(),
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("KinesisDataStreamSink")
                    .kinesisDataStreamSinkConfiguration(MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs.builder()
                        .insightsTarget(example.arn())
                        .build())
                    .build())
            .tags(Map.ofEntries(
                Map.entry("Key1", "Value1"),
                Map.entry("Key2", "Value2")
            ))
            .build());

    }
}
resources:
  myConfiguration:
    type: aws:chimesdkmediapipelines:MediaInsightsPipelineConfiguration
    name: my_configuration
    properties:
      name: MyBasicConfiguration
      resourceAccessRoleArn: ${callAnalyticsRole.arn}
      elements:
        - type: AmazonTranscribeCallAnalyticsProcessor
          amazonTranscribeCallAnalyticsProcessorConfiguration:
            languageCode: en-US
        - type: KinesisDataStreamSink
          kinesisDataStreamSinkConfiguration:
            insightsTarget: ${example.arn}
      tags:
        Key1: Value1
        Key2: Value2
  example:
    type: aws:kinesis:Stream
    properties:
      name: example
      shardCount: 2
  callAnalyticsRole:
    type: aws:iam:Role
    name: call_analytics_role
    properties:
      name: CallAnalyticsRole
      assumeRolePolicy: ${mediaPipelinesAssumeRole.json}
variables:
  mediaPipelinesAssumeRole:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            principals:
              - type: Service
                identifiers:
                  - mediapipelines.chime.amazonaws.com
            actions:
              - sts:AssumeRole

The elements array defines the processing pipeline: audio flows through the AmazonTranscribeCallAnalyticsProcessor for transcription, then insights stream to the KinesisDataStreamSink. The resourceAccessRoleArn grants the service permissions to invoke Transcribe and write to Kinesis. The languageCode property sets the transcription language, and insightsTarget specifies where insights are delivered.

Redact PII and enable post-call analytics

Compliance requirements often demand PII redaction during transcription and post-call analysis stored in S3 for audit trails.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const transcribeAssumeRole = aws.iam.getPolicyDocument({
    statements: [{
        effect: "Allow",
        principals: [{
            type: "Service",
            identifiers: ["transcribe.amazonaws.com"],
        }],
        actions: ["sts:AssumeRole"],
    }],
});
const postCallRole = new aws.iam.Role("post_call_role", {
    name: "PostCallAccessRole",
    assumeRolePolicy: transcribeAssumeRole.then(transcribeAssumeRole => transcribeAssumeRole.json),
});
const myConfiguration = new aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration", {
    name: "MyCallAnalyticsConfiguration",
    resourceAccessRoleArn: exampleAwsIamRole.arn,
    elements: [
        {
            type: "AmazonTranscribeCallAnalyticsProcessor",
            amazonTranscribeCallAnalyticsProcessorConfiguration: {
                callAnalyticsStreamCategories: [
                    "category_1",
                    "category_2",
                ],
                contentRedactionType: "PII",
                enablePartialResultsStabilization: true,
                filterPartialResults: true,
                languageCode: "en-US",
                languageModelName: "MyLanguageModel",
                partialResultsStability: "high",
                piiEntityTypes: "ADDRESS,BANK_ACCOUNT_NUMBER",
                postCallAnalyticsSettings: {
                    contentRedactionOutput: "redacted",
                    dataAccessRoleArn: postCallRole.arn,
                    outputEncryptionKmsKeyId: "MyKmsKeyId",
                    outputLocation: "s3://MyBucket",
                },
                vocabularyFilterMethod: "mask",
                vocabularyFilterName: "MyVocabularyFilter",
                vocabularyName: "MyVocabulary",
            },
        },
        {
            type: "KinesisDataStreamSink",
            kinesisDataStreamSinkConfiguration: {
                insightsTarget: example.arn,
            },
        },
    ],
});
import pulumi
import pulumi_aws as aws

transcribe_assume_role = aws.iam.get_policy_document(statements=[{
    "effect": "Allow",
    "principals": [{
        "type": "Service",
        "identifiers": ["transcribe.amazonaws.com"],
    }],
    "actions": ["sts:AssumeRole"],
}])
post_call_role = aws.iam.Role("post_call_role",
    name="PostCallAccessRole",
    assume_role_policy=transcribe_assume_role.json)
my_configuration = aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration",
    name="MyCallAnalyticsConfiguration",
    resource_access_role_arn=example_aws_iam_role["arn"],
    elements=[
        {
            "type": "AmazonTranscribeCallAnalyticsProcessor",
            "amazon_transcribe_call_analytics_processor_configuration": {
                "call_analytics_stream_categories": [
                    "category_1",
                    "category_2",
                ],
                "content_redaction_type": "PII",
                "enable_partial_results_stabilization": True,
                "filter_partial_results": True,
                "language_code": "en-US",
                "language_model_name": "MyLanguageModel",
                "partial_results_stability": "high",
                "pii_entity_types": "ADDRESS,BANK_ACCOUNT_NUMBER",
                "post_call_analytics_settings": {
                    "content_redaction_output": "redacted",
                    "data_access_role_arn": post_call_role.arn,
                    "output_encryption_kms_key_id": "MyKmsKeyId",
                    "output_location": "s3://MyBucket",
                },
                "vocabulary_filter_method": "mask",
                "vocabulary_filter_name": "MyVocabularyFilter",
                "vocabulary_name": "MyVocabulary",
            },
        },
        {
            "type": "KinesisDataStreamSink",
            "kinesis_data_stream_sink_configuration": {
                "insights_target": example["arn"],
            },
        },
    ])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/chimesdkmediapipelines"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		transcribeAssumeRole, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "Service",
							Identifiers: []string{
								"transcribe.amazonaws.com",
							},
						},
					},
					Actions: []string{
						"sts:AssumeRole",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		postCallRole, err := iam.NewRole(ctx, "post_call_role", &iam.RoleArgs{
			Name:             pulumi.String("PostCallAccessRole"),
			AssumeRolePolicy: pulumi.String(transcribeAssumeRole.Json),
		})
		if err != nil {
			return err
		}
		_, err = chimesdkmediapipelines.NewMediaInsightsPipelineConfiguration(ctx, "my_configuration", &chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs{
			Name:                  pulumi.String("MyCallAnalyticsConfiguration"),
			ResourceAccessRoleArn: pulumi.Any(exampleAwsIamRole.Arn),
			Elements: chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArray{
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("AmazonTranscribeCallAnalyticsProcessor"),
					AmazonTranscribeCallAnalyticsProcessorConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs{
						CallAnalyticsStreamCategories: pulumi.StringArray{
							pulumi.String("category_1"),
							pulumi.String("category_2"),
						},
						ContentRedactionType:              pulumi.String("PII"),
						EnablePartialResultsStabilization: pulumi.Bool(true),
						FilterPartialResults:              pulumi.Bool(true),
						LanguageCode:                      pulumi.String("en-US"),
						LanguageModelName:                 pulumi.String("MyLanguageModel"),
						PartialResultsStability:           pulumi.String("high"),
						PiiEntityTypes:                    pulumi.String("ADDRESS,BANK_ACCOUNT_NUMBER"),
						PostCallAnalyticsSettings: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationPostCallAnalyticsSettingsArgs{
							ContentRedactionOutput:   pulumi.String("redacted"),
							DataAccessRoleArn:        postCallRole.Arn,
							OutputEncryptionKmsKeyId: pulumi.String("MyKmsKeyId"),
							OutputLocation:           pulumi.String("s3://MyBucket"),
						},
						VocabularyFilterMethod: pulumi.String("mask"),
						VocabularyFilterName:   pulumi.String("MyVocabularyFilter"),
						VocabularyName:         pulumi.String("MyVocabulary"),
					},
				},
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("KinesisDataStreamSink"),
					KinesisDataStreamSinkConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs{
						InsightsTarget: pulumi.Any(example.Arn),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var transcribeAssumeRole = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "transcribe.amazonaws.com",
                        },
                    },
                },
                Actions = new[]
                {
                    "sts:AssumeRole",
                },
            },
        },
    });

    var postCallRole = new Aws.Iam.Role("post_call_role", new()
    {
        Name = "PostCallAccessRole",
        AssumeRolePolicy = transcribeAssumeRole.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var myConfiguration = new Aws.ChimeSDKMediaPipelines.MediaInsightsPipelineConfiguration("my_configuration", new()
    {
        Name = "MyCallAnalyticsConfiguration",
        ResourceAccessRoleArn = exampleAwsIamRole.Arn,
        Elements = new[]
        {
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "AmazonTranscribeCallAnalyticsProcessor",
                AmazonTranscribeCallAnalyticsProcessorConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs
                {
                    CallAnalyticsStreamCategories = new[]
                    {
                        "category_1",
                        "category_2",
                    },
                    ContentRedactionType = "PII",
                    EnablePartialResultsStabilization = true,
                    FilterPartialResults = true,
                    LanguageCode = "en-US",
                    LanguageModelName = "MyLanguageModel",
                    PartialResultsStability = "high",
                    PiiEntityTypes = "ADDRESS,BANK_ACCOUNT_NUMBER",
                    PostCallAnalyticsSettings = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationPostCallAnalyticsSettingsArgs
                    {
                        ContentRedactionOutput = "redacted",
                        DataAccessRoleArn = postCallRole.Arn,
                        OutputEncryptionKmsKeyId = "MyKmsKeyId",
                        OutputLocation = "s3://MyBucket",
                    },
                    VocabularyFilterMethod = "mask",
                    VocabularyFilterName = "MyVocabularyFilter",
                    VocabularyName = "MyVocabulary",
                },
            },
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "KinesisDataStreamSink",
                KinesisDataStreamSinkConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs
                {
                    InsightsTarget = example.Arn,
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.iam.Role;
import com.pulumi.aws.iam.RoleArgs;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationPostCallAnalyticsSettingsArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var transcribeAssumeRole = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("Service")
                    .identifiers("transcribe.amazonaws.com")
                    .build())
                .actions("sts:AssumeRole")
                .build())
            .build());

        var postCallRole = new Role("postCallRole", RoleArgs.builder()
            .name("PostCallAccessRole")
            .assumeRolePolicy(transcribeAssumeRole.json())
            .build());

        var myConfiguration = new MediaInsightsPipelineConfiguration("myConfiguration", MediaInsightsPipelineConfigurationArgs.builder()
            .name("MyCallAnalyticsConfiguration")
            .resourceAccessRoleArn(exampleAwsIamRole.arn())
            .elements(            
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("AmazonTranscribeCallAnalyticsProcessor")
                    .amazonTranscribeCallAnalyticsProcessorConfiguration(MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs.builder()
                        .callAnalyticsStreamCategories(                        
                            "category_1",
                            "category_2")
                        .contentRedactionType("PII")
                        .enablePartialResultsStabilization(true)
                        .filterPartialResults(true)
                        .languageCode("en-US")
                        .languageModelName("MyLanguageModel")
                        .partialResultsStability("high")
                        .piiEntityTypes("ADDRESS,BANK_ACCOUNT_NUMBER")
                        .postCallAnalyticsSettings(MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationPostCallAnalyticsSettingsArgs.builder()
                            .contentRedactionOutput("redacted")
                            .dataAccessRoleArn(postCallRole.arn())
                            .outputEncryptionKmsKeyId("MyKmsKeyId")
                            .outputLocation("s3://MyBucket")
                            .build())
                        .vocabularyFilterMethod("mask")
                        .vocabularyFilterName("MyVocabularyFilter")
                        .vocabularyName("MyVocabulary")
                        .build())
                    .build(),
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("KinesisDataStreamSink")
                    .kinesisDataStreamSinkConfiguration(MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs.builder()
                        .insightsTarget(example.arn())
                        .build())
                    .build())
            .build());

    }
}
resources:
  myConfiguration:
    type: aws:chimesdkmediapipelines:MediaInsightsPipelineConfiguration
    name: my_configuration
    properties:
      name: MyCallAnalyticsConfiguration
      resourceAccessRoleArn: ${exampleAwsIamRole.arn}
      elements:
        - type: AmazonTranscribeCallAnalyticsProcessor
          amazonTranscribeCallAnalyticsProcessorConfiguration:
            callAnalyticsStreamCategories:
              - category_1
              - category_2
            contentRedactionType: PII
            enablePartialResultsStabilization: true
            filterPartialResults: true
            languageCode: en-US
            languageModelName: MyLanguageModel
            partialResultsStability: high
            piiEntityTypes: ADDRESS,BANK_ACCOUNT_NUMBER
            postCallAnalyticsSettings:
              contentRedactionOutput: redacted
              dataAccessRoleArn: ${postCallRole.arn}
              outputEncryptionKmsKeyId: MyKmsKeyId
              outputLocation: s3://MyBucket
            vocabularyFilterMethod: mask
            vocabularyFilterName: MyVocabularyFilter
            vocabularyName: MyVocabulary
        - type: KinesisDataStreamSink
          kinesisDataStreamSinkConfiguration:
            insightsTarget: ${example.arn}
  postCallRole:
    type: aws:iam:Role
    name: post_call_role
    properties:
      name: PostCallAccessRole
      assumeRolePolicy: ${transcribeAssumeRole.json}
variables:
  transcribeAssumeRole:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            principals:
              - type: Service
                identifiers:
                  - transcribe.amazonaws.com
            actions:
              - sts:AssumeRole

The contentRedactionType and piiEntityTypes properties control what sensitive data gets redacted from transcripts. The postCallAnalyticsSettings block configures where Transcribe stores detailed analytics after the call ends: dataAccessRoleArn grants Transcribe permissions to write to S3, outputLocation specifies the bucket, and outputEncryptionKmsKeyId encrypts the stored data. Vocabulary filters mask or remove specific terms during transcription.

Trigger alerts on keywords and sentiment

Contact centers monitor calls for specific keywords, negative sentiment, or detected issues to route escalations or trigger supervisor notifications.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const myConfiguration = new aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration", {
    name: "MyRealTimeAlertConfiguration",
    resourceAccessRoleArn: callAnalyticsRole.arn,
    elements: [
        {
            type: "AmazonTranscribeCallAnalyticsProcessor",
            amazonTranscribeCallAnalyticsProcessorConfiguration: {
                languageCode: "en-US",
            },
        },
        {
            type: "KinesisDataStreamSink",
            kinesisDataStreamSinkConfiguration: {
                insightsTarget: example.arn,
            },
        },
    ],
    realTimeAlertConfiguration: {
        disabled: false,
        rules: [
            {
                type: "IssueDetection",
                issueDetectionConfiguration: {
                    ruleName: "MyIssueDetectionRule",
                },
            },
            {
                type: "KeywordMatch",
                keywordMatchConfiguration: {
                    keywords: [
                        "keyword1",
                        "keyword2",
                    ],
                    negate: false,
                    ruleName: "MyKeywordMatchRule",
                },
            },
            {
                type: "Sentiment",
                sentimentConfiguration: {
                    ruleName: "MySentimentRule",
                    sentimentType: "NEGATIVE",
                    timePeriod: 60,
                },
            },
        ],
    },
});
import pulumi
import pulumi_aws as aws

my_configuration = aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration",
    name="MyRealTimeAlertConfiguration",
    resource_access_role_arn=call_analytics_role["arn"],
    elements=[
        {
            "type": "AmazonTranscribeCallAnalyticsProcessor",
            "amazon_transcribe_call_analytics_processor_configuration": {
                "language_code": "en-US",
            },
        },
        {
            "type": "KinesisDataStreamSink",
            "kinesis_data_stream_sink_configuration": {
                "insights_target": example["arn"],
            },
        },
    ],
    real_time_alert_configuration={
        "disabled": False,
        "rules": [
            {
                "type": "IssueDetection",
                "issue_detection_configuration": {
                    "rule_name": "MyIssueDetectionRule",
                },
            },
            {
                "type": "KeywordMatch",
                "keyword_match_configuration": {
                    "keywords": [
                        "keyword1",
                        "keyword2",
                    ],
                    "negate": False,
                    "rule_name": "MyKeywordMatchRule",
                },
            },
            {
                "type": "Sentiment",
                "sentiment_configuration": {
                    "rule_name": "MySentimentRule",
                    "sentiment_type": "NEGATIVE",
                    "time_period": 60,
                },
            },
        ],
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/chimesdkmediapipelines"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := chimesdkmediapipelines.NewMediaInsightsPipelineConfiguration(ctx, "my_configuration", &chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs{
			Name:                  pulumi.String("MyRealTimeAlertConfiguration"),
			ResourceAccessRoleArn: pulumi.Any(callAnalyticsRole.Arn),
			Elements: chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArray{
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("AmazonTranscribeCallAnalyticsProcessor"),
					AmazonTranscribeCallAnalyticsProcessorConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs{
						LanguageCode: pulumi.String("en-US"),
					},
				},
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("KinesisDataStreamSink"),
					KinesisDataStreamSinkConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs{
						InsightsTarget: pulumi.Any(example.Arn),
					},
				},
			},
			RealTimeAlertConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationArgs{
				Disabled: pulumi.Bool(false),
				Rules: chimesdkmediapipelines.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArray{
					&chimesdkmediapipelines.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArgs{
						Type: pulumi.String("IssueDetection"),
						IssueDetectionConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleIssueDetectionConfigurationArgs{
							RuleName: pulumi.String("MyIssueDetectionRule"),
						},
					},
					&chimesdkmediapipelines.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArgs{
						Type: pulumi.String("KeywordMatch"),
						KeywordMatchConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleKeywordMatchConfigurationArgs{
							Keywords: pulumi.StringArray{
								pulumi.String("keyword1"),
								pulumi.String("keyword2"),
							},
							Negate:   pulumi.Bool(false),
							RuleName: pulumi.String("MyKeywordMatchRule"),
						},
					},
					&chimesdkmediapipelines.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArgs{
						Type: pulumi.String("Sentiment"),
						SentimentConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleSentimentConfigurationArgs{
							RuleName:      pulumi.String("MySentimentRule"),
							SentimentType: pulumi.String("NEGATIVE"),
							TimePeriod:    pulumi.Int(60),
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var myConfiguration = new Aws.ChimeSDKMediaPipelines.MediaInsightsPipelineConfiguration("my_configuration", new()
    {
        Name = "MyRealTimeAlertConfiguration",
        ResourceAccessRoleArn = callAnalyticsRole.Arn,
        Elements = new[]
        {
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "AmazonTranscribeCallAnalyticsProcessor",
                AmazonTranscribeCallAnalyticsProcessorConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs
                {
                    LanguageCode = "en-US",
                },
            },
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "KinesisDataStreamSink",
                KinesisDataStreamSinkConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs
                {
                    InsightsTarget = example.Arn,
                },
            },
        },
        RealTimeAlertConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationArgs
        {
            Disabled = false,
            Rules = new[]
            {
                new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArgs
                {
                    Type = "IssueDetection",
                    IssueDetectionConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleIssueDetectionConfigurationArgs
                    {
                        RuleName = "MyIssueDetectionRule",
                    },
                },
                new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArgs
                {
                    Type = "KeywordMatch",
                    KeywordMatchConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleKeywordMatchConfigurationArgs
                    {
                        Keywords = new[]
                        {
                            "keyword1",
                            "keyword2",
                        },
                        Negate = false,
                        RuleName = "MyKeywordMatchRule",
                    },
                },
                new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArgs
                {
                    Type = "Sentiment",
                    SentimentConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleSentimentConfigurationArgs
                    {
                        RuleName = "MySentimentRule",
                        SentimentType = "NEGATIVE",
                        TimePeriod = 60,
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationRealTimeAlertConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var myConfiguration = new MediaInsightsPipelineConfiguration("myConfiguration", MediaInsightsPipelineConfigurationArgs.builder()
            .name("MyRealTimeAlertConfiguration")
            .resourceAccessRoleArn(callAnalyticsRole.arn())
            .elements(            
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("AmazonTranscribeCallAnalyticsProcessor")
                    .amazonTranscribeCallAnalyticsProcessorConfiguration(MediaInsightsPipelineConfigurationElementAmazonTranscribeCallAnalyticsProcessorConfigurationArgs.builder()
                        .languageCode("en-US")
                        .build())
                    .build(),
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("KinesisDataStreamSink")
                    .kinesisDataStreamSinkConfiguration(MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs.builder()
                        .insightsTarget(example.arn())
                        .build())
                    .build())
            .realTimeAlertConfiguration(MediaInsightsPipelineConfigurationRealTimeAlertConfigurationArgs.builder()
                .disabled(false)
                .rules(                
                    MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArgs.builder()
                        .type("IssueDetection")
                        .issueDetectionConfiguration(MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleIssueDetectionConfigurationArgs.builder()
                            .ruleName("MyIssueDetectionRule")
                            .build())
                        .build(),
                    MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArgs.builder()
                        .type("KeywordMatch")
                        .keywordMatchConfiguration(MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleKeywordMatchConfigurationArgs.builder()
                            .keywords(                            
                                "keyword1",
                                "keyword2")
                            .negate(false)
                            .ruleName("MyKeywordMatchRule")
                            .build())
                        .build(),
                    MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleArgs.builder()
                        .type("Sentiment")
                        .sentimentConfiguration(MediaInsightsPipelineConfigurationRealTimeAlertConfigurationRuleSentimentConfigurationArgs.builder()
                            .ruleName("MySentimentRule")
                            .sentimentType("NEGATIVE")
                            .timePeriod(60)
                            .build())
                        .build())
                .build())
            .build());

    }
}
resources:
  myConfiguration:
    type: aws:chimesdkmediapipelines:MediaInsightsPipelineConfiguration
    name: my_configuration
    properties:
      name: MyRealTimeAlertConfiguration
      resourceAccessRoleArn: ${callAnalyticsRole.arn}
      elements:
        - type: AmazonTranscribeCallAnalyticsProcessor
          amazonTranscribeCallAnalyticsProcessorConfiguration:
            languageCode: en-US
        - type: KinesisDataStreamSink
          kinesisDataStreamSinkConfiguration:
            insightsTarget: ${example.arn}
      realTimeAlertConfiguration:
        disabled: false
        rules:
          - type: IssueDetection
            issueDetectionConfiguration:
              ruleName: MyIssueDetectionRule
          - type: KeywordMatch
            keywordMatchConfiguration:
              keywords:
                - keyword1
                - keyword2
              negate: false
              ruleName: MyKeywordMatchRule
          - type: Sentiment
            sentimentConfiguration:
              ruleName: MySentimentRule
              sentimentType: NEGATIVE
              timePeriod: 60

The realTimeAlertConfiguration defines rules that send EventBridge notifications when conditions are met during the call. Each rule has a type (IssueDetection, KeywordMatch, or Sentiment) and configuration: keywords lists terms to match, sentimentType specifies which sentiment triggers alerts, and timePeriod sets the evaluation window in seconds. These alerts fire while the call is active, enabling immediate intervention.

Analyze voice tone and speaker identity

Voice analytics identifies speakers and analyzes tone to detect customer satisfaction or agent performance patterns beyond transcript content.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const myConfiguration = new aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration", {
    name: "MyVoiceAnalyticsConfiguration",
    resourceAccessRoleArn: example.arn,
    elements: [
        {
            type: "VoiceAnalyticsProcessor",
            voiceAnalyticsProcessorConfiguration: {
                speakerSearchStatus: "Enabled",
                voiceToneAnalysisStatus: "Enabled",
            },
        },
        {
            type: "LambdaFunctionSink",
            lambdaFunctionSinkConfiguration: {
                insightsTarget: "arn:aws:lambda:us-west-2:1111111111:function:MyFunction",
            },
        },
        {
            type: "SnsTopicSink",
            snsTopicSinkConfiguration: {
                insightsTarget: "arn:aws:sns:us-west-2:1111111111:topic/MyTopic",
            },
        },
        {
            type: "SqsQueueSink",
            sqsQueueSinkConfiguration: {
                insightsTarget: "arn:aws:sqs:us-west-2:1111111111:queue/MyQueue",
            },
        },
        {
            type: "KinesisDataStreamSink",
            kinesisDataStreamSinkConfiguration: {
                insightsTarget: test.arn,
            },
        },
    ],
});
import pulumi
import pulumi_aws as aws

my_configuration = aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration",
    name="MyVoiceAnalyticsConfiguration",
    resource_access_role_arn=example["arn"],
    elements=[
        {
            "type": "VoiceAnalyticsProcessor",
            "voice_analytics_processor_configuration": {
                "speaker_search_status": "Enabled",
                "voice_tone_analysis_status": "Enabled",
            },
        },
        {
            "type": "LambdaFunctionSink",
            "lambda_function_sink_configuration": {
                "insights_target": "arn:aws:lambda:us-west-2:1111111111:function:MyFunction",
            },
        },
        {
            "type": "SnsTopicSink",
            "sns_topic_sink_configuration": {
                "insights_target": "arn:aws:sns:us-west-2:1111111111:topic/MyTopic",
            },
        },
        {
            "type": "SqsQueueSink",
            "sqs_queue_sink_configuration": {
                "insights_target": "arn:aws:sqs:us-west-2:1111111111:queue/MyQueue",
            },
        },
        {
            "type": "KinesisDataStreamSink",
            "kinesis_data_stream_sink_configuration": {
                "insights_target": test["arn"],
            },
        },
    ])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/chimesdkmediapipelines"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := chimesdkmediapipelines.NewMediaInsightsPipelineConfiguration(ctx, "my_configuration", &chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs{
			Name:                  pulumi.String("MyVoiceAnalyticsConfiguration"),
			ResourceAccessRoleArn: pulumi.Any(example.Arn),
			Elements: chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArray{
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("VoiceAnalyticsProcessor"),
					VoiceAnalyticsProcessorConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementVoiceAnalyticsProcessorConfigurationArgs{
						SpeakerSearchStatus:     pulumi.String("Enabled"),
						VoiceToneAnalysisStatus: pulumi.String("Enabled"),
					},
				},
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("LambdaFunctionSink"),
					LambdaFunctionSinkConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementLambdaFunctionSinkConfigurationArgs{
						InsightsTarget: pulumi.String("arn:aws:lambda:us-west-2:1111111111:function:MyFunction"),
					},
				},
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("SnsTopicSink"),
					SnsTopicSinkConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementSnsTopicSinkConfigurationArgs{
						InsightsTarget: pulumi.String("arn:aws:sns:us-west-2:1111111111:topic/MyTopic"),
					},
				},
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("SqsQueueSink"),
					SqsQueueSinkConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementSqsQueueSinkConfigurationArgs{
						InsightsTarget: pulumi.String("arn:aws:sqs:us-west-2:1111111111:queue/MyQueue"),
					},
				},
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("KinesisDataStreamSink"),
					KinesisDataStreamSinkConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs{
						InsightsTarget: pulumi.Any(test.Arn),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var myConfiguration = new Aws.ChimeSDKMediaPipelines.MediaInsightsPipelineConfiguration("my_configuration", new()
    {
        Name = "MyVoiceAnalyticsConfiguration",
        ResourceAccessRoleArn = example.Arn,
        Elements = new[]
        {
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "VoiceAnalyticsProcessor",
                VoiceAnalyticsProcessorConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementVoiceAnalyticsProcessorConfigurationArgs
                {
                    SpeakerSearchStatus = "Enabled",
                    VoiceToneAnalysisStatus = "Enabled",
                },
            },
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "LambdaFunctionSink",
                LambdaFunctionSinkConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementLambdaFunctionSinkConfigurationArgs
                {
                    InsightsTarget = "arn:aws:lambda:us-west-2:1111111111:function:MyFunction",
                },
            },
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "SnsTopicSink",
                SnsTopicSinkConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementSnsTopicSinkConfigurationArgs
                {
                    InsightsTarget = "arn:aws:sns:us-west-2:1111111111:topic/MyTopic",
                },
            },
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "SqsQueueSink",
                SqsQueueSinkConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementSqsQueueSinkConfigurationArgs
                {
                    InsightsTarget = "arn:aws:sqs:us-west-2:1111111111:queue/MyQueue",
                },
            },
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "KinesisDataStreamSink",
                KinesisDataStreamSinkConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs
                {
                    InsightsTarget = test.Arn,
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementVoiceAnalyticsProcessorConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementLambdaFunctionSinkConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementSnsTopicSinkConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementSqsQueueSinkConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var myConfiguration = new MediaInsightsPipelineConfiguration("myConfiguration", MediaInsightsPipelineConfigurationArgs.builder()
            .name("MyVoiceAnalyticsConfiguration")
            .resourceAccessRoleArn(example.arn())
            .elements(            
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("VoiceAnalyticsProcessor")
                    .voiceAnalyticsProcessorConfiguration(MediaInsightsPipelineConfigurationElementVoiceAnalyticsProcessorConfigurationArgs.builder()
                        .speakerSearchStatus("Enabled")
                        .voiceToneAnalysisStatus("Enabled")
                        .build())
                    .build(),
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("LambdaFunctionSink")
                    .lambdaFunctionSinkConfiguration(MediaInsightsPipelineConfigurationElementLambdaFunctionSinkConfigurationArgs.builder()
                        .insightsTarget("arn:aws:lambda:us-west-2:1111111111:function:MyFunction")
                        .build())
                    .build(),
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("SnsTopicSink")
                    .snsTopicSinkConfiguration(MediaInsightsPipelineConfigurationElementSnsTopicSinkConfigurationArgs.builder()
                        .insightsTarget("arn:aws:sns:us-west-2:1111111111:topic/MyTopic")
                        .build())
                    .build(),
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("SqsQueueSink")
                    .sqsQueueSinkConfiguration(MediaInsightsPipelineConfigurationElementSqsQueueSinkConfigurationArgs.builder()
                        .insightsTarget("arn:aws:sqs:us-west-2:1111111111:queue/MyQueue")
                        .build())
                    .build(),
                MediaInsightsPipelineConfigurationElementArgs.builder()
                    .type("KinesisDataStreamSink")
                    .kinesisDataStreamSinkConfiguration(MediaInsightsPipelineConfigurationElementKinesisDataStreamSinkConfigurationArgs.builder()
                        .insightsTarget(test.arn())
                        .build())
                    .build())
            .build());

    }
}
resources:
  myConfiguration:
    type: aws:chimesdkmediapipelines:MediaInsightsPipelineConfiguration
    name: my_configuration
    properties:
      name: MyVoiceAnalyticsConfiguration
      resourceAccessRoleArn: ${example.arn}
      elements:
        - type: VoiceAnalyticsProcessor
          voiceAnalyticsProcessorConfiguration:
            speakerSearchStatus: Enabled
            voiceToneAnalysisStatus: Enabled
        - type: LambdaFunctionSink
          lambdaFunctionSinkConfiguration:
            insightsTarget: arn:aws:lambda:us-west-2:1111111111:function:MyFunction
        - type: SnsTopicSink
          snsTopicSinkConfiguration:
            insightsTarget: arn:aws:sns:us-west-2:1111111111:topic/MyTopic
        - type: SqsQueueSink
          sqsQueueSinkConfiguration:
            insightsTarget: arn:aws:sqs:us-west-2:1111111111:queue/MyQueue
        - type: KinesisDataStreamSink
          kinesisDataStreamSinkConfiguration:
            insightsTarget: ${test.arn}

The VoiceAnalyticsProcessor enables speaker search and voice tone analysis through speakerSearchStatus and voiceToneAnalysisStatus properties. Unlike transcription processors, voice analytics can deliver insights to multiple sink types simultaneously: LambdaFunctionSink for custom processing, SnsTopicSink for notifications, SqsQueueSink for queued processing, and KinesisDataStreamSink for streaming analytics. Each sink’s insightsTarget property specifies the destination ARN.

Record raw audio to S3

Regulatory compliance or quality assurance workflows often require storing the original audio alongside transcripts and analytics.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const myConfiguration = new aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration", {
    name: "MyS3RecordingConfiguration",
    resourceAccessRoleArn: example.arn,
    elements: [{
        type: "S3RecordingSink",
        s3RecordingSinkConfiguration: {
            destination: "arn:aws:s3:::MyBucket",
        },
    }],
});
import pulumi
import pulumi_aws as aws

my_configuration = aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration("my_configuration",
    name="MyS3RecordingConfiguration",
    resource_access_role_arn=example["arn"],
    elements=[{
        "type": "S3RecordingSink",
        "s3_recording_sink_configuration": {
            "destination": "arn:aws:s3:::MyBucket",
        },
    }])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/chimesdkmediapipelines"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := chimesdkmediapipelines.NewMediaInsightsPipelineConfiguration(ctx, "my_configuration", &chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs{
			Name:                  pulumi.String("MyS3RecordingConfiguration"),
			ResourceAccessRoleArn: pulumi.Any(example.Arn),
			Elements: chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArray{
				&chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementArgs{
					Type: pulumi.String("S3RecordingSink"),
					S3RecordingSinkConfiguration: &chimesdkmediapipelines.MediaInsightsPipelineConfigurationElementS3RecordingSinkConfigurationArgs{
						Destination: pulumi.String("arn:aws:s3:::MyBucket"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var myConfiguration = new Aws.ChimeSDKMediaPipelines.MediaInsightsPipelineConfiguration("my_configuration", new()
    {
        Name = "MyS3RecordingConfiguration",
        ResourceAccessRoleArn = example.Arn,
        Elements = new[]
        {
            new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementArgs
            {
                Type = "S3RecordingSink",
                S3RecordingSinkConfiguration = new Aws.ChimeSDKMediaPipelines.Inputs.MediaInsightsPipelineConfigurationElementS3RecordingSinkConfigurationArgs
                {
                    Destination = "arn:aws:s3:::MyBucket",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfiguration;
import com.pulumi.aws.chimesdkmediapipelines.MediaInsightsPipelineConfigurationArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementArgs;
import com.pulumi.aws.chimesdkmediapipelines.inputs.MediaInsightsPipelineConfigurationElementS3RecordingSinkConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var myConfiguration = new MediaInsightsPipelineConfiguration("myConfiguration", MediaInsightsPipelineConfigurationArgs.builder()
            .name("MyS3RecordingConfiguration")
            .resourceAccessRoleArn(example.arn())
            .elements(MediaInsightsPipelineConfigurationElementArgs.builder()
                .type("S3RecordingSink")
                .s3RecordingSinkConfiguration(MediaInsightsPipelineConfigurationElementS3RecordingSinkConfigurationArgs.builder()
                    .destination("arn:aws:s3:::MyBucket")
                    .build())
                .build())
            .build());

    }
}
resources:
  myConfiguration:
    type: aws:chimesdkmediapipelines:MediaInsightsPipelineConfiguration
    name: my_configuration
    properties:
      name: MyS3RecordingConfiguration
      resourceAccessRoleArn: ${example.arn}
      elements:
        - type: S3RecordingSink
          s3RecordingSinkConfiguration:
            destination: arn:aws:s3:::MyBucket

The S3RecordingSink writes raw audio files to S3. The destination property specifies the bucket ARN where recordings are stored. This sink operates independently of processors, capturing audio without transcription or analysis.

Beyond these examples

These snippets focus on specific pipeline configuration features: transcription processors (Call Analytics and standard Transcribe), voice analytics and real-time alerting, and multiple sink types (Kinesis, Lambda, SNS, SQS, S3). They’re intentionally minimal rather than full call analytics solutions.

The examples reference pre-existing infrastructure such as IAM roles with service-specific permissions, Kinesis streams, Lambda functions, SNS topics, SQS queues, S3 buckets for recordings and post-call analytics, and KMS keys for encryption and custom vocabularies. They focus on configuring the pipeline rather than provisioning the surrounding infrastructure.

To keep things focused, common pipeline patterns are omitted, including:

  • IAM policy definitions for resource access roles
  • Kinesis stream configuration (shard count, retention)
  • Lambda function implementation for processing insights
  • EventBridge rule configuration for alert routing

These omissions are intentional: the goal is to illustrate how each pipeline feature is wired, not provide drop-in call analytics modules. See the Media Insights Pipeline Configuration resource reference for all available configuration options.

Let's configure AWS Chime SDK Media Insights Pipelines

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & IAM
What IAM permissions does the resource access role need?
Required IAM policies vary based on which processors you configure in elements. The role must allow the Chime SDK Media Pipelines service to invoke your selected processors and sinks.
What's the basic structure of a media insights pipeline configuration?
Every configuration requires elements (an array of processors and sinks), resourceAccessRoleArn (IAM role), and name. Processors transform media, while sinks deliver the processed data.
Processors & Sinks
What processor types can I use?
Three processor types are available: AmazonTranscribeCallAnalyticsProcessor for call analytics, AmazonTranscribeProcessor for transcription, and VoiceAnalyticsProcessor for speaker search and voice tone analysis.
What's the difference between the Transcribe processors?
AmazonTranscribeCallAnalyticsProcessor provides call analytics features like sentiment analysis and issue detection, while AmazonTranscribeProcessor focuses on transcription with content identification and speaker labels.
What sink types are available for delivering insights?
Five sink types: KinesisDataStreamSink, LambdaFunctionSink, SnsTopicSink, SqsQueueSink, and S3RecordingSink. Each delivers processed data to its respective AWS service.
Can I use multiple sinks in one configuration?
Yes, you can configure multiple sinks in the elements array. The voice analytics example demonstrates using four different sink types simultaneously.
Real-time Alerts & Advanced Features
How do I set up real-time alerts?
Configure realTimeAlertConfiguration with rules for IssueDetection, KeywordMatch, or Sentiment. Each rule type sends EventBridge notifications when conditions are met.
How do I enable post-call analytics?
Use AmazonTranscribeCallAnalyticsProcessor with postCallAnalyticsSettings, specifying dataAccessRoleArn, outputLocation (S3 bucket), and optional encryption settings.
Can I redact PII from transcriptions?
Yes, set contentRedactionType to PII in the Transcribe Call Analytics processor configuration, and optionally specify piiEntityTypes to target specific entity types like ADDRESS or BANK_ACCOUNT_NUMBER.

Using a different cloud?

Explore analytics guides for other cloud providers: