Guida introduttiva: effettuare una chiamata in uscita con Automazione delle chiamate

Le API di Automazione delle chiamate di Servizi di comunicazione di Azure sono un modo efficace per creare esperienze di chiamata interattive. In questa guida introduttiva viene illustrato un modo per effettuare una chiamata in uscita e riconoscere vari eventi nella chiamata.

Prerequisiti

Codice di esempio

Scaricare o clonare il codice di esempio di avvio rapido da GitHub.

Passare alla cartella CallAutomation_OutboundCalling e aprire la soluzione in un editor di codice.

Configurare e ospitare Azure DevTunnel

Azure DevTunnels è un servizio di Azure che consente di condividere servizi Web locali ospitati su Internet. Eseguire i comandi per connettere l'ambiente di sviluppo locale alla rete Internet pubblica. DevTunnels crea un URL dell'endpoint permanente che consente l'accesso anonimo. Questo endpoint viene usato per notificare all'applicazione gli eventi di chiamata dal servizio Automazione delle chiamate di Servizi di comunicazione di Azure.

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

In alternativa, seguire le istruzioni per configurare Azure DevTunnel in Visual Studio

Aggiornare la configurazione dell'applicazione

Aggiornare quindi il file Program.cs con i valori seguenti:

  • acsConnectionString: stringa di connessione per la risorsa Servizi di comunicazione di Azure. È possibile trovare la stringa di connessione di Servizi di comunicazione di Azure seguendo le istruzioni riportate qui.
  • callbackUriHost: dopo aver inizializzato l'host DevTunnel, aggiornare questo campo con tale URI.
  • acsPhonenumber: aggiornare questo campo con il numero di telefono di Servizi di comunicazione di Azure acquisito. Questo numero di telefono deve usare il formato numero di telefono E164 (ad esempio +18881234567)
  • targetPhonenumber: aggiornare il campo con il numero di telefono che si desidera far chiamare dall'applicazione. Questo numero di telefono deve usare il formato numero di telefono E164 (ad esempio +18881234567)
  • cognitiveServiceEndpoint: aggiornare il campo con l'endpoint di Servizi di Azure AI.
  • targetTeamsUserId: (facoltativo) aggiornare il campo con l'ID utente di Microsoft Teams che si vuole aggiungere alla chiamata. Vedere Usare l'API Graph per ottenere l'ID utente di 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>";

Effettuare una chiamata in uscita

Per effettuare la chiamata in uscita da Servizi di comunicazione di Azure, questo esempio usa l'oggetto targetPhonenumber definito in precedenza nell'applicazione per creare la chiamata usando l'API CreateCallAsync. Questo codice eseguirà una chiamata in uscita usando il numero di telefono di destinazione.

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

Gestire gli eventi di automazione delle chiamate

In precedenza nell'applicazione è stato registrato callbackUriHost nel servizio Automazione delle chiamate. L'host indica che l'endpoint richiesto dal servizio deve inviare una notifica sugli eventi di chiamata che si verificano. È quindi possibile eseguire l'iterazione degli eventi e rilevare eventi specifici che l'applicazione vuole comprendere. Nel codice riportato di seguito viene risposto all'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
    }
  }
});

(Facoltativo) Aggiungere un utente di Microsoft Teams alla chiamata

È possibile aggiungere un utente di Microsoft Teams alla chiamata usando il metodo AddParticipantAsync con MicrosoftTeamsUserIdentifier e l'ID dell'utente di Teams. Per abilitare la chiamata agli utenti di Microsoft Teams, è prima necessario completare il passaggio del prerequisito di autorizzazione per la risorsa Servizi di comunicazione di Azure. Facoltativamente, è anche possibile passare un oggetto SourceDisplayName per controllare il testo visualizzato nella notifica di tipo avviso popup per l'utente di Teams.

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

Avviare la registrazione di una chiamata

Il servizio Automazione delle chiamate consente anche di avviare la registrazione e archiviare le registrazioni delle chiamate vocali e video. Altre informazioni sulle varie funzionalità disponibili nelle API di registrazione delle chiamate sono disponibili qui.

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

Riprodurre un messaggio di benvenuto e riconoscimento

Usando TextSource, è possibile fornire al servizio il testo che si vuole sintetizzare e usare per il messaggio di benvenuto. Il servizio Automazione delle chiamate di Servizi di comunicazione di Azure riproduce questo messaggio all'evento CallConnected.

Passare quindi il testo nell'oggetto CallMediaRecognizeChoiceOptions, poi chiamare StartRecognizingAsync. Ciò consente all'applicazione di riconoscere l'opzione scelta dal chiamante.

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

Gestire gli eventi di scelta

Automazione delle chiamate di Servizi di comunicazione di Azure attiva api/callbacks nel webhook configurato e invia una notifica con l'evento RecognizeCompleted. L'evento consente di rispondere all'input ricevuto e attivare un'azione. L'applicazione riproduce quindi un messaggio al chiamante in base all'input specifico ricevuto.

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

Interruzione della chiamata e della registrazione

Infine, quando viene rilevata una condizione per cui ha senso terminare la chiamata, è possibile usare il metodo HangUpAsync per interromperla.

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

Eseguire il codice

Per eseguire l'applicazione con VS Code, aprire una finestra del terminale ed eseguire il comando seguente

dotnet run

Aprire http://localhost:8080/swagger/index.html o l'URL del tunnel di sviluppo nel browser. L'URL del tunnel è simile al seguente: <YOUR DEV TUNNEL ENDPOINT>/swagger/index.html

Prerequisiti

Codice di esempio

Scaricare o clonare il codice di esempio di avvio rapido da GitHub.

Passare alla cartella CallAutomation_OutboundCalling e aprire la soluzione in un editor di codice.

Configurare e ospitare Azure DevTunnel

Azure DevTunnels è un servizio di Azure che consente di condividere servizi Web locali ospitati su Internet. Eseguire i comandi di DevTunnel per connettere l'ambiente di sviluppo locale alla rete Internet pubblica. DevTunnels crea quindi un tunnel con un URL dell'endpoint permanente che consente l'accesso anonimo. Servizi di comunicazione di Azure usa questo endpoint per notificare all'applicazione gli eventi di chiamata dal servizio Automazione delle chiamate di Servizi di comunicazione di Azure.

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

Aggiornare la configurazione dell'applicazione

Aprire quindi il file application.yml nella cartella /resources per configurare i valori seguenti:

  • connectionstring: stringa di connessione per la risorsa Servizi di comunicazione di Azure. È possibile trovare la stringa di connessione di Servizi di comunicazione di Azure seguendo le istruzioni riportate qui.
  • basecallbackuri: dopo aver inizializzato l'host DevTunnel, aggiornare questo campo con tale URI.
  • callerphonenumber: aggiornare questo campo con il numero di telefono di Servizi di comunicazione di Azure acquisito. Questo numero di telefono deve usare il formato numero di telefono E164 (ad esempio +18881234567)
  • targetphonenumber: aggiornare il campo con il numero di telefono che si desidera far chiamare dall'applicazione. Questo numero di telefono deve usare il formato numero di telefono E164 (ad esempio +18881234567)
  • cognitiveServiceEndpoint: aggiornare il campo con l'endpoint di Servizi di Azure AI.
  • targetTeamsUserId: (facoltativo) aggiornare il campo con l'ID utente di Microsoft Teams che si vuole aggiungere alla chiamata. Vedere Usare l'API Graph per ottenere l'ID utente di 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">

Effettuare una chiamata in uscita e riprodurre contenuti multimediali

Per effettuare la chiamata in uscita da Servizi di comunicazione di Azure, questo esempio usa l'oggetto targetphonenumber definito nel file application.yml per creare la chiamata usando l'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);

(Facoltativo) Aggiungere un utente di Microsoft Teams alla chiamata

È possibile aggiungere un utente di Microsoft Teams alla chiamata usando il metodo addParticipant con MicrosoftTeamsUserIdentifier e l'ID dell'utente di Teams. Per abilitare la chiamata agli utenti di Microsoft Teams, è prima necessario completare il passaggio del prerequisito di autorizzazione per la risorsa Servizi di comunicazione di Azure. Facoltativamente, è anche possibile passare un oggetto SourceDisplayName per controllare il testo visualizzato nella notifica di tipo avviso popup per l'utente di Teams.

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

Avviare la registrazione di una chiamata

Il servizio Automazione delle chiamate consente anche di avviare la registrazione e archiviare le registrazioni delle chiamate vocali e video. Altre informazioni sulle varie funzionalità disponibili nelle API di registrazione delle chiamate sono disponibili qui.

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

Rispondere agli eventi di chiamata

In precedenza nell'applicazione è stato registrato basecallbackuri nel servizio Automazione delle chiamate. L'URI indica l'endpoint che verrà usato dal servizio per inviare una notifica sugli eventi di chiamata che si verificano. È quindi possibile eseguire l'iterazione degli eventi e rilevare eventi specifici che l'applicazione vuole comprendere. Nel codice riportato di seguito viene risposto all'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");
    }
}

Riprodurre un messaggio di benvenuto e riconoscimento

Usando TextSource, è possibile fornire al servizio il testo che si vuole sintetizzare e usare per il messaggio di benvenuto. Il servizio Automazione delle chiamate di Servizi di comunicazione di Azure riproduce questo messaggio all'evento CallConnected.

Passare quindi il testo nell'oggetto CallMediaRecognizeChoiceOptions, poi chiamare StartRecognizingAsync. Ciò consente all'applicazione di riconoscere l'opzione scelta dal chiamante.

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

Gestire gli eventi di scelta

Automazione delle chiamate di Servizi di comunicazione di Azure attiva api/callbacks nel webhook configurato e invia una notifica con l'evento RecognizeCompleted. L'evento consente di rispondere all'input ricevuto e attivare un'azione. L'applicazione riproduce quindi un messaggio al chiamante in base all'input specifico ricevuto.

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

Interrompere la chiamata

Infine, quando viene rilevata una condizione per cui ha senso terminare la chiamata, è possibile usare il metodo hangUp per interromperla.

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

Eseguire il codice

Passare alla directory contenente il file pom.xml e usare i comandi mvn seguenti:

  • Compilare l'applicazione: mvn compile
  • Compilare il pacchetto: mvn package
  • Eseguire l'app: mvn exec:java

Prerequisiti

Codice di esempio

Scaricare o clonare il codice di esempio di avvio rapido da GitHub.

Passare alla cartella CallAutomation_OutboundCalling e aprire la soluzione in un editor di codice.

Configurare l'ambiente

Scaricare il codice di esempio, passare alla directory del progetto ed eseguire il comando npm che installa le dipendenze necessarie e configura l'ambiente per sviluppatori.

npm install

Configurare e ospitare Azure DevTunnel

Azure DevTunnels è un servizio di Azure che consente di condividere servizi Web locali ospitati su Internet. Usare i comandi dell’interfaccia della riga di comando di DevTunnel per connettere l'ambiente di sviluppo locale alla rete Internet pubblica. Questo endpoint viene usato per notificare all'applicazione gli eventi di chiamata dal servizio Automazione delle chiamate di Servizi di comunicazione di Azure.

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

Aggiornare la configurazione dell'applicazione

Aggiornare quindi il file .env con i valori seguenti:

  • CONNECTION_STRING: stringa di connessione per la risorsa Servizi di comunicazione di Azure. È possibile trovare la stringa di connessione di Servizi di comunicazione di Azure seguendo le istruzioni riportate qui.
  • CALLBACK_URI: dopo aver inizializzato l'host DevTunnel, aggiornare questo campo con tale URI.
  • TARGET_PHONE_NUMBER: aggiornare il campo con il numero di telefono che si desidera far chiamare dall'applicazione. Questo numero di telefono deve usare il formato numero di telefono E164 (ad esempio +18881234567)
  • ACS_RESOURCE_PHONE_NUMBER: aggiornare questo campo con il numero di telefono di Servizi di comunicazione di Azure acquisito. Questo numero di telefono deve usare il formato numero di telefono E164 (ad esempio +18881234567)
  • COGNITIVE_SERVICES_ENDPOINT: aggiornare il campo con l'endpoint di Servizi di Azure AI.
  • TARGET_TEAMS_USER_ID: (facoltativo) aggiornare il campo con l'ID utente di Microsoft Teams che si vuole aggiungere alla chiamata. Vedere Usare l'API Graph per ottenere l'ID utente di 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>"

Effettuare una chiamata in uscita e riprodurre contenuti multimediali

Per effettuare la chiamata in uscita da Servizi di comunicazione di Azure, usare il numero di telefono fornito all'ambiente. Assicurarsi che il numero di telefono sia nel formato E164 (ad esempio +18881234567)

Il codice effettua una chiamata in uscita usando il target_phone_number specificato e inserisce una chiamata in uscita a tale numero:

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

(Facoltativo) Aggiungere un utente di Microsoft Teams alla chiamata

È possibile aggiungere un utente di Microsoft Teams alla chiamata usando il metodo addParticipant con la proprietà microsoftTeamsUserId. Per abilitare la chiamata agli utenti di Microsoft Teams, è prima necessario completare il passaggio del prerequisito di autorizzazione per la risorsa Servizi di comunicazione di Azure. Facoltativamente, è anche possibile passare un oggetto sourceDisplayName per controllare il testo visualizzato nella notifica di tipo avviso popup per l'utente di Teams.

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

Avviare la registrazione di una chiamata

Il servizio Automazione delle chiamate consente anche di avviare la registrazione e archiviare le registrazioni delle chiamate vocali e video. Altre informazioni sulle varie funzionalità disponibili nelle API di registrazione delle chiamate sono disponibili qui.

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

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

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

recordingId = response.recordingId;

Rispondere agli eventi di chiamata

In precedenza nell'applicazione è stato registrato CALLBACK_URI nel servizio Automazione delle chiamate. L'URI indica l'endpoint che viene usato dal servizio per inviare una notifica sugli eventi di chiamata che si verificano. È quindi possibile eseguire l'iterazione degli eventi e rilevare eventi specifici che l'applicazione vuole comprendere. Rispondiamo all'evento CallConnected per ricevere una notifica e avviare le operazioni downstream. Usando TextSource, è possibile fornire al servizio il testo che si vuole sintetizzare e usare per il messaggio di benvenuto. Il servizio Automazione delle chiamate di Servizi di comunicazione di Azure riproduce questo messaggio all'evento CallConnected.

Passare quindi il testo nell'oggetto CallMediaRecognizeChoiceOptions, poi chiamare StartRecognizingAsync. Ciò consente all'applicazione di riconoscere l'opzione scelta dal chiamante.

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

Gestire gli eventi di scelta

Automazione delle chiamate di Servizi di comunicazione di Azure attiva api/callbacks nel webhook configurato e invia una notifica con l'evento RecognizeCompleted. L'evento consente di rispondere all'input ricevuto e attivare un'azione. L'applicazione riproduce quindi un messaggio al chiamante in base all'input specifico ricevuto.

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

Interrompere la chiamata

Infine, quando viene rilevata una condizione per cui ha senso terminare la chiamata, è possibile usare il metodo hangUp() per interromperla.

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

Eseguire il codice

Per eseguire l'applicazione, aprire una finestra del terminale ed eseguire il comando seguente:

  npm run dev

Prerequisiti

Codice di esempio

Scaricare o clonare il codice di esempio di avvio rapido da GitHub.

Passare alla cartella CallAutomation_OutboundCalling e aprire la soluzione in un editor di codice.

Configurare l’ambiente Python

Creare e attivare l'ambiente Python e installare i pacchetti necessari usando il comando seguente. Altre informazioni sulla gestione dei pacchetti sono disponibili qui

pip install -r requirements.txt

Configurare e ospitare Azure DevTunnel

Azure DevTunnels è un servizio di Azure che consente di condividere servizi Web locali ospitati su Internet. Usare i comandi per connettere l'ambiente di sviluppo locale alla rete Internet pubblica. DevTunnels crea un tunnel con un URL dell'endpoint permanente che consente l'accesso anonimo. Questo endpoint viene usato per notificare all'applicazione gli eventi di chiamata dal servizio Automazione delle chiamate di Servizi di comunicazione di Azure.

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

Aggiornare la configurazione dell'applicazione

Aggiornare quindi il file main.py con i valori seguenti:

  • ACS_CONNECTION_STRING: stringa di connessione per la risorsa Servizi di comunicazione di Azure. È possibile trovare la stringa di connessione di Servizi di comunicazione di Azure seguendo le istruzioni riportate qui.
  • CALLBACK_URI_HOST: dopo aver inizializzato l'host DevTunnel, aggiornare questo campo con tale URI.
  • TARGET_PHONE_NUMBER: aggiornare il campo con il numero di telefono che si desidera far chiamare dall'applicazione. Questo numero di telefono deve usare il formato numero di telefono E164 (ad esempio +18881234567)
  • ACS_PHONE_NUMBER: aggiornare questo campo con il numero di telefono di Servizi di comunicazione di Azure acquisito. Questo numero di telefono deve usare il formato numero di telefono E164 (ad esempio +18881234567)
  • COGNITIVE_SERVICES_ENDPOINT: aggiornare il campo con l'endpoint di Servizi di Azure AI.
  • TARGET_TEAMS_USER_ID: (facoltativo) aggiornare il campo con l'ID utente di Microsoft Teams che si vuole aggiungere alla chiamata. Vedere Usare l'API Graph per ottenere l'ID utente di 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>"

Effettuare una chiamata in uscita

Per effettuare la chiamata in uscita da Servizi di comunicazione di Azure, fornire innanzitutto il numero di telefono su cui si vuole ricevere la chiamata. Per semplificare l'operazione, è possibile aggiornare target_phone_number con un numero di telefono nel formato E164 (ad esempio +18881234567)

Effettuare una chiamata in uscita usando il target_phone_number fornito:

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("/") 

(Facoltativo) Aggiungere un utente di Microsoft Teams alla chiamata

È possibile aggiungere un utente di Microsoft Teams alla chiamata usando il metodo add_participant con MicrosoftTeamsUserIdentifier e l'ID dell'utente di Teams. Per abilitare la chiamata agli utenti di Microsoft Teams, è prima necessario completare il passaggio del prerequisito di autorizzazione per la risorsa Servizi di comunicazione di Azure. Facoltativamente, è anche possibile passare un oggetto source_display_name per controllare il testo visualizzato nella notifica di tipo avviso popup per l'utente di Teams.

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

Avviare la registrazione di una chiamata

Il servizio Automazione delle chiamate consente anche di avviare la registrazione e archiviare le registrazioni delle chiamate vocali e video. Altre informazioni sulle varie funzionalità disponibili nelle API di registrazione delle chiamate sono disponibili qui.

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

Rispondere agli eventi di chiamata

In precedenza nell'applicazione è stato registrato CALLBACK_URI_HOST nel servizio Automazione delle chiamate. L'URI indica l'endpoint che viene usato dal servizio per inviare una notifica sugli eventi di chiamata che si verificano. È quindi possibile eseguire l'iterazione degli eventi e rilevare eventi specifici che l'applicazione vuole comprendere. Nel codice riportato di seguito viene risposto all'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)

Riprodurre un messaggio di benvenuto e riconoscimento

Usando TextSource, è possibile fornire al servizio il testo che si vuole sintetizzare e usare per il messaggio di benvenuto. Il servizio Automazione delle chiamate di Servizi di comunicazione di Azure riproduce questo messaggio all'evento CallConnected.

Passare quindi il testo nell'oggetto CallMediaRecognizeChoiceOptions, poi chiamare StartRecognizingAsync. Ciò consente all'applicazione di riconoscere l'opzione scelta dal chiamante.


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 

Gestire gli eventi di scelta

Automazione delle chiamate di Servizi di comunicazione di Azure attiva api/callbacks nel webhook configurato e invia una notifica con l'evento RecognizeCompleted. L'evento consente di rispondere all'input ricevuto e attivare un'azione. L'applicazione riproduce quindi un messaggio al chiamante in base all'input specifico ricevuto.

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)

Interrompere la chiamata

Infine, quando viene rilevata una condizione per cui ha senso terminare la chiamata, è possibile usare il metodo hang_up() per interromperla. Infine, è anche possibile arrestare in modo sicuro l'operazione di registrazione chiamata.

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

Eseguire il codice

Per eseguire l'applicazione con VS Code, aprire una finestra del terminale ed eseguire il comando seguente

python main.py