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

使用 Recognize 操作收集用户输入

本指南帮助你了解如何通过 Azure 通信服务通话自动化 SDK 来开始识别参与者提供的 DTMF 输入。

先决条件

对于 AI 功能

技术规范

以下参数可用于自定义 Recognize 函数:

参数 类型 默认值(如果未指定) 说明 必需还是可选
Prompt

(有关详细信息,请参阅使用播放操作为用户自定义语音提示
FileSource、TextSource 未设置 在识别输入之前要播放的消息。 可选
InterToneTimeout TimeSpan 2 秒

最小值:1 秒
最大值:60 秒
Azure 通信服务等待呼叫者按另一个数字的秒数限制(数字间超时)。 可选
InitialSegmentationSilenceTimeoutInSeconds 整数 0.5 秒 识别操作在考虑超时之前将等待输入多长时间。 请参阅如何识别语音 可选
RecognizeInputsType Enum dtmf 识别的输入的类型。 选项包括 dtmfchoicesspeechspeechordtmf 必须
InitialSilenceTimeout TimeSpan 5 秒

最小值:0 秒
最大值:300 秒 (DTMF)
最大值:20 秒 (Choices)
最大值:20 秒 (Speech)
初始静音超时调整在识别尝试以“不匹配”结果结束之前,在一个短语之前允许的非语音音频量。 请参阅如何识别语音 可选
MaxTonesToCollect 整数 无默认值

最小值:1
开发人员期望参与者输入的位数。 必须
StopTones IEnumeration<DtmfTone> 未设置 数字参与者可以按压以退出批量 DTMF 事件。 可选
InterruptPrompt Bool True 如果参与者能够通过按一个数字来中断 playMessage。 可选
InterruptCallMediaOperation Bool True 如果设置此标志,则会中断当前的调用媒体操作。 例如,如果正在播放任何音频,它会中断该操作并启动识别。 可选
OperationContext 字符串 未设置 开发人员可以传递 mid 操作的字符串,用于允许开发人员存储有关他们收到的事件的上下文。 可选
Phrases 字符串 未设置 与标签关联的短语列表。 听到其中任何一个短语都表示成功识别。 必须
Tone 字符串 未设置 用户决定按下数字而不是使用语音时,要识别的音调。 可选
Label 字符串 未设置 用于识别的关键值。 必须
Language 字符串 En-us 用于识别语音的语言。 可选
EndSilenceTimeout TimeSpan 0.5 秒 用于检测生成为语音的最终结果的说话人的最后一次暂停。 可选

注意

如果 DTMF 和语音都在 recognizeInputsType 中,则识别操作将作用于收到的第一个输入类型。 例如,如果用户首先按下小键盘上的数字,则识别操作会将其视为 DTMF 事件并继续侦听 DTMF 音调。 如果用户先说话,则识别操作会将其视为语音识别事件并侦听语音输入。

新建 C# 应用程序

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

dotnet new web -n MyApplication

安装 NuGet 包

NuGet 库 | Azure.Communication.CallAutomation 获取 NuGet 包。 按照说明安装相应的包。

建立呼叫

至此,你应已熟悉如何开始通话。 有关发起通话的详细信息,请参阅快速入门:发起传出通话。 还可以使用此处提供的代码片段来了解如何应答呼叫。

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); 

调用识别动作

在你的应用程序应答呼叫时,你可以提供有关识别参与者输入和播放提示的信息。

DTMF

var maxTonesToCollect = 3;
String textToPlay = "Welcome to Contoso, please enter 3 DTMF.";
var playSource = new TextSource(textToPlay, "en-US-ElizabethNeural");
var recognizeOptions = new CallMediaRecognizeDtmfOptions(targetParticipant, maxTonesToCollect) {
  InitialSilenceTimeout = TimeSpan.FromSeconds(30),
    Prompt = playSource,
    InterToneTimeout = TimeSpan.FromSeconds(5),
    InterruptPrompt = true,
    StopTones = new DtmfTone[] {
      DtmfTone.Pound
    },
};
var recognizeResult = await callAutomationClient.GetCallConnection(callConnectionId)
  .GetCallMedia()
  .StartRecognizingAsync(recognizeOptions);

对于语音转文本流,通话自动化识别操作还支持使用自定义语音识别模型。 在生成需要侦听默认语音转文本模型可能无法理解的复杂字词的应用程序时,自定义语音识别模型等功能可能非常有用。 例如,在为远程医疗行业生成应用程序,并且虚拟代理需要能够识别医疗术语时。 可以在创建自定义语音识别项目中了解详细信息。

语音转文本选择

var choices = new List < RecognitionChoice > {
  new RecognitionChoice("Confirm", new List < string > {
    "Confirm",
    "First",
    "One"
  }) {
    Tone = DtmfTone.One
  },
  new RecognitionChoice("Cancel", new List < string > {
    "Cancel",
    "Second",
    "Two"
  }) {
    Tone = DtmfTone.Two
  }
};
String textToPlay = "Hello, This is a reminder for your appointment at 2 PM, Say Confirm to confirm your appointment or Cancel to cancel the appointment. Thank you!";

var playSource = new TextSource(textToPlay, "en-US-ElizabethNeural");
var recognizeOptions = new CallMediaRecognizeChoiceOptions(targetParticipant, choices) {
  InterruptPrompt = true,
    InitialSilenceTimeout = TimeSpan.FromSeconds(30),
    Prompt = playSource,
    OperationContext = "AppointmentReminderMenu",
    //Only add the SpeechModelEndpointId if you have a custom speech model you would like to use
    SpeechModelEndpointId = "YourCustomSpeechModelEndpointId"
};
var recognizeResult = await callAutomationClient.GetCallConnection(callConnectionId)
  .GetCallMedia()
  .StartRecognizingAsync(recognizeOptions);

语音转文本

String textToPlay = "Hi, how can I help you today?";
var playSource = new TextSource(textToPlay, "en-US-ElizabethNeural");
var recognizeOptions = new CallMediaRecognizeSpeechOptions(targetParticipant) {
  Prompt = playSource,
    EndSilenceTimeout = TimeSpan.FromMilliseconds(1000),
    OperationContext = "OpenQuestionSpeech",
    //Only add the SpeechModelEndpointId if you have a custom speech model you would like to use
    SpeechModelEndpointId = "YourCustomSpeechModelEndpointId"
};
var recognizeResult = await callAutomationClient.GetCallConnection(callConnectionId)
  .GetCallMedia()
  .StartRecognizingAsync(recognizeOptions);

语音转文本或 DTMF

var maxTonesToCollect = 1; 
String textToPlay = "Hi, how can I help you today, you can press 0 to speak to an agent?"; 
var playSource = new TextSource(textToPlay, "en-US-ElizabethNeural"); 
var recognizeOptions = new CallMediaRecognizeSpeechOrDtmfOptions(targetParticipant, maxTonesToCollect) 
{ 
    Prompt = playSource, 
    EndSilenceTimeout = TimeSpan.FromMilliseconds(1000), 
    InitialSilenceTimeout = TimeSpan.FromSeconds(30), 
    InterruptPrompt = true, 
    OperationContext = "OpenQuestionSpeechOrDtmf",
    //Only add the SpeechModelEndpointId if you have a custom speech model you would like to use
    SpeechModelEndpointId = "YourCustomSpeechModelEndpointId" 
}; 
var recognizeResult = await callAutomationClient.GetCallConnection(callConnectionId) 
    .GetCallMedia() 
    .StartRecognizingAsync(recognizeOptions); 

注意

如果未设置参数,将尽可能应用默认值。

接收识别事件更新

开发人员可以订阅有关已注册 webhook 回调的 RecognizeCompletedRecognizeFailed 事件。 在应用程序中将此回调与业务逻辑配合使用可以确定当其中一个事件发生时要采取的后续步骤。

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

if (acsEvent is RecognizeCompleted recognizeCompleted) 
{ 
    switch (recognizeCompleted.RecognizeResult) 
    { 
        case DtmfResult dtmfResult: 
            //Take action for Recognition through DTMF 
            var tones = dtmfResult.Tones; 
            logger.LogInformation("Recognize completed succesfully, tones={tones}", tones); 
            break; 
        case ChoiceResult choiceResult: 
            // Take action for Recognition through Choices 
            var labelDetected = choiceResult.Label; 
            var phraseDetected = choiceResult.RecognizedPhrase; 
            // If choice is detected by phrase, choiceResult.RecognizedPhrase will have the phrase detected, 
            // If choice is detected using dtmf tone, phrase will be null 
            logger.LogInformation("Recognize completed succesfully, labelDetected={labelDetected}, phraseDetected={phraseDetected}", labelDetected, phraseDetected);
            break; 
        case SpeechResult speechResult: 
            // Take action for Recognition through Choices 
            var text = speechResult.Speech; 
            logger.LogInformation("Recognize completed succesfully, text={text}", text); 
            break; 
        default: 
            logger.LogInformation("Recognize completed succesfully, recognizeResult={recognizeResult}", recognizeCompleted.RecognizeResult); 
            break; 
    } 
} 

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

if (acsEvent is RecognizeFailed recognizeFailed) 
{ 
    if (MediaEventReasonCode.RecognizeInitialSilenceTimedOut.Equals(recognizeFailed.ReasonCode)) 
    { 
        // Take action for time out 
        logger.LogInformation("Recognition failed: initial silencev time out"); 
    } 
    else if (MediaEventReasonCode.RecognizeSpeechOptionNotMatched.Equals(recognizeFailed.ReasonCode)) 
    { 
        // Take action for option not matched 
        logger.LogInformation("Recognition failed: speech option not matched"); 
    } 
    else if (MediaEventReasonCode.RecognizeIncorrectToneDetected.Equals(recognizeFailed.ReasonCode)) 
    { 
        // Take action for incorrect tone 
        logger.LogInformation("Recognition failed: incorrect tone detected"); 
    } 
    else 
    { 
        logger.LogInformation("Recognition failed, result={result}, context={context}", recognizeFailed.ResultInformation?.Message, recognizeFailed.OperationContext); 
    } 
} 

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

if (acsEvent is RecognizeCanceled { OperationContext: "AppointmentReminderMenu" })
        {
            logger.LogInformation($"RecognizeCanceled event received for call connection id: {@event.CallConnectionId}");
            //Take action on recognize canceled operation
           await callConnection.HangUpAsync(forEveryone: true);
        }

先决条件

对于 AI 功能

技术规范

以下参数可用于自定义 Recognize 函数:

参数 类型 默认值(如果未指定) 说明 必需还是可选
Prompt

(有关详细信息,请参阅使用播放操作为用户自定义语音提示
FileSource、TextSource 未设置 在识别输入之前要播放的消息。 可选
InterToneTimeout TimeSpan 2 秒

最小值:1 秒
最大值:60 秒
Azure 通信服务等待呼叫者按另一个数字的秒数限制(数字间超时)。 可选
InitialSegmentationSilenceTimeoutInSeconds 整数 0.5 秒 识别操作在考虑超时之前将等待输入多长时间。 请参阅如何识别语音 可选
RecognizeInputsType Enum dtmf 识别的输入的类型。 选项包括 dtmfchoicesspeechspeechordtmf 必须
InitialSilenceTimeout TimeSpan 5 秒

最小值:0 秒
最大值:300 秒 (DTMF)
最大值:20 秒 (Choices)
最大值:20 秒 (Speech)
初始静音超时调整在识别尝试以“不匹配”结果结束之前,在一个短语之前允许的非语音音频量。 请参阅如何识别语音 可选
MaxTonesToCollect 整数 无默认值

最小值:1
开发人员期望参与者输入的位数。 必须
StopTones IEnumeration<DtmfTone> 未设置 数字参与者可以按压以退出批量 DTMF 事件。 可选
InterruptPrompt Bool True 如果参与者能够通过按一个数字来中断 playMessage。 可选
InterruptCallMediaOperation Bool True 如果设置此标志,则会中断当前的调用媒体操作。 例如,如果正在播放任何音频,它会中断该操作并启动识别。 可选
OperationContext 字符串 未设置 开发人员可以传递 mid 操作的字符串,用于允许开发人员存储有关他们收到的事件的上下文。 可选
Phrases 字符串 未设置 与标签关联的短语列表。 听到其中任何一个短语都表示成功识别。 必须
Tone 字符串 未设置 用户决定按下数字而不是使用语音时,要识别的音调。 可选
Label 字符串 未设置 用于识别的关键值。 必须
Language 字符串 En-us 用于识别语音的语言。 可选
EndSilenceTimeout TimeSpan 0.5 秒 用于检测生成为语音的最终结果的说话人的最后一次暂停。 可选

注意

如果 DTMF 和语音都在 recognizeInputsType 中,则识别操作将作用于收到的第一个输入类型。 例如,如果用户首先按下小键盘上的数字,则识别操作会将其视为 DTMF 事件并继续侦听 DTMF 音调。 如果用户先说话,则识别操作会将其视为语音识别事件并侦听语音输入。

创建新的 Java 应用程序

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

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

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

请注意,generate 步骤创建了一个与 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

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

建立呼叫

至此,你应已熟悉如何开始通话。 有关发起通话的详细信息,请参阅快速入门:发起传出通话。 还可以使用此处提供的代码片段来了解如何应答呼叫。

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();

调用识别动作

在你的应用程序应答呼叫时,你可以提供有关识别参与者输入和播放提示的信息。

DTMF

var maxTonesToCollect = 3;
String textToPlay = "Welcome to Contoso, please enter 3 DTMF.";
var playSource = new TextSource() 
    .setText(textToPlay) 
    .setVoiceName("en-US-ElizabethNeural");

var recognizeOptions = new CallMediaRecognizeDtmfOptions(targetParticipant, maxTonesToCollect) 
    .setInitialSilenceTimeout(Duration.ofSeconds(30)) 
    .setPlayPrompt(playSource) 
    .setInterToneTimeout(Duration.ofSeconds(5)) 
    .setInterruptPrompt(true) 
    .setStopTones(Arrays.asList(DtmfTone.POUND));

var recognizeResponse = callAutomationClient.getCallConnectionAsync(callConnectionId) 
    .getCallMediaAsync() 
    .startRecognizingWithResponse(recognizeOptions) 
    .block(); 

log.info("Start recognizing result: " + recognizeResponse.getStatusCode()); 

对于语音转文本流,通话自动化识别操作还支持使用自定义语音识别模型。 在生成需要侦听默认语音转文本模型可能无法理解的复杂字词的应用程序时,自定义语音识别模型等功能可能非常有用。 例如,在为远程医疗行业生成应用程序,并且虚拟代理需要能够识别医疗术语时。 可以在创建自定义语音识别项目中了解详细信息。

语音转文本选择

var choices = Arrays.asList(
  new RecognitionChoice()
  .setLabel("Confirm")
  .setPhrases(Arrays.asList("Confirm", "First", "One"))
  .setTone(DtmfTone.ONE),
  new RecognitionChoice()
  .setLabel("Cancel")
  .setPhrases(Arrays.asList("Cancel", "Second", "Two"))
  .setTone(DtmfTone.TWO)
);

String textToPlay = "Hello, This is a reminder for your appointment at 2 PM, Say Confirm to confirm your appointment or Cancel to cancel the appointment. Thank you!";
var playSource = new TextSource()
  .setText(textToPlay)
  .setVoiceName("en-US-ElizabethNeural");
var recognizeOptions = new CallMediaRecognizeChoiceOptions(targetParticipant, choices)
  .setInterruptPrompt(true)
  .setInitialSilenceTimeout(Duration.ofSeconds(30))
  .setPlayPrompt(playSource)
  .setOperationContext("AppointmentReminderMenu")
  //Only add the SpeechRecognitionModelEndpointId if you have a custom speech model you would like to use
  .setSpeechRecognitionModelEndpointId("YourCustomSpeechModelEndpointID"); 
var recognizeResponse = callAutomationClient.getCallConnectionAsync(callConnectionId)
  .getCallMediaAsync()
  .startRecognizingWithResponse(recognizeOptions)
  .block();

语音转文本

String textToPlay = "Hi, how can I help you today?"; 
var playSource = new TextSource() 
    .setText(textToPlay) 
    .setVoiceName("en-US-ElizabethNeural"); 
var recognizeOptions = new CallMediaRecognizeSpeechOptions(targetParticipant, Duration.ofMillis(1000)) 
    .setPlayPrompt(playSource) 
    .setOperationContext("OpenQuestionSpeech")
    //Only add the SpeechRecognitionModelEndpointId if you have a custom speech model you would like to use
    .setSpeechRecognitionModelEndpointId("YourCustomSpeechModelEndpointID");  
var recognizeResponse = callAutomationClient.getCallConnectionAsync(callConnectionId) 
    .getCallMediaAsync() 
    .startRecognizingWithResponse(recognizeOptions) 
    .block(); 

语音转文本或 DTMF

var maxTonesToCollect = 1; 
String textToPlay = "Hi, how can I help you today, you can press 0 to speak to an agent?"; 
var playSource = new TextSource() 
    .setText(textToPlay) 
    .setVoiceName("en-US-ElizabethNeural"); 
var recognizeOptions = new CallMediaRecognizeSpeechOrDtmfOptions(targetParticipant, maxTonesToCollect, Duration.ofMillis(1000)) 
    .setPlayPrompt(playSource) 
    .setInitialSilenceTimeout(Duration.ofSeconds(30)) 
    .setInterruptPrompt(true) 
    .setOperationContext("OpenQuestionSpeechOrDtmf")
    //Only add the SpeechRecognitionModelEndpointId if you have a custom speech model you would like to use
    .setSpeechRecognitionModelEndpointId("YourCustomSpeechModelEndpointID");  
var recognizeResponse = callAutomationClient.getCallConnectionAsync(callConnectionId) 
    .getCallMediaAsync() 
    .startRecognizingWithResponse(recognizeOptions) 
    .block(); 

注意

如果未设置参数,将尽可能应用默认值。

接收识别事件更新

开发人员可以订阅有关已注册 webhook 回调的 RecognizeCompletedRecognizeFailed 事件。 在应用程序中将此回调与业务逻辑配合使用可以确定当其中一个事件发生时要采取的后续步骤。

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

if (acsEvent instanceof RecognizeCompleted) { 
    RecognizeCompleted event = (RecognizeCompleted) acsEvent; 
    RecognizeResult recognizeResult = event.getRecognizeResult().get(); 
    if (recognizeResult instanceof DtmfResult) { 
        // Take action on collect tones 
        DtmfResult dtmfResult = (DtmfResult) recognizeResult; 
        List<DtmfTone> tones = dtmfResult.getTones(); 
        log.info("Recognition completed, tones=" + tones + ", context=" + event.getOperationContext()); 
    } else if (recognizeResult instanceof ChoiceResult) { 
        ChoiceResult collectChoiceResult = (ChoiceResult) recognizeResult; 
        String labelDetected = collectChoiceResult.getLabel(); 
        String phraseDetected = collectChoiceResult.getRecognizedPhrase(); 
        log.info("Recognition completed, labelDetected=" + labelDetected + ", phraseDetected=" + phraseDetected + ", context=" + event.getOperationContext()); 
    } else if (recognizeResult instanceof SpeechResult) { 
        SpeechResult speechResult = (SpeechResult) recognizeResult; 
        String text = speechResult.getSpeech(); 
        log.info("Recognition completed, text=" + text + ", context=" + event.getOperationContext()); 
    } else { 
        log.info("Recognition completed, result=" + recognizeResult + ", context=" + event.getOperationContext()); 
    } 
} 

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

if (acsEvent instanceof RecognizeFailed) { 
    RecognizeFailed event = (RecognizeFailed) acsEvent; 
    if (ReasonCode.Recognize.INITIAL_SILENCE_TIMEOUT.equals(event.getReasonCode())) { 
        // Take action for time out 
        log.info("Recognition failed: initial silence time out"); 
    } else if (ReasonCode.Recognize.SPEECH_OPTION_NOT_MATCHED.equals(event.getReasonCode())) { 
        // Take action for option not matched 
        log.info("Recognition failed: speech option not matched"); 
    } else if (ReasonCode.Recognize.DMTF_OPTION_MATCHED.equals(event.getReasonCode())) { 
        // Take action for incorrect tone 
        log.info("Recognition failed: incorrect tone detected"); 
    } else { 
        log.info("Recognition failed, result=" + event.getResultInformation().getMessage() + ", context=" + event.getOperationContext()); 
    } 
} 

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

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

先决条件

对于 AI 功能

技术规范

以下参数可用于自定义 Recognize 函数:

参数 类型 默认值(如果未指定) 说明 必需还是可选
Prompt

(有关详细信息,请参阅使用播放操作为用户自定义语音提示
FileSource、TextSource 未设置 在识别输入之前要播放的消息。 可选
InterToneTimeout TimeSpan 2 秒

最小值:1 秒
最大值:60 秒
Azure 通信服务等待呼叫者按另一个数字的秒数限制(数字间超时)。 可选
InitialSegmentationSilenceTimeoutInSeconds 整数 0.5 秒 识别操作在考虑超时之前将等待输入多长时间。 请参阅如何识别语音 可选
RecognizeInputsType Enum dtmf 识别的输入的类型。 选项包括 dtmfchoicesspeechspeechordtmf 必须
InitialSilenceTimeout TimeSpan 5 秒

最小值:0 秒
最大值:300 秒 (DTMF)
最大值:20 秒 (Choices)
最大值:20 秒 (Speech)
初始静音超时调整在识别尝试以“不匹配”结果结束之前,在一个短语之前允许的非语音音频量。 请参阅如何识别语音 可选
MaxTonesToCollect 整数 无默认值

最小值:1
开发人员期望参与者输入的位数。 必须
StopTones IEnumeration<DtmfTone> 未设置 数字参与者可以按压以退出批量 DTMF 事件。 可选
InterruptPrompt Bool True 如果参与者能够通过按一个数字来中断 playMessage。 可选
InterruptCallMediaOperation Bool True 如果设置此标志,则会中断当前的调用媒体操作。 例如,如果正在播放任何音频,它会中断该操作并启动识别。 可选
OperationContext 字符串 未设置 开发人员可以传递 mid 操作的字符串,用于允许开发人员存储有关他们收到的事件的上下文。 可选
Phrases 字符串 未设置 与标签关联的短语列表。 听到其中任何一个短语都表示成功识别。 必须
Tone 字符串 未设置 用户决定按下数字而不是使用语音时,要识别的音调。 可选
Label 字符串 未设置 用于识别的关键值。 必须
Language 字符串 En-us 用于识别语音的语言。 可选
EndSilenceTimeout TimeSpan 0.5 秒 用于检测生成为语音的最终结果的说话人的最后一次暂停。 可选

注意

如果 DTMF 和语音都在 recognizeInputsType 中,则识别操作将作用于收到的第一个输入类型。 例如,如果用户首先按下小键盘上的数字,则识别操作会将其视为 DTMF 事件并继续侦听 DTMF 音调。 如果用户先说话,则识别操作会将其视为语音识别事件并侦听语音输入。

创建新的 JavaScript 应用程序

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

npm init -y

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

npm install @azure/communication-call-automation

例如,在项目目录中创建新的 JavaScript 文件并将其命名为 app.js。 在此文件中编写 JavaScript 代码。

通过以下命令,使用 Node.js 运行你的应用程序。

node app.js

建立呼叫

至此,你应已熟悉如何开始通话。 有关发起通话的详细信息,请参阅快速入门:发起传出通话

调用识别动作

在你的应用程序应答呼叫时,你可以提供有关识别参与者输入和播放提示的信息。

DTMF

const maxTonesToCollect = 3; 
const textToPlay = "Welcome to Contoso, please enter 3 DTMF."; 
const playSource: TextSource = { text: textToPlay, voiceName: "en-US-ElizabethNeural", kind: "textSource" }; 
const recognizeOptions: CallMediaRecognizeDtmfOptions = { 
    maxTonesToCollect: maxTonesToCollect, 
    initialSilenceTimeoutInSeconds: 30, 
    playPrompt: playSource, 
    interToneTimeoutInSeconds: 5, 
    interruptPrompt: true, 
    stopDtmfTones: [ DtmfTone.Pound ], 
    kind: "callMediaRecognizeDtmfOptions" 
}; 

await callAutomationClient.getCallConnection(callConnectionId) 
    .getCallMedia() 
    .startRecognizing(targetParticipant, recognizeOptions); 

对于语音转文本流,通话自动化识别操作还支持使用自定义语音识别模型。 在生成需要侦听默认语音转文本模型可能无法理解的复杂字词的应用程序时,自定义语音识别模型等功能可能非常有用。 例如,在为远程医疗行业生成应用程序,并且虚拟代理需要能够识别医疗术语时。 可以在创建自定义语音识别项目中了解详细信息。

语音转文本选择

const choices = [ 
    {  
        label: "Confirm", 
        phrases: [ "Confirm", "First", "One" ], 
        tone: DtmfTone.One 
    }, 
    { 
        label: "Cancel", 
        phrases: [ "Cancel", "Second", "Two" ], 
        tone: DtmfTone.Two 
    } 
]; 

const textToPlay = "Hello, This is a reminder for your appointment at 2 PM, Say Confirm to confirm your appointment or Cancel to cancel the appointment. Thank you!"; 
const playSource: TextSource = { text: textToPlay, voiceName: "en-US-ElizabethNeural", kind: "textSource" }; 
const recognizeOptions: CallMediaRecognizeChoiceOptions = { 
    choices: choices, 
    interruptPrompt: true, 
    initialSilenceTimeoutInSeconds: 30, 
    playPrompt: playSource, 
    operationContext: "AppointmentReminderMenu", 
    kind: "callMediaRecognizeChoiceOptions",
    //Only add the speechRecognitionModelEndpointId if you have a custom speech model you would like to use
    speechRecognitionModelEndpointId: "YourCustomSpeechEndpointId"
}; 

await callAutomationClient.getCallConnection(callConnectionId) 
    .getCallMedia() 
    .startRecognizing(targetParticipant, recognizeOptions); 

语音转文本

const textToPlay = "Hi, how can I help you today?"; 
const playSource: TextSource = { text: textToPlay, voiceName: "en-US-ElizabethNeural", kind: "textSource" }; 
const recognizeOptions: CallMediaRecognizeSpeechOptions = { 
    endSilenceTimeoutInSeconds: 1, 
    playPrompt: playSource, 
    operationContext: "OpenQuestionSpeech", 
    kind: "callMediaRecognizeSpeechOptions",
    //Only add the speechRecognitionModelEndpointId if you have a custom speech model you would like to use
    speechRecognitionModelEndpointId: "YourCustomSpeechEndpointId"
}; 

await callAutomationClient.getCallConnection(callConnectionId) 
    .getCallMedia() 
    .startRecognizing(targetParticipant, recognizeOptions); 

语音转文本或 DTMF

const maxTonesToCollect = 1; 
const textToPlay = "Hi, how can I help you today, you can press 0 to speak to an agent?"; 
const playSource: TextSource = { text: textToPlay, voiceName: "en-US-ElizabethNeural", kind: "textSource" }; 
const recognizeOptions: CallMediaRecognizeSpeechOrDtmfOptions = { 
    maxTonesToCollect: maxTonesToCollect, 
    endSilenceTimeoutInSeconds: 1, 
    playPrompt: playSource, 
    initialSilenceTimeoutInSeconds: 30, 
    interruptPrompt: true, 
    operationContext: "OpenQuestionSpeechOrDtmf", 
    kind: "callMediaRecognizeSpeechOrDtmfOptions",
    //Only add the speechRecognitionModelEndpointId if you have a custom speech model you would like to use
    speechRecognitionModelEndpointId: "YourCustomSpeechEndpointId"
}; 

await callAutomationClient.getCallConnection(callConnectionId) 
    .getCallMedia() 
    .startRecognizing(targetParticipant, recognizeOptions); 

注意

如果未设置参数,将尽可能应用默认值。

接收识别事件更新

开发人员可以订阅有关已注册 webhook 回调的 RecognizeCompletedRecognizeFailed 事件。 在应用程序中将此回调与业务逻辑配合使用可以确定当其中一个事件发生时要采取的后续步骤。

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

if (event.type === "Microsoft.Communication.RecognizeCompleted") { 
    if (eventData.recognitionType === "dtmf") { 
        const tones = eventData.dtmfResult.tones; 
        console.log("Recognition completed, tones=%s, context=%s", tones, eventData.operationContext); 
    } else if (eventData.recognitionType === "choices") { 
        const labelDetected = eventData.choiceResult.label; 
        const phraseDetected = eventData.choiceResult.recognizedPhrase; 
        console.log("Recognition completed, labelDetected=%s, phraseDetected=%s, context=%s", labelDetected, phraseDetected, eventData.operationContext); 
    } else if (eventData.recognitionType === "speech") { 
        const text = eventData.speechResult.speech; 
        console.log("Recognition completed, text=%s, context=%s", text, eventData.operationContext); 
    } else { 
        console.log("Recognition completed: data=%s", JSON.stringify(eventData, null, 2)); 
    } 
} 

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

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

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

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

先决条件

对于 AI 功能

技术规范

以下参数可用于自定义 Recognize 函数:

参数 类型 默认值(如果未指定) 说明 必需还是可选
Prompt

(有关详细信息,请参阅使用播放操作为用户自定义语音提示
FileSource、TextSource 未设置 在识别输入之前要播放的消息。 可选
InterToneTimeout TimeSpan 2 秒

最小值:1 秒
最大值:60 秒
Azure 通信服务等待呼叫者按另一个数字的秒数限制(数字间超时)。 可选
InitialSegmentationSilenceTimeoutInSeconds 整数 0.5 秒 识别操作在考虑超时之前将等待输入多长时间。 请参阅如何识别语音 可选
RecognizeInputsType Enum dtmf 识别的输入的类型。 选项包括 dtmfchoicesspeechspeechordtmf 必须
InitialSilenceTimeout TimeSpan 5 秒

最小值:0 秒
最大值:300 秒 (DTMF)
最大值:20 秒 (Choices)
最大值:20 秒 (Speech)
初始静音超时调整在识别尝试以“不匹配”结果结束之前,在一个短语之前允许的非语音音频量。 请参阅如何识别语音 可选
MaxTonesToCollect 整数 无默认值

最小值:1
开发人员期望参与者输入的位数。 必须
StopTones IEnumeration<DtmfTone> 未设置 数字参与者可以按压以退出批量 DTMF 事件。 可选
InterruptPrompt Bool True 如果参与者能够通过按一个数字来中断 playMessage。 可选
InterruptCallMediaOperation Bool True 如果设置此标志,则会中断当前的调用媒体操作。 例如,如果正在播放任何音频,它会中断该操作并启动识别。 可选
OperationContext 字符串 未设置 开发人员可以传递 mid 操作的字符串,用于允许开发人员存储有关他们收到的事件的上下文。 可选
Phrases 字符串 未设置 与标签关联的短语列表。 听到其中任何一个短语都表示成功识别。 必须
Tone 字符串 未设置 用户决定按下数字而不是使用语音时,要识别的音调。 可选
Label 字符串 未设置 用于识别的关键值。 必须
Language 字符串 En-us 用于识别语音的语言。 可选
EndSilenceTimeout TimeSpan 0.5 秒 用于检测生成为语音的最终结果的说话人的最后一次暂停。 可选

注意

如果 DTMF 和语音都在 recognizeInputsType 中,则识别操作将作用于收到的第一个输入类型。 例如,如果用户首先按下小键盘上的数字,则识别操作会将其视为 DTMF 事件并继续侦听 DTMF 音调。 如果用户先说话,则识别操作会将其视为语音识别事件并侦听语音输入。

创建新的 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.py。 在此文件中编写 Python 代码。

通过以下命令,使用 Python 运行你的应用程序。

python app.py

建立呼叫

至此,你应已熟悉如何开始通话。 有关发起通话的详细信息,请参阅快速入门:发起传出通话

调用识别动作

在你的应用程序应答呼叫时,你可以提供有关识别参与者输入和播放提示的信息。

DTMF

max_tones_to_collect = 3 
text_to_play = "Welcome to Contoso, please enter 3 DTMF." 
play_source = TextSource(text=text_to_play, voice_name="en-US-ElizabethNeural") 
call_automation_client.get_call_connection(call_connection_id).start_recognizing_media( 
    dtmf_max_tones_to_collect=max_tones_to_collect, 
    input_type=RecognizeInputType.DTMF, 
    target_participant=target_participant, 
    initial_silence_timeout=30, 
    play_prompt=play_source, 
    dtmf_inter_tone_timeout=5, 
    interrupt_prompt=True, 
    dtmf_stop_tones=[ DtmfTone.Pound ]) 

对于语音转文本流,通话自动化识别操作还支持使用自定义语音识别模型。 在生成需要侦听默认语音转文本模型可能无法理解的复杂字词的应用程序时,自定义语音识别模型等功能可能非常有用。 例如,在为远程医疗行业生成应用程序,并且虚拟代理需要能够识别医疗术语时。 可以在创建自定义语音识别项目中了解详细信息。

语音转文本选择

choices = [ 
    RecognitionChoice( 
        label="Confirm", 
        phrases=[ "Confirm", "First", "One" ], 
        tone=DtmfTone.ONE 
    ), 
    RecognitionChoice( 
        label="Cancel", 
        phrases=[ "Cancel", "Second", "Two" ], 
        tone=DtmfTone.TWO 
    ) 
] 
text_to_play = "Hello, This is a reminder for your appointment at 2 PM, Say Confirm to confirm your appointment or Cancel to cancel the appointment. Thank you!" 
play_source = TextSource(text=text_to_play, voice_name="en-US-ElizabethNeural") 
call_automation_client.get_call_connection(call_connection_id).start_recognizing_media( 
    input_type=RecognizeInputType.CHOICES, 
    target_participant=target_participant, 
    choices=choices, 
    interrupt_prompt=True, 
    initial_silence_timeout=30, 
    play_prompt=play_source, 
    operation_context="AppointmentReminderMenu",
    # Only add the speech_recognition_model_endpoint_id if you have a custom speech model you would like to use
    speech_recognition_model_endpoint_id="YourCustomSpeechModelEndpointId")  

语音转文本

text_to_play = "Hi, how can I help you today?" 
play_source = TextSource(text=text_to_play, voice_name="en-US-ElizabethNeural") 
call_automation_client.get_call_connection(call_connection_id).start_recognizing_media( 
    input_type=RecognizeInputType.SPEECH, 
    target_participant=target_participant, 
    end_silence_timeout=1, 
    play_prompt=play_source, 
    operation_context="OpenQuestionSpeech",
    # Only add the speech_recognition_model_endpoint_id if you have a custom speech model you would like to use
    speech_recognition_model_endpoint_id="YourCustomSpeechModelEndpointId") 

语音转文本或 DTMF

max_tones_to_collect = 1 
text_to_play = "Hi, how can I help you today, you can also press 0 to speak to an agent." 
play_source = TextSource(text=text_to_play, voice_name="en-US-ElizabethNeural") 
call_automation_client.get_call_connection(call_connection_id).start_recognizing_media( 
    dtmf_max_tones_to_collect=max_tones_to_collect, 
    input_type=RecognizeInputType.SPEECH_OR_DTMF, 
    target_participant=target_participant, 
    end_silence_timeout=1, 
    play_prompt=play_source, 
    initial_silence_timeout=30, 
    interrupt_prompt=True, 
    operation_context="OpenQuestionSpeechOrDtmf",
    # Only add the speech_recognition_model_endpoint_id if you have a custom speech model you would like to use
    speech_recognition_model_endpoint_id="YourCustomSpeechModelEndpointId")  
app.logger.info("Start recognizing") 

注意

如果未设置参数,将尽可能应用默认值。

接收识别事件更新

开发人员可以订阅有关已注册 webhook 回调的 RecognizeCompletedRecognizeFailed 事件。 在应用程序中将此回调与业务逻辑配合使用可以确定当其中一个事件发生时要采取的后续步骤。

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

if event.type == "Microsoft.Communication.RecognizeCompleted": 
    app.logger.info("Recognize completed: data=%s", event.data) 
    if event.data['recognitionType'] == "dtmf": 
        tones = event.data['dtmfResult']['tones'] 
        app.logger.info("Recognition completed, tones=%s, context=%s", tones, event.data.get('operationContext')) 
    elif event.data['recognitionType'] == "choices": 
        labelDetected = event.data['choiceResult']['label']; 
        phraseDetected = event.data['choiceResult']['recognizedPhrase']; 
        app.logger.info("Recognition completed, labelDetected=%s, phraseDetected=%s, context=%s", labelDetected, phraseDetected, event.data.get('operationContext')); 
    elif event.data['recognitionType'] == "speech": 
        text = event.data['speechResult']['speech']; 
        app.logger.info("Recognition completed, text=%s, context=%s", text, event.data.get('operationContext')); 
    else: 
        app.logger.info("Recognition completed: data=%s", event.data); 

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

if event.type == "Microsoft.Communication.RecognizeFailed": 
    app.logger.info("Recognize failed: data=%s", event.data); 

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

if event.type == "Microsoft.Communication.RecognizeCanceled":
    # Handle the RecognizeCanceled event according to your application logic

事件代码

Status 代码 子代码 消息
RecognizeCompleted 200 8531 操作已完成,接收的最大位数。
RecognizeCompleted 200 8514 检测到停止音调时完成的操作。
RecognizeCompleted 400 8508 操作失败,操作已取消。
RecognizeCompleted 400 8532 操作失败,已达到数字间静音超时。
RecognizeCanceled 400 8508 操作失败,操作已取消。
RecognizeFailed 400 8510 操作失败,已达到初始静音超时。
RecognizeFailed 500 8511 操作失败,尝试播放提示时遇到失败。
RecognizeFailed 500 8512 未知的内部服务器错误。
RecognizeFailed 400 8510 操作失败,已达到初始静音超时
RecognizeFailed 400 8532 操作失败,已达到数字间静音超时。
RecognizeFailed 400 8565 操作失败,对 Azure AI 服务的请求不正确。 检查输入参数。
RecognizeFailed 400 8565 操作失败,对 Azure AI 服务的请求不正确。 无法处理提供的有效负载,请检查播放源输入。
RecognizeFailed 401 8565 操作失败,Azure AI 服务身份验证错误。
RecognizeFailed 403 8565 操作失败,禁止请求 Azure AI 服务,请求使用的免费订阅已用完配额。
RecognizeFailed 429 8565 操作失败,请求超出了 Azure AI 服务订阅允许的并发请求数。
RecognizeFailed 408 8565 操作失败,对 Azure AI 服务的请求已超时。
RecognizeFailed 500 8511 操作失败,尝试播放提示时遇到失败。
RecognizeFailed 500 8512 未知的内部服务器错误。

已知限制

  • 不支持带内 DTMF。 请改用 RFC 2833 DTMF。
  • 文本转语音文本提示最多支持 400 个字符,如果你的提示超过此长度限制,建议对基于文本转语音的播放操作使用 SSML。
  • 对于超出语音服务配额限制的情况,可以按照语音服务配额和限制中所述的步骤请求提高此限制。

清理资源

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

后续步骤