Início Rápido: como fazer uma chamada de saída por meio da Automação de Chamadas

As APIS de Automação de Chamada dos Serviços de Comunicação do Azure APIs são uma maneira poderosa de criar experiências interativas de chamada. Nesse início rápido, abordamos uma maneira de fazer uma chamada de saída e reconhecer vários eventos na chamada.

Pré-requisitos

Código de exemplo

Baixe ou clone o código de exemplo de início rápido do GitHub.

Navegue até a pasta CallAutomation_OutboundCalling e abra a solução em um editor de código.

Configurar e hospedar seu Azure DevTunnel

OAzure DevTunnels é um serviço do Azure que permite compartilhar serviços Web locais hospedados na Internet. Execute os comandos para conectar seu ambiente de desenvolvimento local à Internet pública. O DevTunnels cria uma URL de ponto de extremidade persistente e que permite acesso anônimo. Usamos esse ponto de extremidade para notificar seu aplicativo de eventos de chamada do serviço Automação de Chamadas dos Serviços de Comunicação do Azure.

devtunnel create --allow-anonymous
devtunnel port create -p 8080
devtunnel host

Como alternativa, siga as instruções para configurar seu Azure DevTunnel no Visual Studio

Atualize a configuração do aplicativo

Em seguida, atualize o arquivo Program.cs com os seguintes valores:

  • acsConnectionString: a cadeia de conexão do recurso dos Serviços de Comunicação do Azure. Encontre a cadeia de conexão dos Serviços de Comunicação do Azure usando as instruções descritas aqui.
  • callbackUriHost: depois de inicializar o host do DevTunnel, atualize esse campo com a URI.
  • acsPhonenumber: atualize esse campo com o número de telefone dos Serviços de Comunicação do Azure que você adquiriu. Esse número de telefone deve usar o formato de número de telefone E164 (por exemplo, +18881234567)
  • targetPhonenumber: atualize o campo com o número de telefone que você gostaria que seu aplicativo chamasse. Esse número de telefone deve usar o formato de número de telefone E164 (por exemplo, +18881234567)
  • cognitiveServiceEndpoint: atualize o campo com o ponto de extremidade dos serviços de IA do Azure.
  • targetTeamsUserId: (Opcional) atualize o campo com a ID de usuário do Microsoft Teams que você deseja adicionar à chamada. Consulte Usar a API do Graph para obter a ID de usuário do Teams.
// Your ACS resource connection string 
var acsConnectionString = "<ACS_CONNECTION_STRING>"; 

// Your ACS resource phone number will act as source number to start outbound call 
var acsPhonenumber = "<ACS_PHONE_NUMBER>"; 
 
// Target phone number you want to receive the call. 
var targetPhonenumber = "<TARGET_PHONE_NUMBER>";

// Base url of the app 
var callbackUriHost = "<CALLBACK_URI_HOST_WITH_PROTOCOL>"; 

// Your cognitive service endpoint 
var cognitiveServiceEndpoint = "<COGNITIVE_SERVICE_ENDPOINT>";

// (Optional) User Id of the target teams user you want to receive the call.
var targetTeamsUserId = "<TARGET_TEAMS_USER_ID>";

Fazer uma chamada de saída

Para fazer a chamada de saída dos Serviços de Comunicação do Azure, este exemplo usa o targetPhonenumber que você definiu anteriormente no aplicativo para criar a chamada usando a API CreateCallAsync. Esse código fará uma chamada de saída usando o número de telefone de destino.

PhoneNumberIdentifier target = new PhoneNumberIdentifier(targetPhonenumber);
PhoneNumberIdentifier caller = new PhoneNumberIdentifier(acsPhonenumber);
var callbackUri = new Uri(callbackUriHost + "/api/callbacks");
CallInvite callInvite = new CallInvite(target, caller);
var createCallOptions = new CreateCallOptions(callInvite, callbackUri) {
  CallIntelligenceOptions = new CallIntelligenceOptions() {
    CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint)
  }
};
CreateCallResult createCallResult = await callAutomationClient.CreateCallAsync(createCallOptions);

Lidar com eventos de automação de chamadas

Anteriormente em nosso aplicativo, registramos o callbackUriHost no Serviço de Automação de Chamadas. O host indica o ponto de extremidade que o serviço exige para nos notificar sobre a chamada de eventos que acontecem. Em seguida, podemos iterar pelos eventos e detectar eventos específicos que nosso aplicativo deseja entender. No código abaixo respondemos ao evento CallConnected.

app.MapPost("/api/callbacks", async (CloudEvent[] cloudEvents, ILogger < Program > logger) => {
  foreach(var cloudEvent in cloudEvents) {
    logger.LogInformation($"Event received: {JsonConvert.SerializeObject(cloudEvent)}");
    CallAutomationEventBase parsedEvent = CallAutomationEventParser.Parse(cloudEvent);
    logger.LogInformation($"{parsedEvent?.GetType().Name} parsedEvent received for call connection id: {parsedEvent?.CallConnectionId}");
    var callConnection = callAutomationClient.GetCallConnection(parsedEvent.CallConnectionId);
    var callMedia = callConnection.GetCallMedia();
    if (parsedEvent is CallConnected) {
      //Handle Call Connected Event
    }
  }
});

(Opcional) Adicionar um usuário do Microsoft Teams à chamada

Você pode adicionar um usuário do Microsoft Teams à chamada usando o AddParticipantAsync método com a MicrosoftTeamsUserIdentifier ID do usuário e do Teams. Primeiro, você precisa concluir a etapa de pré-requisito Autorização para o recurso dos Serviços de Comunicação do Azure para habilitar a chamada aos usuários do Microsoft Teams. Opcionalmente, você também pode passar um SourceDisplayName para controlar o texto exibido na notificação do sistema para o usuário do Teams.

await callConnection.AddParticipantAsync(
    new CallInvite(new MicrosoftTeamsUserIdentifier(targetTeamsUserId))
    {
        SourceDisplayName = "Jack (Contoso Tech Support)"
    });

Iniciar a gravação de uma chamada

O serviço de Automação de Chamadas também permite a capacidade de iniciar a gravação e armazenar gravações de chamadas de voz e vídeo. Você pode aprender mais sobre os vários recursos das APIs de gravação de chamadas aqui.

CallLocator callLocator = new ServerCallLocator(parsedEvent.ServerCallId);
var recordingResult = await callAutomationClient.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator));
recordingId = recordingResult.Value.RecordingId;

Reproduza mensagem de boas-vindas e reconheça

Usando o TextSource, você pode fornecer ao serviço o texto que deseja sintetizar e usado para sua mensagem de boas-vindas. O serviço Automação de Chamadas dos Serviços de Comunicação do Azure reproduz essa mensagem após o evento CallConnected.

Em seguida, passamos o texto para o CallMediaRecognizeChoiceOptions e, em seguida, chamamos StartRecognizingAsync. Isso permite que seu aplicativo reconheça a opção escolhida pelo chamador.

if (parsedEvent is CallConnected callConnected) {
  logger.LogInformation($"Start Recording...");
  CallLocator callLocator = new ServerCallLocator(parsedEvent.ServerCallId);
  var recordingResult = await callAutomationClient.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator));
  recordingId = recordingResult.Value.RecordingId;

  var choices = GetChoices();

  // prepare recognize tones 
  var recognizeOptions = GetMediaRecognizeChoiceOptions(mainMenu, targetPhonenumber, choices);

  // Send request to recognize tones 
  await callMedia.StartRecognizingAsync(recognizeOptions);
}

CallMediaRecognizeChoiceOptions GetMediaRecognizeChoiceOptions(string content, string targetParticipant, List < RecognitionChoice > choices, string context = "") {
  var playSource = new TextSource(content) {
    VoiceName = SpeechToTextVoice
  };

  var recognizeOptions = new CallMediaRecognizeChoiceOptions(targetParticipant: new PhoneNumberIdentifier(targetParticipant), choices) {
    InterruptCallMediaOperation = false,
      InterruptPrompt = false,
      InitialSilenceTimeout = TimeSpan.FromSeconds(10),
      Prompt = playSource,
      OperationContext = context
  };
  return recognizeOptions;
}

List < RecognitionChoice > GetChoices() {
  return 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
    }
  };
}

Manipular eventos de escolha

A Automação de Chamadas dos Serviços de Comunicação do Azure dispara o api/callbacks para o webhook que configuramos e nos notificará com o evento RecognizeCompleted. O evento nos dá a capacidade de responder à entrada recebida e disparar uma ação. Em seguida, o aplicativo reproduz uma mensagem para o chamador com base na entrada específica recebida.

if (parsedEvent is RecognizeCompleted recognizeCompleted) {
  var choiceResult = recognizeCompleted.RecognizeResult as ChoiceResult;
  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);

  var textToPlay = labelDetected.Equals(ConfirmChoiceLabel, StringComparison.OrdinalIgnoreCase) ? ConfirmedText : CancelText;

  await HandlePlayAsync(callMedia, textToPlay);
}

async Task HandlePlayAsync(CallMedia callConnectionMedia, string text) {
  // Play goodbye message 
  var GoodbyePlaySource = new TextSource(text) {
    VoiceName = "en-US-NancyNeural"
  };
  await callConnectionMedia.PlayToAllAsync(GoodbyePlaySource);
}

Desligar e parar a gravação

Por fim, quando detectamos uma condição que faz sentido para encerrarmos a chamada, podemos usar o método HangUpAsync para desligar a chamada.

if ((parsedEvent is PlayCompleted) || (parsedEvent is PlayFailed))
{
    logger.LogInformation($"Stop recording and terminating call.");
    callAutomationClient.GetCallRecording().Stop(recordingId);
    await callConnection.HangUpAsync(true);
}

Executar o código

Para executar o aplicativo com o VS Code, abra uma janela do Terminal e execute o comando a seguir

dotnet run

Abra http://localhost:8080/swagger/index.html ou a URL do túnel de desenvolvimento no navegador. A URL do túnel é semelhante a: <YOUR DEV TUNNEL ENDPOINT>/swagger/index.html

Pré-requisitos

Código de exemplo

Baixe ou clone o código de exemplo de início rápido do GitHub.

Navegue até a pasta CallAutomation_OutboundCalling e abra a solução em um editor de código.

Configurar e hospedar seu Azure DevTunnel

OAzure DevTunnels é um serviço do Azure que permite compartilhar serviços Web locais hospedados na Internet. Execute os comandos do DevTunnel para conectar seu ambiente de desenvolvimento local à Internet pública. Em seguida, o DevTunnels cria um túnel com uma URL de ponto de extremidade persistente e que permite acesso anônimo. Os Serviços de Comunicação do Azure usa esse ponto de extremidade para notificar seu aplicativo de eventos de chamada do serviço Automação de Chamadas dos Serviços de Comunicação do Azure.

devtunnel create --allow-anonymous
devtunnel port create -p MY_SPRINGAPP_PORT
devtunnel host

Atualize a configuração do aplicativo

Em seguida, abra o arquivo application.yml na pasta /resources para configurar os seguintes valores:

  • connectionstring: a cadeia de conexão do recurso dos Serviços de Comunicação do Azure. Encontre a cadeia de conexão dos Serviços de Comunicação do Azure usando as instruções descritas aqui.
  • basecallbackuri: depois de inicializar o host do DevTunnel, atualize esse campo com a URI.
  • callerphonenumber: atualize esse campo com o número de telefone dos Serviços de Comunicação do Azure que você adquiriu. Esse número de telefone deve usar o formato de número de telefone E164 (por exemplo, +18881234567)
  • targetphonenumber: atualize o campo com o número de telefone que você gostaria que seu aplicativo chamasse. Esse número de telefone deve usar o formato de número de telefone E164 (por exemplo, +18881234567)
  • cognitiveServiceEndpoint: atualize o campo com o ponto de extremidade dos serviços de IA do Azure.
  • targetTeamsUserId: (Opcional) atualize o campo com a ID de usuário do Microsoft Teams que você deseja adicionar à chamada. Consulte Usar a API do Graph para obter a ID de usuário do Teams.
acs:
  connectionstring: <YOUR ACS CONNECTION STRING> 
  basecallbackuri: <YOUR DEV TUNNEL ENDPOINT> 
  callerphonenumber: <YOUR ACS PHONE NUMBER ex. "+1425XXXAAAA"> 
  targetphonenumber: <YOUR TARGET PHONE NUMBER ex. "+1425XXXAAAA"> 
  cognitiveServiceEndpoint: <YOUR COGNITIVE SERVICE ENDPOINT>
  targetTeamsUserId: <(OPTIONAL) YOUR TARGET TEAMS USER ID ex. "ab01bc12-d457-4995-a27b-c405ecfe4870">

Fazer uma chamada de saída e reproduzir mídia

Para fazer a chamada de saída dos Serviços de Comunicação do Azure, este exemplo usa o targetphonenumber que você definiu no arquivo application.yml para criar a chamada usando a API createCallWithResponse.

PhoneNumberIdentifier caller = new PhoneNumberIdentifier(appConfig.getCallerphonenumber());
PhoneNumberIdentifier target = new PhoneNumberIdentifier(appConfig.getTargetphonenumber());
CallInvite callInvite = new CallInvite(target, caller);
CreateCallOptions createCallOptions = new CreateCallOptions(callInvite, appConfig.getCallBackUri());
CallIntelligenceOptions callIntelligenceOptions = new CallIntelligenceOptions().setCognitiveServicesEndpoint(appConfig.getCognitiveServiceEndpoint());
createCallOptions = createCallOptions.setCallIntelligenceOptions(callIntelligenceOptions);
Response<CreateCallResult> result = client.createCallWithResponse(createCallOptions, Context.NONE);

(Opcional) Adicionar um usuário do Microsoft Teams à chamada

Você pode adicionar um usuário do Microsoft Teams à chamada usando o addParticipant método com a MicrosoftTeamsUserIdentifier ID do usuário e do Teams. Primeiro, você precisa concluir a etapa de pré-requisito Autorização para o recurso dos Serviços de Comunicação do Azure para habilitar a chamada aos usuários do Microsoft Teams. Opcionalmente, você também pode passar um SourceDisplayName para controlar o texto exibido na notificação do sistema para o usuário do Teams.

client.getCallConnection(callConnectionId).addParticipant(
    new CallInvite(new MicrosoftTeamsUserIdentifier(targetTeamsUserId))
        .setSourceDisplayName("Jack (Contoso Tech Support)"));

Iniciar a gravação de uma chamada

O serviço de Automação de Chamadas também permite a capacidade de iniciar a gravação e armazenar gravações de chamadas de voz e vídeo. Você pode aprender mais sobre os vários recursos das APIs de gravação de chamadas aqui.

ServerCallLocator serverCallLocator = new ServerCallLocator(
    client.getCallConnection(callConnectionId)
        .getCallProperties()
        .getServerCallId());
        
StartRecordingOptions startRecordingOptions = new StartRecordingOptions(serverCallLocator);

Response<RecordingStateResult> response = client.getCallRecording()
    .startWithResponse(startRecordingOptions, Context.NONE);

recordingId = response.getValue().getRecordingId();

Responder a eventos de chamada

Anteriormente em nosso aplicativo, registramos o basecallbackuri no Serviço de Automação de Chamadas. O URI indica o ponto de extremidade que o serviço usará para nos notificar sobre a chamada de eventos que acontecem. Em seguida, podemos iterar pelos eventos e detectar eventos específicos que nosso aplicativo deseja entender. No código abaixo respondemos ao evento CallConnected.

List<CallAutomationEventBase> events = CallAutomationEventParser.parseEvents(reqBody);
for (CallAutomationEventBase event : events) {
    String callConnectionId = event.getCallConnectionId();
    if (event instanceof CallConnected) {
        log.info("CallConnected event received");
    }
    else if (event instanceof RecognizeCompleted) {
        log.info("Recognize Completed event received");
    }
}

Reproduza mensagem de boas-vindas e reconheça

Usando o TextSource, você pode fornecer ao serviço o texto que deseja sintetizar e usado para sua mensagem de boas-vindas. O serviço Automação de Chamadas dos Serviços de Comunicação do Azure reproduz essa mensagem após o evento CallConnected.

Em seguida, passamos o texto para o CallMediaRecognizeChoiceOptions e, em seguida, chamamos StartRecognizingAsync. Isso permite que seu aplicativo reconheça a opção escolhida pelo chamador.

var playSource = new TextSource().setText(content).setVoiceName("en-US-NancyNeural");

var recognizeOptions = new CallMediaRecognizeChoiceOptions(new PhoneNumberIdentifier(targetParticipant), getChoices())
  .setInterruptCallMediaOperation(false)
  .setInterruptPrompt(false)
  .setInitialSilenceTimeout(Duration.ofSeconds(10))
  .setPlayPrompt(playSource)
  .setOperationContext(context);

client.getCallConnection(callConnectionId)
  .getCallMedia()
  .startRecognizing(recognizeOptions);

private List < RecognitionChoice > getChoices() {
  var choices = Arrays.asList(
    new RecognitionChoice().setLabel(confirmLabel).setPhrases(Arrays.asList("Confirm", "First", "One")).setTone(DtmfTone.ONE),
    new RecognitionChoice().setLabel(cancelLabel).setPhrases(Arrays.asList("Cancel", "Second", "Two")).setTone(DtmfTone.TWO)
  );

  return choices;
}

Manipular eventos de escolha

A Automação de Chamadas dos Serviços de Comunicação do Azure dispara o api/callbacks para o webhook que configuramos e nos notificará com o evento RecognizeCompleted. O evento nos dá a capacidade de responder à entrada recebida e disparar uma ação. Em seguida, o aplicativo reproduz uma mensagem para o chamador com base na entrada específica recebida.

else if (event instanceof RecognizeCompleted) {
  log.info("Recognize Completed event received");

  RecognizeCompleted acsEvent = (RecognizeCompleted) event;

  var choiceResult = (ChoiceResult) acsEvent.getRecognizeResult().get();

  String labelDetected = choiceResult.getLabel();

  String phraseDetected = choiceResult.getRecognizedPhrase();

  log.info("Recognition completed, labelDetected=" + labelDetected + ", phraseDetected=" + phraseDetected + ", context=" + event.getOperationContext());

  String textToPlay = labelDetected.equals(confirmLabel) ? confirmedText : cancelText;

  handlePlay(callConnectionId, textToPlay);
}

private void handlePlay(final String callConnectionId, String textToPlay) {
  var textPlay = new TextSource()
    .setText(textToPlay)
    .setVoiceName("en-US-NancyNeural");

  client.getCallConnection(callConnectionId)
    .getCallMedia()
    .playToAll(textPlay);
}

Desligar a chamada

Por fim, quando detectamos uma condição que faz sentido para encerrarmos a chamada, podemos usar o método hangUp para desligar a chamada.

client.getCallConnection(callConnectionId).hangUp(true);

Executar o código

Acesse o diretório que contém o arquivo pom.xml e use os seguintes comandos mvn:

  • Compilar o aplicativo: mvn compile
  • Criar o pacote: mvn package
  • Executar o aplicativo: mvn exec:java

Pré-requisitos

Código de exemplo

Baixe ou clone o código de exemplo de início rápido do GitHub.

Navegue até a pasta CallAutomation_OutboundCalling e abra a solução em um editor de código.

Configurar o ambiente

Baixe o código de exemplo e navegue até o diretório do projeto e execute o comando npm, que instala as dependências necessárias e configure seu ambiente de desenvolvedor.

npm install

Configurar e hospedar seu Azure DevTunnel

OAzure DevTunnels é um serviço do Azure que permite compartilhar serviços Web locais hospedados na Internet. Use os comandos da CLI do DevTunnel para conectar seu ambiente de desenvolvimento local à Internet pública. Usamos esse ponto de extremidade para notificar seu aplicativo de eventos de chamada do serviço Automação de Chamadas dos Serviços de Comunicação do Azure.

devtunnel create --allow-anonymous
devtunnel port create -p 8080
devtunnel host

Atualize a configuração do aplicativo

Em seguida, atualize o arquivo .env com os seguintes valores:

  • CONNECTION_STRING: a cadeia de conexão do recurso dos Serviços de Comunicação do Azure. Encontre a cadeia de conexão dos Serviços de Comunicação do Azure usando as instruções descritas aqui.
  • CALLBACK_URI: depois de inicializar o host do DevTunnel, atualize esse campo com a URI.
  • TARGET_PHONE_NUMBER: atualize o campo com o número de telefone que você gostaria que seu aplicativo chamasse. Esse número de telefone deve usar o formato de número de telefone E164 (por exemplo, +18881234567)
  • ACS_RESOURCE_PHONE_NUMBER: atualize esse campo com o número de telefone dos Serviços de Comunicação do Azure que você adquiriu. Esse número de telefone deve usar o formato de número de telefone E164 (por exemplo, +18881234567)
  • COGNITIVE_SERVICES_ENDPOINT: atualize o campo com o ponto de extremidade dos serviços de IA do Azure.
  • TARGET_TEAMS_USER_ID: (Opcional) atualize o campo com a ID de usuário do Microsoft Teams que você deseja adicionar à chamada. Consulte Usar a API do Graph para obter a ID de usuário do Teams.
CONNECTION_STRING="<YOUR_CONNECTION_STRING>" 
ACS_RESOURCE_PHONE_NUMBER ="<YOUR_ACS_NUMBER>" 
TARGET_PHONE_NUMBER="<+1XXXXXXXXXX>" 
CALLBACK_URI="<VS_TUNNEL_URL>" 
COGNITIVE_SERVICES_ENDPOINT="<COGNITIVE_SERVICES_ENDPOINT>" 
TARGET_TEAMS_USER_ID="<TARGET_TEAMS_USER_ID>"

Fazer uma chamada de saída e reproduzir mídia

Para fazer a chamada de saída dos Serviços de Comunicação do Azure, use o número de telefone fornecido para o ambiente. Verifique se o número de telefone está no formato de número de telefone E164 (por exemplo, +18881234567)

O código faz uma chamada de saída por meio do target_phone_number que você forneceu e faz uma chamada de saída para esse número:

const callInvite: CallInvite = {
	targetParticipant: callee,
	sourceCallIdNumber: {
		phoneNumber: process.env.ACS_RESOURCE_PHONE_NUMBER || "",
	},
};

const options: CreateCallOptions = {
	cognitiveServicesEndpoint: process.env.COGNITIVE_SERVICES_ENDPOINT
};

console.log("Placing outbound call...");
acsClient.createCall(callInvite, process.env.CALLBACK_URI + "/api/callbacks", options);

(Opcional) Adicionar um usuário do Microsoft Teams à chamada

Você pode adicionar um usuário do Microsoft Teams à chamada usando o método addParticipant com a propriedade microsoftTeamsUserId. Primeiro, você precisa concluir a etapa de pré-requisito Autorização para o recurso dos Serviços de Comunicação do Azure para habilitar a chamada aos usuários do Microsoft Teams. Opcionalmente, você também pode passar um sourceDisplayName para controlar o texto exibido na notificação do sistema para o usuário do Teams.

await acsClient.getCallConnection(callConnectionId).addParticipant({
    targetParticipant: { microsoftTeamsUserId: process.env.TARGET_TEAMS_USER_ID },
    sourceDisplayName: "Jack (Contoso Tech Support)"
});

Iniciar a gravação de uma chamada

O serviço de Automação de Chamadas também permite a capacidade de iniciar a gravação e armazenar gravações de chamadas de voz e vídeo. Você pode aprender mais sobre os vários recursos das APIs de gravação de chamadas aqui.

const callLocator: CallLocator = {
    id: serverCallId,
    kind: "serverCallLocator",
};

const recordingOptions: StartRecordingOptions = {
    callLocator: callLocator,
};

const response = await acsClient.getCallRecording().start(recordingOptions);

recordingId = response.recordingId;

Responder a eventos de chamada

Anteriormente em nosso aplicativo, registramos o CALLBACK_URI no Serviço de Automação de Chamadas. O URI indica o ponto de extremidade que o serviço usa para nos notificar sobre a chamada de eventos que ocorrem. Em seguida, podemos iterar pelos eventos e detectar eventos específicos que nosso aplicativo deseja entender. Respondemos ao evento CallConnected para ser notificado e iniciar operações de downstream. Usando o TextSource, você pode fornecer ao serviço o texto que deseja sintetizar e usado para sua mensagem de boas-vindas. O serviço Automação de Chamadas dos Serviços de Comunicação do Azure reproduz essa mensagem após o evento CallConnected.

Em seguida, passamos o texto para o CallMediaRecognizeChoiceOptions e, em seguida, chamamos StartRecognizingAsync. Isso permite que seu aplicativo reconheça a opção escolhida pelo chamador.

callConnectionId = eventData.callConnectionId;
serverCallId = eventData.serverCallId;
console.log("Call back event received, callConnectionId=%s, serverCallId=%s, eventType=%s", callConnectionId, serverCallId, event.type);
callConnection = acsClient.getCallConnection(callConnectionId);
const callMedia = callConnection.getCallMedia();

if (event.type === "Microsoft.Communication.CallConnected") {
 	console.log("Received CallConnected event");
 	await startRecording();
	await startRecognizing(callMedia, mainMenu, "");
}

async function startRecognizing(callMedia: CallMedia, textToPlay: string, context: string) {
	const playSource: TextSource = {
 		text: textToPlay,
 		voiceName: "en-US-NancyNeural",
 		kind: "textSource"
 	};

 	const recognizeOptions: CallMediaRecognizeChoiceOptions = {
 		choices: await getChoices(),
 		interruptPrompt: false,
 		initialSilenceTimeoutInSeconds: 10,
 		playPrompt: playSource,
 		operationContext: context,
 		kind: "callMediaRecognizeChoiceOptions"
 	};

 	await callMedia.startRecognizing(callee, recognizeOptions)
 }

Manipular eventos de escolha

A Automação de Chamadas dos Serviços de Comunicação do Azure dispara o api/callbacks para o webhook que configuramos e nos notificará com o evento RecognizeCompleted. O evento nos dá a capacidade de responder à entrada recebida e disparar uma ação. Em seguida, o aplicativo reproduz uma mensagem para o chamador com base na entrada específica recebida.

else if (event.type === "Microsoft.Communication.RecognizeCompleted") { 
	if(eventData.recognitionType === "choices"){ 
        	console.log("Recognition completed, event=%s, resultInformation=%s",eventData, eventData.resultInformation); 
        	var context = eventData.operationContext; 
            	const labelDetected = eventData.choiceResult.label;  
            	const phraseDetected = eventData.choiceResult.recognizedPhrase; 
            	console.log("Recognition completed, labelDetected=%s, phraseDetected=%s, context=%s", labelDetected, phraseDetected, eventData.operationContext); 
            	const textToPlay = labelDetected === confirmLabel ? confirmText : cancelText;            
            	await handlePlay(callMedia, textToPlay); 
        } 
}  
 
async function handlePlay(callConnectionMedia:CallMedia, textContent:string){ 
	const play : TextSource = { text:textContent , voiceName: "en-US-NancyNeural", kind: "textSource"} 
	await callConnectionMedia.playToAll([play]); 
} 

Desligar a chamada

Por fim, quando detectamos uma condição que faz sentido para encerrarmos a chamada, podemos usar o método hangUp() para desligar a chamada.

  await acsClient.getCallRecording().stop(recordingId);
  callConnection.hangUp(true);

Executar o código

Para executar o aplicativo, abra uma janela terminal e execute o seguinte comando:

  npm run dev

Pré-requisitos

Código de exemplo

Baixe ou clone o código de exemplo de início rápido do GitHub.

Navegue até a pasta CallAutomation_OutboundCalling e abra a solução em um editor de código.

Configurar o ambiente do Python

Crie e ative o ambiente do Python e instale os pacotes necessários usando o comando a seguir. Você pode aprender mais sobre como gerenciar pacotes aqui

pip install -r requirements.txt

Configurar e hospedar seu Azure DevTunnel

OAzure DevTunnels é um serviço do Azure que permite compartilhar serviços Web locais hospedados na Internet. Use os comandos para conectar seu ambiente de desenvolvimento local à Internet pública. O DevTunnels cria um túnel com uma URL de ponto de extremidade persistente e que permite acesso anônimo. Usamos esse ponto de extremidade para notificar seu aplicativo de eventos de chamada do serviço Automação de Chamadas dos Serviços de Comunicação do Azure.

devtunnel create --allow-anonymous
devtunnel port create -p 8080
devtunnel host

Atualize a configuração do aplicativo

Em seguida, atualize o arquivo main.py com os seguintes valores:

  • ACS_CONNECTION_STRING: a cadeia de conexão do recurso dos Serviços de Comunicação do Azure. Encontre a cadeia de conexão dos Serviços de Comunicação do Azure usando as instruções descritas aqui.
  • CALLBACK_URI_HOST: depois de inicializar o host do DevTunnel, atualize esse campo com a URI.
  • TARGET_PHONE_NUMBER: atualize o campo com o número de telefone que você gostaria que seu aplicativo chamasse. Esse número de telefone deve usar o formato de número de telefone E164 (por exemplo, +18881234567)
  • ACS_PHONE_NUMBER: atualize esse campo com o número de telefone dos Serviços de Comunicação do Azure que você adquiriu. Esse número de telefone deve usar o formato de número de telefone E164 (por exemplo, +18881234567)
  • COGNITIVE_SERVICES_ENDPOINT: atualize o campo com o ponto de extremidade dos serviços de IA do Azure.
  • TARGET_TEAMS_USER_ID: (Opcional) atualize o campo com a ID de usuário do Microsoft Teams que você deseja adicionar à chamada. Consulte Usar a API do Graph para obter a ID de usuário do Teams.
# Your ACS resource connection string 
ACS_CONNECTION_STRING = "<ACS_CONNECTION_STRING>" 

# Your ACS resource phone number will act as source number to start outbound call 
ACS_PHONE_NUMBER = "<ACS_PHONE_NUMBER>" 

# Target phone number you want to receive the call. 
TARGET_PHONE_NUMBER = "<TARGET_PHONE_NUMBER>" 

# Callback events URI to handle callback events. 
CALLBACK_URI_HOST = "<CALLBACK_URI_HOST_WITH_PROTOCOL>" 
CALLBACK_EVENTS_URI = CALLBACK_URI_HOST + "/api/callbacks" 

#Your Cognitive service endpoint 
COGNITIVE_SERVICES_ENDPOINT = "<COGNITIVE_SERVICES_ENDPOINT>" 

#(OPTIONAL) Your target Microsoft Teams user Id ex. "ab01bc12-d457-4995-a27b-c405ecfe4870"
TARGET_TEAMS_USER_ID = "<TARGET_TEAMS_USER_ID>"

Fazer uma chamada de saída

Para fazer a chamada de saída dos Serviços de Comunicação do Azure, primeiro forneça o número de telefone que deseja receber a chamada. Para simplificar, você pode atualizar o target_phone_number com um número de telefone no formato de número de telefone E164 (por exemplo, +18881234567)

Faça uma chamada de saída por meio do target_phone_number que você forneceu:

target_participant = PhoneNumberIdentifier(TARGET_PHONE_NUMBER) 
source_caller = PhoneNumberIdentifier(ACS_PHONE_NUMBER) 
call_invite = CallInvite(target=target_participant, source_caller_id_number=source_caller) 
call_connection_properties = call_automation_client.create_call(call_invite, CALLBACK_EVENTS_URI, 
cognitive_services_endpoint=COGNITIVE_SERVICES_ENDPOINT) 
    app.logger.info("Created call with connection id: %s",
call_connection_properties.call_connection_id) 
return redirect("/") 

(Opcional) Adicionar um usuário do Microsoft Teams à chamada

Você pode adicionar um usuário do Microsoft Teams à chamada usando o add_participant método com a MicrosoftTeamsUserIdentifier ID do usuário e do Teams. Primeiro, você precisa concluir a etapa de pré-requisito Autorização para o recurso dos Serviços de Comunicação do Azure para habilitar a chamada aos usuários do Microsoft Teams. Opcionalmente, você também pode passar um source_display_name para controlar o texto exibido na notificação do sistema para o usuário do Teams.

call_connection_client.add_participant(target_participant = CallInvite(
    target = MicrosoftTeamsUserIdentifier(user_id=TARGET_TEAMS_USER_ID),
    source_display_name = "Jack (Contoso Tech Support)"))

Iniciar a gravação de uma chamada

O serviço de Automação de Chamadas também permite a capacidade de iniciar a gravação e armazenar gravações de chamadas de voz e vídeo. Você pode aprender mais sobre os vários recursos das APIs de gravação de chamadas aqui.

recording_properties = call_automation_client.start_recording(ServerCallLocator(event.data['serverCallId']))
recording_id = recording_properties.recording_id

Responder a eventos de chamada

Anteriormente em nosso aplicativo, registramos o CALLBACK_URI_HOST no Serviço de Automação de Chamadas. O URI indica o ponto de extremidade que o serviço usa para nos notificar sobre a chamada de eventos que ocorrem. Em seguida, podemos iterar pelos eventos e detectar eventos específicos que nosso aplicativo deseja entender. No código abaixo respondemos ao evento CallConnected.

@app.route('/api/callbacks', methods=['POST'])
def callback_events_handler():
    for event_dict in request.json:
        event = CloudEvent.from_dict(event_dict)
        if event.type == "Microsoft.Communication.CallConnected":
            # Handle Call Connected Event
            ...
            return Response(status=200)

Reproduza mensagem de boas-vindas e reconheça

Usando o TextSource, você pode fornecer ao serviço o texto que deseja sintetizar e usado para sua mensagem de boas-vindas. O serviço Automação de Chamadas dos Serviços de Comunicação do Azure reproduz essa mensagem após o evento CallConnected.

Em seguida, passamos o texto para o CallMediaRecognizeChoiceOptions e, em seguida, chamamos StartRecognizingAsync. Isso permite que seu aplicativo reconheça a opção escolhida pelo chamador.


get_media_recognize_choice_options( 
    call_connection_client=call_connection_client, 
    text_to_play=MainMenu,  
    target_participant=target_participant, 
    choices=get_choices(),context="") 

def get_media_recognize_choice_options(call_connection_client: CallConnectionClient, text_to_play: str, target_participant:str, choices: any, context: str): 
    play_source =  TextSource (text= text_to_play, voice_name= SpeechToTextVoice) 
    call_connection_client.start_recognizing_media( 
        input_type=RecognizeInputType.CHOICES, 

        target_participant=target_participant,
        choices=choices, 
        play_prompt=play_source, 
        interrupt_prompt=False, 
        initial_silence_timeout=10, 
        operation_context=context 
    ) 

def get_choices(): 
    choices = [ 
        RecognitionChoice(label = ConfirmChoiceLabel, phrases= ["Confirm", "First", "One"], tone = DtmfTone.ONE), 
        RecognitionChoice(label = CancelChoiceLabel, phrases= ["Cancel", "Second", "Two"], tone = DtmfTone.TWO) 
    ] 
return choices 

Manipular eventos de escolha

A Automação de Chamadas dos Serviços de Comunicação do Azure dispara o api/callbacks para o webhook que configuramos e nos notificará com o evento RecognizeCompleted. O evento nos dá a capacidade de responder à entrada recebida e disparar uma ação. Em seguida, o aplicativo reproduz uma mensagem para o chamador com base na entrada específica recebida.

elif event.type == "Microsoft.Communication.RecognizeCompleted":
	app.logger.info("Recognize completed: data=%s", event.data)
if 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'))
if labelDetected == ConfirmChoiceLabel:
	textToPlay = ConfirmedText
else:
	textToPlay = CancelText
handle_play(call_connection_client = call_connection_client, text_to_play = textToPlay)
def handle_play(call_connection_client: CallConnectionClient, text_to_play: str):
	play_source = TextSource(text = text_to_play, voice_name = SpeechToTextVoice)
call_connection_client.play_media_to_all(play_source)

Desligar a chamada

Por fim, quando detectamos uma condição que faz sentido para encerrarmos a chamada, podemos usar o método hang_up() para desligar a chamada. Por fim, também podemos interromper com segurança a operação de gravação de chamadas.

call_automation_client.stop_recording(recording_id)
call_connection_client.hang_up(is_for_everyone=True)

Executar o código

Para executar o aplicativo com o VS Code, abra uma janela do Terminal e execute o comando a seguir

python main.py