Сбор входных данных пользователей с помощью действия "Распознать"
Это руководство поможет вам приступить к распознаванию входных данных DTMF, предоставляемых участниками с помощью пакета SDK для автоматизации вызовов Службы коммуникации Azure.
Необходимые компоненты
- Учетная запись Azure с активной подпиской см. в статье "Создание учетной записи бесплатно".
- Службы коммуникации Azure ресурс. См. статью "Создание ресурса Службы коммуникации Azure". Обратите внимание на строка подключения для этого ресурса.
- Создайте новое приложение веб-службы с помощью пакета SDK службы автоматизации вызовов.
- Последняя библиотека .NET для операционной системы.
- Получите последний пакет NuGet.
Для функций ИИ
- Создайте и подключите службы ИИ Azure к Службы коммуникации Azure ресурсу.
- Создайте настраиваемый поддомен для ресурса служб искусственного интеллекта Azure.
Технические характеристики
Для настройки функции Распознавания доступны следующие параметры:
Параметр | Тип | Значение по умолчанию (если не указано) | Description | Обязательный или необязательный |
---|---|---|---|---|
Подсказывать (Дополнительные сведения о действии воспроизведения см. в этом руководстве) |
FileSource, TextSource | Не установлено | Это сообщение, которое вы хотите воспроизвести перед распознаванием входных данных. | Необязательно |
InterToneTimeout | TimeSpan | 2 секунды Мин: 1 секунда Максимальное значение: 60 секунд |
Ограничение в секундах, которые Службы коммуникации Azure ожидает, пока вызывающий объект нажимает другую цифру (время ожидания между цифрами). | Необязательно |
InitialSegmentationSilenceTimeoutInSeconds | Целое | 0,5 секунды | Как долго распознать действие ожидает входных данных, прежде чем рассматривать время ожидания. Дополнительные сведения см. здесь. | Необязательно |
RecognizeInputsType | Перечисление | dtmf | Тип распознаваемых входных данных. Параметры : dtmf, выбор, речь и речь. | Обязательное поле |
InitialSilenceTimeout | TimeSpan | 5 секунд Мин: 0 секунд Макс: 300 секунд (DTMF) Макс: 20 секунд (варианты) Макс: 20 секунд (речь) |
Начальное время ожидания молчания корректирует, сколько неписучего звука разрешено перед фразой, прежде чем попытка распознавания заканчивается в результате "без совпадения". Дополнительные сведения см. здесь. | Необязательно |
MaxTonesToCollect | Целое | Нет по умолчанию Мин: 1 |
Число цифр, которые разработчик ожидает в качестве входных данных от участника. | Обязательное поле |
СтопТоны | IEnumeration<DtmfTone> | Не установлено | Участники цифры могут нажать клавишу, чтобы выйти из пакетного события DTMF. | Необязательно |
ПрерываниеPrompt | Bool | Истина | Если участник может прервать воспроизведениеMessage, нажав цифру. | Необязательно |
ПрерываниеCallMediaOperation | Bool | Истина | Если этот флаг задан, он прерывает текущую операцию вызова мультимедиа. Например, если звук воспроизводится, он прерывает операцию и инициирует распознавание. | Необязательно |
OperationContext | Строка | Не установлено | Строка, которую разработчики могут передать середину действия, полезная для того, чтобы разработчики могли хранить контекст о событиях, которые они получают. | Необязательно |
Фразы | Строка | Не установлено | Список фраз, которые связываются с меткой, если любой из них слышал, считается успешным распознаванием. | Обязательное поле |
Тон | Строка | Не установлено | Тон для распознавания того, решит ли пользователь нажать число вместо использования речи. | Необязательно |
Этикетка | Строка | Не установлено | Ключевое значение для распознавания. | Обязательное поле |
Язык | Строка | En-us | Язык, используемый для распознавания речи. | Необязательно |
EndSilenceTimeout | TimeSpan | 0,5 секунды | Последняя пауза говорящего, используемая для обнаружения окончательного результата, создаваемого как речь. | Необязательно |
Примечание.
В ситуациях, когда как dtmf, так и речь находятся в распознаваемом Типе, действие распознания будет действовать с первым полученным типом входных данных, т. е. если пользователь нажимает номер клавиатуры сначала, то действие распознавания будет рассматривать его как событие dtmf и продолжать прослушивать dtmf тонов. Если пользователь сначала говорит, то действие распознавания речи будет рассматривать его как распознавание речи и прослушивание голосовых входных данных.
Создание нового приложения C#
В окне консоли операционной системы используйте dotnet
команду для создания нового веб-приложения.
dotnet new web -n MyApplication
Установка пакета NuGet
Пакет 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);
Примечание.
Если параметры не заданы, по возможности применяются значения по умолчанию.
Получение обновлений событий распознавания
Разработчики могут подписаться на события RecognizeCompleted и RecognizeFailed в обратном вызове веб-перехватчика, зарегистрированном для вызова, чтобы создать бизнес-логику в приложении для определения следующих шагов при возникновении одного из упомянутых ранее событий.
Пример десериализации события 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);
}
Необходимые компоненты
- Учетная запись Azure с активной подпиской см. в статье "Создание учетной записи бесплатно".
- Службы коммуникации Azure ресурс. См. статью "Создание ресурса Службы коммуникации Azure"
- Создайте новое приложение веб-службы с помощью пакета SDK службы автоматизации вызовов.
- Пакет средств разработки Java версии 8 или более поздней.
- Apache Maven.
Для функций ИИ
- Создайте и подключите службы ИИ Azure к Службы коммуникации Azure ресурсу.
- Создайте настраиваемый поддомен для ресурса служб искусственного интеллекта Azure.
Технические характеристики
Для настройки функции Распознавания доступны следующие параметры:
Параметр | Тип | Значение по умолчанию (если не указано) | Description | Обязательный или необязательный |
---|---|---|---|---|
Подсказывать (Дополнительные сведения о действии воспроизведения см. в этом руководстве) |
FileSource, TextSource | Не установлено | Это сообщение, которое вы хотите воспроизвести перед распознаванием входных данных. | Необязательно |
InterToneTimeout | TimeSpan | 2 секунды Мин: 1 секунда Максимальное значение: 60 секунд |
Ограничение в секундах, которые Службы коммуникации Azure ожидает, пока вызывающий объект нажимает другую цифру (время ожидания между цифрами). | Необязательно |
InitialSegmentationSilenceTimeoutInSeconds | Целое | 0,5 секунды | Как долго распознать действие ожидает входных данных, прежде чем рассматривать время ожидания. Дополнительные сведения см. здесь. | Необязательно |
RecognizeInputsType | Перечисление | dtmf | Тип распознаваемых входных данных. Параметры : dtmf, выбор, речь и речь. | Обязательное поле |
InitialSilenceTimeout | TimeSpan | 5 секунд Мин: 0 секунд Макс: 300 секунд (DTMF) Макс: 20 секунд (варианты) Макс: 20 секунд (речь) |
Начальное время ожидания молчания корректирует, сколько неписучего звука разрешено перед фразой, прежде чем попытка распознавания заканчивается в результате "без совпадения". Дополнительные сведения см. здесь. | Необязательно |
MaxTonesToCollect | Целое | Нет по умолчанию Мин: 1 |
Число цифр, которые разработчик ожидает в качестве входных данных от участника. | Обязательное поле |
СтопТоны | IEnumeration<DtmfTone> | Не установлено | Участники цифры могут нажать клавишу, чтобы выйти из пакетного события DTMF. | Необязательно |
ПрерываниеPrompt | Bool | Истина | Если участник может прервать воспроизведениеMessage, нажав цифру. | Необязательно |
ПрерываниеCallMediaOperation | Bool | Истина | Если этот флаг задан, он прерывает текущую операцию вызова мультимедиа. Например, если звук воспроизводится, он прерывает операцию и инициирует распознавание. | Необязательно |
OperationContext | Строка | Не установлено | Строка, которую разработчики могут передать середину действия, полезная для того, чтобы разработчики могли хранить контекст о событиях, которые они получают. | Необязательно |
Фразы | Строка | Не установлено | Список фраз, которые связываются с меткой, если любой из них слышал, считается успешным распознаванием. | Обязательное поле |
Тон | Строка | Не установлено | Тон для распознавания того, решит ли пользователь нажать число вместо использования речи. | Необязательно |
Этикетка | Строка | Не установлено | Ключевое значение для распознавания. | Обязательное поле |
Язык | Строка | En-us | Язык, используемый для распознавания речи. | Необязательно |
EndSilenceTimeout | TimeSpan | 0,5 секунды | Последняя пауза говорящего, используемая для обнаружения окончательного результата, создаваемого как речь. | Необязательно |
Примечание.
В ситуациях, когда как dtmf, так и речь находятся в распознаваемом Типе, действие распознания будет действовать с первым полученным типом входных данных, т. е. если пользователь нажимает номер клавиатуры сначала, то действие распознавания будет рассматривать его как событие dtmf и продолжать прослушивать dtmf тонов. Если пользователь сначала говорит, то действие распознавания речи будет рассматривать его как распознавание речи и прослушивание голосовых входных данных.
Создание нового приложения Java
В окне терминала или командной строки перейдите в каталог, в котором вы хотите создать приложение Java. mvn
Выполните команду, чтобы создать проект Java из шаблона maven-archetype-quickstart.
mvn archetype:generate -DgroupId=com.communication.quickstart -DartifactId=communication-quickstart -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
Команда mvn
создает каталог с тем же именем, что artifactId
и аргумент. В этом каталоге src/main/java
каталог содержит исходный код проекта, src/test/java
каталог содержит источник теста.
Вы заметите, что шаг "generate" создал каталог с таким же именем, как артефактId. В этом каталоге 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();
Примечание.
Если параметры не заданы, по возможности применяются значения по умолчанию.
Получение обновлений событий распознавания
Разработчики могут подписаться на события RecognizeCompleted и RecognizeFailed на зарегистрированном обратном вызове веб-перехватчика. Этот обратный вызов можно использовать с бизнес-логикой в приложении для определения следующих шагов при возникновении одного из событий.
Пример десериализации события 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());
}
Необходимые компоненты
- Учетная запись Azure с активной подпиской см. в статье "Создание учетной записи бесплатно".
- Службы коммуникации Azure ресурс. См. статью "Создание ресурса Службы коммуникации Azure". Обратите внимание на строка подключения для этого ресурса.
- Создайте новое приложение веб-службы с помощью пакета SDK службы автоматизации вызовов.
- Установите Node.js, вы можете установить его с официального веб-сайта.
Для функций ИИ
- Создайте и подключите службы ИИ Azure к Службы коммуникации Azure ресурсу.
- Создайте настраиваемый поддомен для ресурса служб искусственного интеллекта Azure.
Технические характеристики
Для настройки функции Распознавания доступны следующие параметры:
Параметр | Тип | Значение по умолчанию (если не указано) | Description | Обязательный или необязательный |
---|---|---|---|---|
Подсказывать (Дополнительные сведения о действии воспроизведения см. в этом руководстве) |
FileSource, TextSource | Не установлено | Это сообщение, которое вы хотите воспроизвести перед распознаванием входных данных. | Необязательно |
InterToneTimeout | TimeSpan | 2 секунды Мин: 1 секунда Максимальное значение: 60 секунд |
Ограничение в секундах, которые Службы коммуникации Azure ожидает, пока вызывающий объект нажимает другую цифру (время ожидания между цифрами). | Необязательно |
InitialSegmentationSilenceTimeoutInSeconds | Целое | 0,5 секунды | Как долго распознать действие ожидает входных данных, прежде чем рассматривать время ожидания. Дополнительные сведения см. здесь. | Необязательно |
RecognizeInputsType | Перечисление | dtmf | Тип распознаваемых входных данных. Параметры : dtmf, выбор, речь и речь. | Обязательное поле |
InitialSilenceTimeout | TimeSpan | 5 секунд Мин: 0 секунд Макс: 300 секунд (DTMF) Макс: 20 секунд (варианты) Макс: 20 секунд (речь) |
Начальное время ожидания молчания корректирует, сколько неписучего звука разрешено перед фразой, прежде чем попытка распознавания заканчивается в результате "без совпадения". Дополнительные сведения см. здесь. | Необязательно |
MaxTonesToCollect | Целое | Нет по умолчанию Мин: 1 |
Число цифр, которые разработчик ожидает в качестве входных данных от участника. | Обязательное поле |
СтопТоны | IEnumeration<DtmfTone> | Не установлено | Участники цифры могут нажать клавишу, чтобы выйти из пакетного события DTMF. | Необязательно |
ПрерываниеPrompt | Bool | Истина | Если участник может прервать воспроизведениеMessage, нажав цифру. | Необязательно |
ПрерываниеCallMediaOperation | Bool | Истина | Если этот флаг задан, он прерывает текущую операцию вызова мультимедиа. Например, если звук воспроизводится, он прерывает операцию и инициирует распознавание. | Необязательно |
OperationContext | Строка | Не установлено | Строка, которую разработчики могут передать середину действия, полезная для того, чтобы разработчики могли хранить контекст о событиях, которые они получают. | Необязательно |
Фразы | Строка | Не установлено | Список фраз, которые связываются с меткой, если любой из них слышал, считается успешным распознаванием. | Обязательное поле |
Тон | Строка | Не установлено | Тон для распознавания того, решит ли пользователь нажать число вместо использования речи. | Необязательно |
Этикетка | Строка | Не установлено | Ключевое значение для распознавания. | Обязательное поле |
Язык | Строка | En-us | Язык, используемый для распознавания речи. | Необязательно |
EndSilenceTimeout | TimeSpan | 0,5 секунды | Последняя пауза говорящего, используемая для обнаружения окончательного результата, создаваемого как речь. | Необязательно |
Примечание.
В ситуациях, когда как dtmf, так и речь находятся в распознаваемом Типе, действие распознания будет действовать с первым полученным типом входных данных, т. е. если пользователь нажимает номер клавиатуры сначала, то действие распознавания будет рассматривать его как событие dtmf и продолжать прослушивать dtmf тонов. Если пользователь сначала говорит, то действие распознавания речи будет рассматривать его как распознавание речи и прослушивание голосовых входных данных.
Создание приложения 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
Установка вызова
К этому моменту вы должны ознакомиться с начальными звонками, если вам нужно узнать больше о вызове, следуйте нашему краткому руководству. В этом кратком руководстве мы создадим исходящий вызов.
Вызов действия распознавания
Когда приложение отвечает на вызов, вы можете предоставить сведения о распознавании входных данных участника и воспроизведении запроса. Действие распознавания также поддерживает воспроизведение нескольких запросов в одном запросе.
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);
Примечание.
Если параметры не заданы, по возможности применяются значения по умолчанию.
Получение обновлений событий распознавания
Разработчики могут подписаться на события RecognizeCompleted и RecognizeFailed в обратном вызове веб-перехватчика, зарегистрированном для вызова, чтобы создать бизнес-логику в приложении для определения следующих шагов при возникновении одного из упомянутых ранее событий.
Пример десериализации события 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);
}
Необходимые компоненты
- Учетная запись Azure с активной подпиской см. в статье "Создание учетной записи бесплатно".
- Службы коммуникации Azure ресурс. См. статью "Создание ресурса Службы коммуникации Azure". Обратите внимание на строка подключения для этого ресурса.
- Создайте новое приложение веб-службы с помощью пакета SDK службы автоматизации вызовов.
- Установить Python можно с официального сайта.
Для функций ИИ
- Создайте и подключите службы ИИ Azure к Службы коммуникации Azure ресурсу.
- Создайте настраиваемый поддомен для ресурса служб искусственного интеллекта Azure.
Технические характеристики
Для настройки функции Распознавания доступны следующие параметры:
Параметр | Тип | Значение по умолчанию (если не указано) | Description | Обязательный или необязательный |
---|---|---|---|---|
Подсказывать (Дополнительные сведения о действии воспроизведения см. в этом руководстве) |
FileSource, TextSource | Не установлено | Это сообщение, которое вы хотите воспроизвести перед распознаванием входных данных. | Необязательно |
InterToneTimeout | TimeSpan | 2 секунды Мин: 1 секунда Максимальное значение: 60 секунд |
Ограничение в секундах, которые Службы коммуникации Azure ожидает, пока вызывающий объект нажимает другую цифру (время ожидания между цифрами). | Необязательно |
InitialSegmentationSilenceTimeoutInSeconds | Целое | 0,5 секунды | Как долго распознать действие ожидает входных данных, прежде чем рассматривать время ожидания. Дополнительные сведения см. здесь. | Необязательно |
RecognizeInputsType | Перечисление | dtmf | Тип распознаваемых входных данных. Параметры : dtmf, выбор, речь и речь. | Обязательное поле |
InitialSilenceTimeout | TimeSpan | 5 секунд Мин: 0 секунд Макс: 300 секунд (DTMF) Макс: 20 секунд (варианты) Макс: 20 секунд (речь) |
Начальное время ожидания молчания корректирует, сколько неписучего звука разрешено перед фразой, прежде чем попытка распознавания заканчивается в результате "без совпадения". Дополнительные сведения см. здесь. | Необязательно |
MaxTonesToCollect | Целое | Нет по умолчанию Мин: 1 |
Число цифр, которые разработчик ожидает в качестве входных данных от участника. | Обязательное поле |
СтопТоны | IEnumeration<DtmfTone> | Не установлено | Участники цифры могут нажать клавишу, чтобы выйти из пакетного события DTMF. | Необязательно |
ПрерываниеPrompt | Bool | Истина | Если участник может прервать воспроизведениеMessage, нажав цифру. | Необязательно |
ПрерываниеCallMediaOperation | Bool | Истина | Если этот флаг задан, он прерывает текущую операцию вызова мультимедиа. Например, если звук воспроизводится, он прерывает операцию и инициирует распознавание. | Необязательно |
OperationContext | Строка | Не установлено | Строка, которую разработчики могут передать середину действия, полезная для того, чтобы разработчики могли хранить контекст о событиях, которые они получают. | Необязательно |
Фразы | Строка | Не установлено | Список фраз, которые связываются с меткой, если любой из них слышал, считается успешным распознаванием. | Обязательное поле |
Тон | Строка | Не установлено | Тон для распознавания того, решит ли пользователь нажать число вместо использования речи. | Необязательно |
Этикетка | Строка | Не установлено | Ключевое значение для распознавания. | Обязательное поле |
Язык | Строка | En-us | Язык, используемый для распознавания речи. | Необязательно |
EndSilenceTimeout | TimeSpan | 0,5 секунды | Последняя пауза говорящего, используемая для обнаружения окончательного результата, создаваемого как речь. | Необязательно |
Примечание.
В ситуациях, когда как dtmf, так и речь находятся в распознаваемом Типе, действие распознания будет действовать с первым полученным типом входных данных, т. е. если пользователь нажимает номер клавиатуры сначала, то действие распознавания будет рассматривать его как событие 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.
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")
Примечание.
Если параметры не заданы, по возможности применяются значения по умолчанию.
Получение обновлений событий распознавания
Разработчики могут подписаться на события RecognizeCompleted и RecognizeFailed в обратном вызове веб-перехватчика, зарегистрированном для вызова, чтобы создать бизнес-логику в приложении для определения следующих шагов при возникновении одного из упомянутых ранее событий.
Пример десериализации события 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
Коды событий
Состояние | Код | Вложенный код | Сообщение |
---|---|---|---|
Распознаваемый | 200 | 8531 | Выполнено действие, полученные максимальные цифры. |
Распознаваемый | 200 | 8514 | Действие выполнено по мере обнаружения тона остановки. |
Распознаваемый | 400 | 8508 | Сбой действия, операция была отменена. |
Распознаваемый | 400 | 8532 | Не удалось выполнить действие, достигнуто время ожидания межзначного молчания. |
РаспознатьCanceled | 400 | 8508 | Сбой действия, операция была отменена. |
RecognizeFailed | 400 | 8510 | Сбой действия, достигнуто начальное время ожидания молчания. |
RecognizeFailed | 500 | 8511 | Сбой действия, обнаружен сбой при попытке воспроизвести запрос. |
RecognizeFailed | 500 | 8512 | Неизвестная внутренняя ошибка сервера. |
RecognizeFailed | 400 | 8510 | Сбой действия, достигнуто начальное время ожидания молчания |
RecognizeFailed | 400 | 8532 | Не удалось выполнить действие, достигнуто время ожидания межзначного молчания. |
RecognizeFailed | 400 | 8565 | Сбой действия, неправильный запрос к службам ИИ Azure. Проверить входные параметры. |
Распознать сбой | 400 | 8565 | Сбой действия, неправильный запрос к службам ИИ Azure. Не удалось обработать предоставленные полезные данные, проверьте входные данные источника воспроизведения |
RecognizeFailed | 401 | 8565 | Сбой действия, ошибка проверки подлинности служб ИИ Azure. |
RecognizeFailed | 403 | 8565 | Сбой действия, запрещенный запрос к службам ИИ Azure, бесплатная подписка, используемая запросом, закончилась квота. |
RecognizeFailed | 429 | 8565 | Сбой действия, запросы превысили количество разрешенных одновременных запросов для подписки на службы искусственного интеллекта Azure. |
RecognizeFailed | 408 | 8565 | Сбой действия, время ожидания запроса к службам ИИ Azure истекло. |
RecognizeFailed | 500 | 8511 | Сбой действия, обнаружен сбой при попытке воспроизвести запрос. |
RecognizeFailed | 500 | 8512 | Неизвестная внутренняя ошибка сервера. |
Известные ограничения
- Вместо этого используйте RFC 2833 DTMF в полосе DTMF.
- Текстовые запросы на речь поддерживают не более 400 символов, если ваш запрос больше, чем это мы рекомендуем использовать SSML для действий воспроизведения на основе текста в речь.
- В сценариях, когда превышено ограничение квоты службы "Речь", можно запросить увеличение этого lilmit, выполнив описанные здесь действия.
Очистка ресурсов
Если вы хотите отменить и удалить подписку на Службы коммуникации, можно удалить ресурс или группу ресурсов. При удалении группы ресурсов также удаляются все связанные с ней ресурсы. См. сведения об очистке ресурсов.
Next Steps
- Дополнительные сведения о сборе входных данных пользователей
- Дополнительные сведения о воспроизведении звука в вызове
- Дополнительные сведения об автоматизации вызовов