你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 Play 操作为用户自定义语音提示

本指南将帮助你开始使用 Azure 通信服务通话自动化 SDK 提供的播放操作向参与者播放音频文件。

先决条件

对于 AI 功能

新建 C# 应用程序

在操作系统的控制台窗口中,使用 dotnet 命令创建新的 Web 应用程序。

dotnet new web -n MyApplication

安装 NuGet 包

可以从此处获取 NuGet 包(如果尚未获取)。

(可选)如果要使用音频文件播放提示,请准备音频文件

创建一个音频文件(如果还没有),用于向参与者播放提示和消息。 音频文件必须托管在 Azure 通信服务可访问的位置,并支持身份验证。 保留 URL 的副本,以便在请求播放音频文件时使用。 Azure 通信服务支持以下两种文件类型:具有 ID3V2TAG 的 MP3 文件具有单声道 16 位 PCM 和 16 KHz 采样率的 WAV 文件。 。

你可以使用我们的语音合成与音频内容创建工具来试验创建自己的音频文件。

(可选)将 Azure 认知服务连接到 Azure 通信服务

若要使用文本转语音功能,需要将 Azure 认知服务连接到 Azure 通信服务

建立呼叫

至此,你应该熟悉开始呼叫,如需了解有关拨打电话的详细信息,请遵循我们的快速入门。 还可以使用此处提供的代码片段来了解如何应答呼叫。

var callAutomationClient = new CallAutomationClient("<Azure Communication Services connection string>");   

var answerCallOptions = new AnswerCallOptions("<Incoming call context once call is connected>", new Uri("<https://sample-callback-uri>"))  

{  
    CallIntelligenceOptions = new CallIntelligenceOptions() { CognitiveServicesEndpoint = new Uri("<Azure Cognitive Services Endpoint>") } 
};  

var answerCallResult = await callAutomationClient.AnswerCallAsync(answerCallOptions); 

播放音频

建立呼叫后,有多种选择可用于播放音频。 你可以向加入呼叫的参与者播放音频,也可以向呼叫中的所有参与者播放音频。

播放源 - 音频文件

若要使用音频文件向参与者播放音频,需要确保音频文件是具有单声道和 16 KHz 的 WAV 文件。 若要播放音频文件,需要确保为 Azure 通信服务提供托管在 Azure 通信服务可以访问的位置的文件 URI。 SDK 中的 FileSource 类型可用于指定播放操作的音频文件。

var playSource = new FileSource(new Uri(audioUri));

//Multiple FileSource Prompts, if you want to play multiple audio files in one request you can provide them in a list.
//var playSources = new List<PlaySource>() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")) };

播放源 - 文本转语音

若要通过 Azure AI 服务使用文本转语音来播放音频,需要提供要播放的文本,以及 SourceLocale 和 VoiceKind 或要使用的 VoiceName。 我们支持受 Azure AI 服务支持的所有语音名称,可从此处获取完整列表。

String textToPlay = "Welcome to Contoso";

// Provide SourceLocale and VoiceKind to select an appropriate voice. 
var playSource = new TextSource(textToPlay, "en-US", VoiceKind.Female);

//Multiple TextSource prompt, if you want to play multiple text prompts in one request you can provide them in a list.
//var playSources = new List<PlaySource>() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new TextSource("recognize prompt two") { VoiceName = SpeechToTextVoice }, new TextSource(content) { VoiceName = SpeechToTextVoice } };
String textToPlay = "Welcome to Contoso"; 
 
// Provide VoiceName to select a specific voice. 
var playSource = new TextSource(textToPlay, "en-US-ElizabethNeural");

//Multiple TextSource prompt, if you want to play multiple text prompts in one request you can provide them in a list.
//var playSources = new List<PlaySource>() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new TextSource("recognize prompt two") { VoiceName = SpeechToTextVoice }, new TextSource(content) { VoiceName = SpeechToTextVoice } };

播放源 - 使用 SSML 进行文本转语音

若要使用 Azure AI 服务自定义文本转语音输出,可以在通过呼叫自动化调用播放操作时使用语音合成标记语言 SSML。 使用 SSML,你可以微调音调、暂停、改进发音、更改语速、调整音量,以及归属多个语音。

String ssmlToPlay = "<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\"><voice name=\"en-US-JennyNeural\">Hello World!</voice></speak>"; 

var playSource = new SsmlSource(ssmlToPlay);

自定义语音模型

如果你希望增强提示并包括自定义语音模型,播放操作“文本转语音”现在支持这些自定义语音。 如果你试图为客户提供更加本地化、个性化的体验,或者遇到默认模型可能无法覆盖你想要发音的单词和口音的情况,则这是一个很好的选择。 若要详细了解如何创建和部署自定义模型,请阅读此指南

自定义语音名称常规文本示例

String textToPlay = "Welcome to Contoso"; 
 
// Provide VoiceName and CustomVoiceEndpointId to select custom voice. 
var playSource = new TextSource(textToPlay)
    {
        VoiceName = "YourCustomVoiceName",
        CustomVoiceEndpointId = "YourCustomEndpointId"
    };

自定义语音名称 SSML 示例


var playSource = new SsmlSource(ssmlToPlay,"YourCustomEndpointId");

确定要用于播放音频的 playSource 后,可以选择是向特定参与者还是向所有参与者播放。

向所有参与者播放音频

在此方案中,将向通话中的所有参与者播放音频。

var playResponse = await callAutomationClient.GetCallConnection(callConnectionId) 
    .GetCallMedia() 
    .PlayToAllAsync(playSource); 

对插播的支持

在向所有参与者循环播放音频的场景中,例如等候大厅,你可以向大厅的参与者播放音频,并让他们随时了解自己在队列中的编号。 使用插播支持时,这将取消正在播放的音频并播放新消息。 然后,如果想要继续播放原始音频,则需发出另一个播放请求。

var GoodbyePlaySource = new TextSource("Good bye")
{
    VoiceName = "en-US-NancyNeural"
};

PlayToAllOptions playOptions = new PlayToAllOptions(GoodbyePlaySource)
{
    InterruptCallMediaOperation = false,
    OperationCallbackUri = new Uri(callbackUriHost),
    Loop = true
};

await callConnectionMedia.PlayToAllAsync(playOptions);

// Interrupt media with text source

// Option1:
var interrupt = new TextSource("Interrupt prompt message")
{
    VoiceName = "en-US-NancyNeural"
};

PlayToAllOptions playInterrupt = new PlayToAllOptions(interrupt)
{
    InterruptCallMediaOperation = true,
    OperationCallbackUri = new Uri(callbackUriHost),
    Loop = false
};

await callConnectionMedia.PlayToAllAsync(playInterrupt);

/*
Option2: Interrupt media with file source
var interruptFile = new FileSource(new Uri(<AUDIO URL>));
PlayToAllOptions playFileInterrupt = new PlayToAllOptions(interruptFile)
{
    InterruptCallMediaOperation = true,
    OperationCallbackUri = new Uri(callbackUriHost),
    Loop = false
};
await callConnectionMedia.PlayToAllAsync(playFileInterrupt);
*/

向特定参与者播放音频

在此方案中,将向特定参与者播放音频。

var playTo = new List<CommunicationIdentifier> { targetParticipant }; 
var playResponse = await callAutomationClient.GetCallConnection(callConnectionId) 
    .GetCallMedia() 
    .PlayAsync(playSource, playTo); 

播放多个音频提示

播放操作都支持仅通过一个请求发送多个播放源。 这意味着你可以一次性发送要播放的一组提示,而不是分别发出这些请求。

循环播放音频

可以使用循环选项播放保持音乐循环播放,直到应用程序准备好接受呼叫方为止。 或者根据应用程序业务逻辑将呼叫方推进到下一个逻辑步骤。

var playOptions = new PlayToAllOptions(playSource) 
{ 
    Loop = true 
}; 
var playResult = await callAutomationClient.GetCallConnection(callConnectionId) 
    .GetCallMedia() 
    .PlayToAllAsync(playOptions); 

通过音频文件缓存增强播放

如果要多次播放同一音频文件,应用程序可以向 Azure 通信服务提供音频文件的 sourceID。 Azure 通信服务会将此音频文件缓存 1 小时。

注意

缓存音频文件不适合动态提示。 如果将提供的 URL 更改为 Azure 通信服务,则不会立即更新缓存的 URL。 更新将在现有缓存过期后进行。

var playTo = new List<CommunicationIdentifier> { targetParticipant }; 
var playSource = new FileSource(new Uri(audioUri)) 
{ 
    PlaySourceCacheId = "<playSourceId>" 
}; 
var playResult = await callAutomationClient.GetCallConnection(callConnectionId) 
    .GetCallMedia() 
    .PlayAsync(playSource, playTo); 

处理播放操作事件更新

应用程序将在应答呼叫时提供给呼叫自动化服务的回拨 URL 上接收操作生命周期事件更新。 成功播放事件更新的示例。

如何反序列化 PlayCompleted 事件的示例:

if (acsEvent is PlayCompleted playCompleted) 
{ 
    logger.LogInformation("Play completed successfully, context={context}", playCompleted.OperationContext); 
} 

如何反序列化 PlayStarted 事件的示例:

if (acsEvent is PlayStarted playStarted) 
{ 
    logger.LogInformation("Play started successfully, context={context}", playStarted.OperationContext); 
} 

如何反序列化 PlayFailed 事件的示例:

if (acsEvent is PlayFailed playFailed) 
{ 
    if (MediaEventReasonCode.PlayDownloadFailed.Equals(playFailed.ReasonCode)) 
    { 
        logger.LogInformation("Play failed: download failed, context={context}", playFailed.OperationContext); 
    } 
    else if (MediaEventReasonCode.PlayInvalidFileFormat.Equals(playFailed.ReasonCode)) 
    { 
        logger.LogInformation("Play failed: invalid file format, context={context}", playFailed.OperationContext); 
    } 
    else 
    { 
        logger.LogInformation("Play failed, result={result}, context={context}", playFailed.ResultInformation?.Message, playFailed.OperationContext); 
    } 
} 

若要了解有关其他受支持事件的详细信息,请访问通话自动化概述文档

取消播放操作

取消所有媒体操作,所有待处理的媒体操作都会取消。 此操作还会取消其他排队的播放操作。

var cancelResult = await callAutomationClient.GetCallConnection(callConnectionId) 
    .GetCallMedia() 
    .CancelAllMediaOperationsAsync(); 

如何反序列化 PlayCanceled 事件的示例:

if (acsEvent is PlayCanceled playCanceled) 
{ 
    logger.LogInformation("Play canceled, context={context}", playCanceled.OperationContext); 
} 

先决条件

对于 AI 功能

创建新的 Java 应用程序

在终端或命令窗口中,导航到要在其中创建 Java 应用程序的目录。 运行此处显示的命令,以从 maven-archetype-quickstart 模板生成 Java 项目。

mvn archetype:generate -DgroupId=com.communication.quickstart -DartifactId=communication-quickstart -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

上一个命令创建一个与 artifactId 参数同名的目录。 在此目录下,src/main/java 目录包含项目源代码,src/test/java 目录包含测试源。

你会注意到,“生成”步骤创建了与 artifactId 同名的目录。 在此目录下,src/main/java 目录包含源代码,src/test/java 目录包含测试,pom.xml 文件是项目的项目对象模型 (POM)。

将应用程序的 POM 文件更新为使用 Java 8 或更高版本。

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

添加包引用

在 POM 文件中,为项目添加以下引用。

azure-communication-callautomation

Azure 通信服务呼叫自动化 SDK 包是从 Azure SDK 开发源中检索的。

<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-communication-callautomation</artifactId>
  <version>1.0.0</version>
</dependency>

(可选)如果要使用音频文件播放提示,请准备音频文件

创建一个音频文件(如果还没有),用于向参与者播放提示和消息。 音频文件必须托管在 Azure 通信服务可访问的位置,并支持身份验证。 保留 URL 的副本,以便在请求播放音频文件时使用。 Azure 通信服务支持以下两种文件类型:具有 ID3V2TAG 的 MP3 文件具有单声道 16 位 PCM 和 16 KHz 采样率的 WAV 文件。 。

你可以使用我们的语音合成与音频内容创建工具来试验创建自己的音频文件。

(可选)将 Azure 认知服务连接到 Azure 通信服务

若要使用文本转语音功能,需要将 Azure 认知服务连接到 Azure 通信服务

使用代码更新 App.java

在所选编辑器中,打开 App.java 文件,并通过使用代码更新 App.java 部分中提供的代码对其进行更新。

建立呼叫

至此,你应该熟悉开始呼叫,如需了解有关拨打电话的详细信息,请遵循我们的快速入门。 还可以使用此处提供的代码片段来了解如何应答呼叫。

CallIntelligenceOptions callIntelligenceOptions = new CallIntelligenceOptions().setCognitiveServicesEndpoint("https://sample-cognitive-service-resource.cognitiveservices.azure.com/"); 
answerCallOptions = new AnswerCallOptions("<Incoming call context>", "<https://sample-callback-uri>").setCallIntelligenceOptions(callIntelligenceOptions); 
Response<AnswerCallResult> answerCallResult = callAutomationClient 
    .answerCallWithResponse(answerCallOptions) 
    .block(); 

播放音频

建立呼叫后,有多种选择可用于播放音频。 你可以向加入呼叫的参与者播放音频,也可以向呼叫中的所有参与者播放音频。

播放源 - 音频文件

若要使用音频文件向参与者播放音频,需要确保音频文件是具有单声道和 16 KHz 的 WAV 文件。 若要播放音频文件,需要确保为 Azure 通信服务提供托管在 Azure 通信服务可以访问的位置的文件 URI。 SDK 中的 FileSource 类型可用于指定播放操作的音频文件。

var playSource = new FileSource(new Uri(audioUri));

/* Multiple FileSource Prompts
var p1 = new FileSource().setUrl("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav");
var p2 = new FileSource().setUrl("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav");

var playSources = new ArrayList();
playSources.add(p1);
playSources.add(p2);
*/

播放源 - 文本转语音

若要通过 Azure AI 服务使用文本转语音来播放音频,需要提供要播放的文本,以及 SourceLocale 和 VoiceKind 或要使用的 VoiceName。 我们支持受 Azure AI 服务支持的所有语音名称,可从此处获取完整列表。

// Provide SourceLocale and VoiceKind to select an appropriate voice.
var playSource = new TextSource() 
    .setText(textToPlay) 
    .setSourceLocale("en-US") 
    .setVoiceKind(VoiceKind.FEMALE);

/* Multiple Prompt list setup: Multiple TextSource prompt

var p1 = new TextSource().setText("recognize prompt one").setSourceLocale("en-US").setVoiceKind(VoiceKind.FEMALE);
var p2 = new TextSource().setText("recognize prompt two").setSourceLocale("en-US").setVoiceKind(VoiceKind.FEMALE);
var p3 = new TextSource().setText(content).setSourceLocale("en-US").setVoiceKind(VoiceKind.FEMALE);

var playSources = new ArrayList();
playSources.add(p1);
playSources.add(p2);
playSources.add(p3);
*/
// Provide VoiceName to select a specific voice.
var playSource = new TextSource() 
    .setText(textToPlay) 
    .setVoiceName("en-US-ElizabethNeural");

/* Multiple Prompt list setup: Multiple TextSource prompt

var p1 = new TextSource().setText("recognize prompt one").setVoiceName("en-US-NancyNeural");
var p2 = new TextSource().setText("recognize prompt two").setVoiceName("en-US-NancyNeural");
var p3 = new TextSource().setText(content).setVoiceName("en-US-NancyNeural");

var playSources = new ArrayList();
playSources.add(p1);
playSources.add(p2);
playSources.add(p3);
*/

播放源 - 文本转语音 SSML

String ssmlToPlay = "<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\"><voice name=\"en-US-JennyNeural\">Hello World!</voice></speak>"; 
var playSource = new SsmlSource() 
    .setSsmlText(ssmlToPlay);

自定义语音模型

如果你希望增强提示并包括自定义语音模型,播放操作“文本转语音”现在支持这些自定义语音。 如果你试图为客户提供更加本地化、个性化的体验,或者遇到默认模型可能无法覆盖你想要发音的单词和口音的情况,则这是一个很好的选择。 若要详细了解如何创建和部署自定义模型,请阅读此指南

自定义语音名称常规文本示例

// Provide VoiceName and  to select a specific voice.
var playSource = new TextSource() 
    .setText(textToPlay) 
    .setCustomVoiceName("YourCustomVoiceName")
    .setCustomVoiceEndpointId("YourCustomEndpointId");

自定义语音名称 SSML 示例

String ssmlToPlay = "<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\"><voice name=\"YourCustomVoiceName\">Hello World!</voice></speak>"; 
var playSource = new SsmlSource() 
    .setSsmlText(ssmlToPlay)
    .setCustomVoiceEndpointId("YourCustomEndpointId");

确定要用于播放音频的 playSource 后,可以选择是向特定参与者还是向所有参与者播放。

向所有参与者播放音频

在此方案中,将向通话中的所有参与者播放音频。

var playOptions = new PlayToAllOptions(playSource); 
var playResponse = callAutomationClient.getCallConnectionAsync(callConnectionId) 
    .getCallMediaAsync() 
    .playToAllWithResponse(playOptions) 
    .block(); 
log.info("Play result: " + playResponse.getStatusCode()); 

对插播的支持

在向所有参与者循环播放音频的场景中,例如等候大厅,你可以向大厅的参与者播放音频,并让他们随时了解自己在队列中的编号。 使用插播支持时,这将取消正在播放的音频并播放新消息。 然后,如果想要继续播放原始音频,则需发出另一个播放请求。

// Option1: Interrupt media with text source
var textPlay = new TextSource()
    .setText("First Interrupt prompt message")
    .setVoiceName("en-US-NancyNeural");

var playToAllOptions = new PlayToAllOptions(textPlay)
    .setLoop(false)
    .setOperationCallbackUrl(appConfig.getBasecallbackuri())
    .setInterruptCallMediaOperation(false);

client.getCallConnection(callConnectionId)
    .getCallMedia()
    .playToAllWithResponse(playToAllOptions, Context.NONE);

/*
Option2: Interrupt media with text source
client.getCallConnection(callConnectionId)
    .getCallMedia()
    .playToAll(textPlay);
*/

/*
Option1: Barge-in with file source
var interruptFile = new FileSource()
    .setUrl("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav");

var playFileOptions = new PlayToAllOptions(interruptFile)
    .setLoop(false)
    .setOperationCallbackUrl(appConfig.getBasecallbackuri())
    .setInterruptCallMediaOperation(true);

client.getCallConnection(callConnectionId)
    .getCallMedia()
    .playToAllWithResponse(playFileOptions, Context.NONE);

Option2: Barge-in with file source
client.getCallConnection(callConnectionId)
    .getCallMedia()
    .playToAll(interruptFile);
*/

向特定参与者播放音频

在此方案中,将向特定参与者播放音频。

var playTo = Arrays.asList(targetParticipant); 
var playOptions = new PlayOptions(playSource, playTo); 
var playResponse = callAutomationClient.getCallConnectionAsync(callConnectionId) 
    .getCallMediaAsync() 
    .playWithResponse(playOptions) 
    .block(); 

循环播放音频

可以使用循环选项播放保持音乐循环播放,直到应用程序准备好接受呼叫方为止。 或者根据应用程序业务逻辑将呼叫方推进到下一个逻辑步骤。

var playOptions = new PlayToAllOptions(playSource) 
    .setLoop(true); 
var playResponse = callAutomationClient.getCallConnectionAsync(callConnectionId) 
    .getCallMediaAsync() 
    .playToAllWithResponse(playOptions) 
    .block(); 

通过音频文件缓存增强播放

如果要多次播放同一音频文件,应用程序可以向 Azure 通信服务提供音频文件的 sourceID。 Azure 通信服务会将此音频文件缓存 1 小时。

注意

缓存音频文件不适合动态提示。 如果将提供的 URL 更改为 Azure 通信服务,则不会立即更新缓存的 URL。 更新将在现有缓存过期后进行。

var playTo = Arrays.asList(targetParticipant); 
var playSource = new FileSource() 
    .setUrl(audioUri) \
    .setPlaySourceCacheId("<playSourceId>"); 
var playOptions = new PlayOptions(playSource, playTo); 
var playResponse = callAutomationClient.getCallConnectionAsync(callConnectionId) 
    .getCallMediaAsync() 
    .playWithResponse(playOptions) 
    .block(); 

处理播放操作事件更新

应用程序将在应答呼叫时提供给呼叫自动化服务的回拨 URL 上接收操作生命周期事件更新。 成功播放事件更新的示例。

如何反序列化 PlayCompleted 事件的示例:

if (acsEvent instanceof PlayCompleted) { 
    PlayCompleted event = (PlayCompleted) acsEvent; 
    log.info("Play completed, context=" + event.getOperationContext()); 
} 

如何反序列化 PlayStarted 事件的示例:

if (acsEvent instanceof PlayStarted) { 
    PlayStarted event = (PlayStarted) acsEvent; 
    log.info("Play started, context=" + event.getOperationContext()); 
} 

如何反序列化 PlayFailed 事件的示例:

if (acsEvent instanceof PlayFailed) { 
    PlayFailed event = (PlayFailed) acsEvent; 
    if (ReasonCode.Play.DOWNLOAD_FAILED.equals(event.getReasonCode())) { 
        log.info("Play failed: download failed, context=" + event.getOperationContext()); 
    } else if (ReasonCode.Play.INVALID_FILE_FORMAT.equals(event.getReasonCode())) { 
        log.info("Play failed: invalid file format, context=" + event.getOperationContext()); 
    } else { 
        log.info("Play failed, result=" + event.getResultInformation().getMessage() + ", context=" + event.getOperationContext()); 
    } 
} 

若要了解有关其他受支持事件的详细信息,请访问通话自动化概述文档

取消播放操作

取消所有媒体操作,所有待处理的媒体操作都会取消。 此操作还会取消其他排队的播放操作。

var cancelResponse = callAutomationClient.getCallConnectionAsync(callConnectionId) 
    .getCallMediaAsync() 
    .cancelAllMediaOperationsWithResponse() 
    .block(); 
log.info("Cancel result: " + cancelResponse.getStatusCode()); 

如何反序列化 PlayCanceled 事件的示例:

if (acsEvent instanceof PlayCanceled) { 
    PlayCanceled event = (PlayCanceled) acsEvent; 
    log.info("Play canceled, context=" + event.getOperationContext()); 
} 

先决条件

对于 AI 功能

创建新的 JavaScript 应用程序

在项目目录中创建新的 JavaScript 应用程序。 使用以下命令,初始化新的 Node.js 项目。 这会为项目创建一个 package.json 文件,该文件用于管理项目的依赖项。

npm init -y

安装 Azure 通信服务呼叫自动化包

npm install @azure/communication-call-automation

例如,在项目目录中创建新的 JavaScript 文件,将其命名为 app.js。 在此文件中编写 JavaScript 代码。 通过以下命令,使用 Node.js 运行你的应用程序。 此代码执行已编写的 JavaScript 代码。

node app.js

(可选)如果要使用音频文件播放提示,请准备音频文件

创建一个音频文件(如果还没有),用于向参与者播放提示和消息。 音频文件必须托管在 Azure 通信服务可访问的位置,并支持身份验证。 保留 URL 的副本,以便在请求播放音频文件时使用。 Azure 通信服务支持以下两种文件类型:具有 ID3V2TAG 的 MP3 文件具有单声道 16 位 PCM 和 16 KHz 采样率的 WAV 文件

你可以使用我们的语音合成与音频内容创建工具来试验创建自己的音频文件。

(可选)将 Azure 认知服务连接到 Azure 通信服务

若要使用文本转语音功能,需要将 Azure 认知服务连接到 Azure 通信服务

建立呼叫

至此,你应该熟悉开始呼叫,如需了解有关拨打电话的详细信息,请遵循我们的快速入门。 还可以使用此处提供的代码片段来了解如何应答呼叫。

const callIntelligenceOptions: CallIntelligenceOptions = { "<https://sample-callback-uri>" }; 
        const answerCallOptions: AnswerCallOptions = { callIntelligenceOptions: callIntelligenceOptions };
  
await acsClient.answerCall("<Incoming call context>", "<https://sample-callback-uri>", answerCallOptions); 

播放音频

建立呼叫后,有多种选择可用于播放音频。 你可以向加入呼叫的参与者播放音频,也可以向呼叫中的所有参与者播放音频。

播放源 - 音频文件

若要使用音频文件向参与者播放音频,需要确保音频文件是具有单声道和 16 KHz 的 WAV 文件。 若要播放音频文件,需要确保为 Azure 通信服务提供托管在 Azure 通信服务可以访问的位置的文件 URI。 SDK 中的 FileSource 类型可用于指定播放操作的音频文件。

const playSource: FileSource = { url: audioUri, kind: "fileSource" };

播放源 - 文本转语音

若要通过 Azure AI 服务使用文本转语音来播放音频,需要提供要播放的文本,以及 SourceLocale 和 VoiceKind 或要使用的 VoiceName。 我们支持受 Azure AI 服务支持的所有语音名称,可从此处获取完整列表。

const textToPlay = "Welcome to Contoso"; 
// Provide SourceLocale and VoiceKind to select an appropriate voice. 
const playSource: TextSource = { text: textToPlay, sourceLocale: "en-US", voiceKind: VoiceKind.Female, kind: "textSource" }; 
const textToPlay = "Welcome to Contoso"; 
// Provide VoiceName to select a specific voice. 
const playSource: TextSource = { text: textToPlay, voiceName: "en-US-ElizabethNeural", kind: "textSource" }; 

播放源 - 使用 SSML 进行文本转语音

若要使用 Azure AI 服务自定义文本转语音输出,可以在通过呼叫自动化调用播放操作时使用语音合成标记语言 SSML。 使用 SSML,你可以微调音调、暂停、改进发音、更改语速、调整音量,以及归属多个语音。

const ssmlToPlay = "<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\"><voice name=\"en-US-JennyNeural\">Hello World!</voice></speak>"; 
const playSource: SsmlSource = { ssmlText: ssmlToPlay, kind: "ssmlSource" }; 

自定义语音模型

如果你希望增强提示并包括自定义语音模型,播放操作“文本转语音”现在支持这些自定义语音。 如果你试图为客户提供更加本地化、个性化的体验,或者遇到默认模型可能无法覆盖你想要发音的单词和口音的情况,则这是一个很好的选择。 若要详细了解如何创建和部署自定义模型,请阅读此指南

自定义语音名称常规文本示例

const textToPlay = "Welcome to Contoso";
// Provide VoiceName and CustomVoiceEndpointID to play your custom voice
const playSource: TextSource = { text: textToPlay, voiceName: "YourCustomVoiceName", customVoiceEndpointId: "YourCustomEndpointId"}

自定义语音名称 SSML 示例

const ssmlToPlay = "<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\"><voice name=\"YourCustomVoiceName\">Hello World!</voice></speak>"; 
const playSource: SsmlSource = { ssmlText: ssmlToPlay, kind: "ssmlSource", customVoiceEndpointId: "YourCustomEndpointId"}; 

确定要用于播放音频的 playSource 后,可以选择是向特定参与者还是向所有参与者播放。

播放音频 - 所有参与者

在此方案中,将向通话中的所有参与者播放音频。

await callAutomationClient.getCallConnection(callConnectionId) 
    .getCallMedia() 
    .playToAll([ playSource ]);

对插播的支持

在向所有参与者循环播放音频的场景中,例如等候大厅,你可以向大厅的参与者播放音频,并让他们随时了解自己在队列中的编号。 使用插播支持时,这将取消正在播放的音频并播放新消息。 然后,如果想要继续播放原始音频,则需发出另一个播放请求。

// Interrupt media with text source 
//Option1:

const playSource: TextSource = { text: "Interrupt prompt", voiceName: "en-US-NancyNeural", kind: "textSource" };

const interruptOption: PlayToAllOptions = { 
loop: false, 
interruptCallMediaOperation: true, 
operationContext: "interruptOperationContext", 
operationCallbackUrl: process.env.CALLBACK_URI + "/api/callbacks" 
}; 

await callConnectionMedia.playToAll([playSource], interruptOption); 

/*
// Interrupt media with file source 

Option2: 

const playSource: FileSource = { 
url: MEDIA_URI + "MainMenu.wav", 
kind: "fileSource" 
}; 

const interruptOption: PlayToAllOptions = { 
loop: false, 
interruptCallMediaOperation: true, 
operationContext: "interruptOperationContext", 
operationCallbackUrl: process.env.CALLBACK_URI + "/api/callbacks" 
}; 

await callConnectionMedia.playToAll([playSource], interruptOption); 
*/

播放音频 - 特定参与者

在此方案中,将向特定参与者播放音频。

await callAutomationClient.getCallConnection(callConnectionId) 
    .getCallMedia() 
    .play([ playSource ], [ targetParticipant ]); 

循环播放音频

可以使用循环选项播放保持音乐循环播放,直到应用程序准备好接受呼叫方为止。 或者根据应用程序业务逻辑将呼叫方推进到下一个逻辑步骤。

const playOptions: PlayOptions = { loop: true }; 
await callAutomationClient.getCallConnection(callConnectionId) 
    .getCallMedia() 
    .playToAll([ playSource ], playOptions); 

通过音频文件缓存增强播放

如果要多次播放同一音频文件,应用程序可以向 Azure 通信服务提供音频文件的 sourceID。 Azure 通信服务会将此音频文件缓存 1 小时。

注意

缓存音频文件不适合动态提示。 如果将提供的 URL 更改为 Azure 通信服务,则不会立即更新缓存的 URL。 更新将在现有缓存过期后进行。

const playSource: FileSource = { url: audioUri, playsourcacheid: "<playSourceId>", kind: "fileSource" }; 
await callAutomationClient.getCallConnection(callConnectionId) 
.getCallMedia() 
.play([ playSource ], [ targetParticipant ]);

处理播放操作事件更新

应用程序将在应答呼叫时提供给呼叫自动化服务的回拨 URL 上接收操作生命周期事件更新。

如何反序列化 PlayCompleted 事件的示例:

if (event.type === "Microsoft.Communication.PlayCompleted") { 
    console.log("Play completed, context=%s", eventData.operationContext); 
} 

如何反序列化 PlayFailed 事件的示例:

if (event.type === "Microsoft.Communication.PlayFailed") { 
    console.log("Play failed: data=%s", JSON.stringify(eventData)); 
} 

如何反序列化 PlayStarted 事件的示例:

if (event.type === "Microsoft.Communication.PlayStarted") { 
    console.log("Play started: data=%s", JSON.stringify(eventData)); 
} 

若要了解有关其他受支持事件的详细信息,请访问通话自动化概述文档

取消播放操作

取消所有媒体操作,所有待处理的媒体操作都会取消。 此操作还会取消其他排队的播放操作。

await callAutomationClient.getCallConnection(callConnectionId) 
.getCallMedia() 
.cancelAllOperations();

如何反序列化 PlayCanceled 事件的示例:

if (event.type === "Microsoft.Communication.PlayCanceled") {
    console.log("Play canceled, context=%s", eventData.operationContext);
}

先决条件

对于 AI 功能

创建新的 Python 应用程序

为你的项目设置 Python 虚拟环境

python -m venv play-audio-app

激活虚拟环境

在 Windows 上,使用以下命令:

.\ play-audio-quickstart \Scripts\activate

在 Unix 上,使用以下命令:

source play-audio-quickstart /bin/activate

安装 Azure 通信服务呼叫自动化包

pip install azure-communication-callautomation

例如,在项目目录中创建应用程序文件,将其命名为 app.js。 在此文件中编写 Python 代码。

通过以下命令使用 Python 运行应用程序以执行代码。

python app.py

(可选)如果要使用音频文件播放提示,请准备音频文件

创建一个音频文件(如果还没有),用于向参与者播放提示和消息。 音频文件必须托管在 Azure 通信服务可访问的位置,并支持身份验证。 保留 URL 的副本,以便在请求播放音频文件时使用。 Azure 通信服务支持以下两种文件类型:MP3具有单声道 16 位 PCM 和 16 KHz 采样率的 WAV 文件。 。

你可以使用我们的语音合成与音频内容创建工具来试验创建自己的音频文件。

(可选)将 Azure 认知服务连接到 Azure 通信服务

若要使用文本转语音功能,需要将 Azure 认知服务连接到 Azure 通信服务

建立呼叫

至此,你应该熟悉开始呼叫,如需了解有关拨打电话的详细信息,请遵循我们的快速入门。 还可以使用此处提供的代码片段来了解如何应答呼叫。

call_automation_client.answer_call(
    incoming_call_context="<Incoming call context>",
    callback_url="<https://sample-callback-uri>",
    cognitive_services_endpoint=COGNITIVE_SERVICE_ENDPOINT,
)

播放音频

建立呼叫后,有多种选择可用于播放音频。 你可以向加入呼叫的参与者播放音频,也可以向呼叫中的所有参与者播放音频。

播放源 - 音频文件

若要使用音频文件向参与者播放音频,需要确保音频文件是具有单声道和 16 KHz 的 WAV 文件。 若要播放音频文件,需要确保为 Azure 通信服务提供托管在 Azure 通信服务可以访问的位置的文件 URI。 SDK 中的 FileSource 类型可用于指定播放操作的音频文件。

play_source = FileSource(url=audioUri)

#Play multiple audio files
#file_source1 = FileSource(MAIN_MENU_PROMPT_URI) 
#file_source2 = FileSource(MAIN_MENU_PROMPT_URI) 
#
# play_sources = [file_source1, file_source2]
# 
# call_connection_client.play_media_to_all(
#     play_source=play_sources,
#     interrupt_call_media_operation=False,
#     operation_context="multiplePlayContext",
#     operation_callback_url=CALLBACK_EVENTS_URI,
#     loop=False
# )

播放源 - 文本转语音

若要通过 Azure AI 服务使用文本转语音来播放音频,需要提供要播放的文本,以及 SourceLocale 和 VoiceKind 或要使用的 VoiceName。 我们支持受 Azure AI 服务支持的所有语音名称,可从此处获取完整列表。

text_to_play = "Welcome to Contoso"

# Provide SourceLocale and VoiceKind to select an appropriate voice. 
play_source = TextSource(
    text=text_to_play, source_locale="en-US", voice_kind=VoiceKind.FEMALE
)
play_to = [target_participant]
call_automation_client.get_call_connection(call_connection_id).play_media(
    play_source=play_source, play_to=play_to
)

#Multiple text prompts
#play_source1 = TextSource(text="Hi, This is multiple play source one call media test.", source_locale="en-US", voice_kind=VoiceKind.FEMALE) 
#play_source2 = TextSource(text="Hi, This is multiple play source two call media test.", source_locale="en-US", voice_kind=VoiceKind.FEMALE)
#
#play_sources = [play_source1, play_source2]
#
#call_connection_client.play_media_to_all(
#    play_source=play_sources,
#    interrupt_call_media_operation=False,
#    operation_context="multiplePlayContext",
#    operation_callback_url=CALLBACK_EVENTS_URI,
#    loop=False
#)
text_to_play = "Welcome to Contoso"

# Provide VoiceName to select a specific voice. 
play_source = TextSource(text=text_to_play, voice_name="en-US-ElizabethNeural")
play_to = [target_participant]
call_automation_client.get_call_connection(call_connection_id).play_media(
    play_source=play_source, play_to=play_to
)

#Play multiple text prompts
#play_source1 = TextSource(text="Hi, This is multiple play source one call media test.", voice_name=SPEECH_TO_TEXT_VOICE) 
#play_source2 = TextSource(text="Hi, This is multiple play source two call media test.", voice_name=SPEECH_TO_TEXT_VOICE)
#
#play_sources = [play_source1, play_source2]
#
#call_connection_client.play_media_to_all(
#    play_source=play_sources,
#    interrupt_call_media_operation=False,
#    operation_context="multiplePlayContext",
#    operation_callback_url=CALLBACK_EVENTS_URI,
#    loop=False
#)

播放源 - 使用 SSML 进行文本转语音

若要使用 Azure AI 服务自定义文本转语音输出,可以在通过呼叫自动化调用播放操作时使用语音合成标记语言 SSML。 使用 SSML,你可以微调音调、暂停、改进发音、更改语速、调整音量,以及归属多个语音。

ssmlToPlay = '<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US"><voice name="en-US-JennyNeural">Hello World!</voice></speak>'

play_source = SsmlSource(ssml_text=ssmlToPlay)

play_to = [target_participant]

call_automation_client.get_call_connection(call_connection_id).play_media(
    play_source=play_source, play_to=play_to
)

自定义语音模型

如果你希望增强提示并包括自定义语音模型,播放操作“文本转语音”现在支持这些自定义语音。 如果你试图为客户提供更加本地化、个性化的体验,或者遇到默认模型可能无法覆盖你想要发音的单词和口音的情况,则这是一个很好的选择。 若要详细了解如何创建和部署自定义模型,请阅读此指南

自定义语音名称常规文本示例

text_to_play = "Welcome to Contoso"

# Provide VoiceName to select a specific voice. 
play_source = TextSource(text=text_to_play, voice_name="YourCustomVoiceName", custom_voice_endpoint_id = "YourCustomEndpointId")
play_to = [target_participant]
call_automation_client.get_call_connection(call_connection_id).play_media(
    play_source=play_source, play_to=play_to
)

自定义语音名称 SSML 示例

ssmlToPlay = '<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US"><voice name="YourCustomVoiceName">Hello World!</voice></speak>'

play_source = SsmlSource(ssml_text=ssmlToPlay, custom_voice_endpoint_id="YourCustomEndpointId")

play_to = [target_participant]

call_automation_client.get_call_connection(call_connection_id).play_media(
    play_source=play_source, play_to=play_to
)

确定要用于播放音频的 playSource 后,可以选择是向特定参与者还是向所有参与者播放。

播放音频 - 所有参与者

向通话中的所有参与者播放预录制的音频文件。

text_to_play = "Welcome to Contoso"

play_source = TextSource(text=text_to_play, voice_name="en-US-ElizabethNeural")

call_automation_client.get_call_connection(call_connection_id).play_media(
    play_source=play_source
)

对插播的支持

在向所有参与者循环播放音频的场景中,例如等候大厅,你可以向大厅的参与者播放音频,并让他们随时了解自己在队列中的编号。 使用插播支持时,这将取消正在播放的音频并播放新消息。 然后,如果想要继续播放原始音频,则需发出另一个播放请求。

# Interrupt media with text source
# Option 1
play_source = TextSource(text="This is interrupt call media test.", voice_name=SPEECH_TO_TEXT_VOICE)
call_connection_client.play_media_to_all(
    play_source, 
    interrupt_call_media_operation=True, 
    operation_context="interruptContext", 
    operation_callback_url=CALLBACK_EVENTS_URI, 
    loop=False
)

# Interrupt media with file source
# Option 2
#play_source = FileSource(MAIN_MENU_PROMPT_URI)
#call_connection_client.play_media_to_all(
#    play_source, 
#    interrupt_call_media_operation=True, 
#    operation_context="interruptContext", 
#    operation_callback_url=CALLBACK_EVENTS_URI, 
#    loop=False
#)

播放音频 - 特定参与者

向通话中的特定参与者播放预录制的音频文件。

play_to = [target_participant]

call_automation_client.get_call_connection(call_connection_id).play_media(
    play_source=play_source, play_to=play_to
)

循环播放音频

可以使用循环选项播放保持音乐循环播放,直到应用程序准备好接受呼叫方为止。 或者根据应用程序业务逻辑将呼叫方推进到下一个逻辑步骤。

text_to_play = "Welcome to Contoso"

play_source = TextSource(text=text_to_play, voice_name="en-US-ElizabethNeural")

call_automation_client.get_call_connection(call_connection_id).play_media(
    play_source=play_source, loop=True
)

通过音频文件缓存增强播放

如果要多次播放同一音频文件,应用程序可以向 Azure 通信服务提供音频文件的 sourceID。 Azure 通信服务会将此音频文件缓存 1 小时。

注意

缓存音频文件不适合动态提示。 如果将提供的 URL 更改为 Azure 通信服务,则不会立即更新缓存的 URL。 更新将在现有缓存过期后进行。

play_source = FileSource(url=audioUri, play_source_cache_id="<playSourceId>")

play_to = [target_participant]

call_automation_client.get_call_connection(call_connection_id).play_media(
    play_source=play_source, play_to=play_to
)

处理播放操作事件更新

应用程序将在应答呼叫时提供给呼叫自动化服务的回拨 URL 上接收操作生命周期事件更新。

如何反序列化 PlayCompleted 事件的示例:

if event.type == "Microsoft.Communication.PlayCompleted":

    app.logger.info("Play completed, context=%s", event.data.get("operationContext"))

如何反序列化 PlayStarted 事件的示例:

if event.type == "Microsoft.Communication.PlayStarted":

    app.logger.info("Play started, context=%s", event.data.get("operationContext"))

如何反序列化 PlayFailed 事件的示例:

if event.type == "Microsoft.Communication.PlayFailed":

    app.logger.info("Play failed: data=%s", event.data)

若要了解有关其他受支持事件的详细信息,请访问通话自动化概述文档

取消播放操作

取消所有媒体操作,所有待处理的媒体操作都会取消。 此操作还会取消其他排队的播放操作。

call_automation_client.get_call_connection(
    call_connection_id
).cancel_all_media_operations()

如何反序列化 PlayCanceled 事件的示例:

if event.type == "Microsoft.Communication.PlayCanceled":

    app.logger.info("Play canceled, context=%s", event.data.get("operationContext"))

事件代码

Status 代码 子代码 Message
PlayCompleted 200 0 操作已成功完成。
PlayCanceled 400 8508 操作失败,操作已取消。
PlayFailed 400 8535 操作失败,文件格式无效。
PlayFailed 400 8536 操作失败,无法下文件。
PlayFailed 400 8565 操作失败,对 Azure AI 服务的请求不正确。 检查输入参数。
PlayFailed 401 8565 操作失败,Azure AI 服务身份验证错误。
PlayFailed 403 8565 操作失败,禁止请求 Azure AI 服务,请求使用的免费订阅已用完配额。
PlayFailed 429 8565 操作失败,请求超出了 Azure AI 服务订阅允许的并发请求数。
PlayFailed 408 8565 操作失败,对 Azure AI 服务的请求已超时。
PlayFailed 500 9999 未知的内部服务器错误
PlayFailed 500 8572 由于播放服务关闭,操作失败。

已知限制

  • 文本转语音文本提示最多支持 400 个字符,如果你的提示超过此长度限制,建议对基于文本转语音的播放操作使用 SSML。
  • 对于超出语音服务配额限制的场景,可按照此处概述的步骤请求调高此限制。

清理资源

如果想要清理并删除通信服务订阅,可以删除资源或资源组。 删除资源组同时也会删除与之相关联的任何其他资源。 了解有关清理资源的详细信息。

后续步骤