From 0f4a704bdf03a526b5782bd8ba620c1f1cc62a5e Mon Sep 17 00:00:00 2001 From: Pilli Vamshi Date: Wed, 19 Jun 2024 17:52:01 +0530 Subject: [PATCH 1/2] added testing feature for SDK beta4 branch --- .../CallAutomation_OutboundCalling/Program.cs | 428 +++++++++++++++++- 1 file changed, 409 insertions(+), 19 deletions(-) diff --git a/CallAutomation_OutboundCalling/CallAutomation_OutboundCalling/Program.cs b/CallAutomation_OutboundCalling/CallAutomation_OutboundCalling/Program.cs index 9fa19699..c832975a 100644 --- a/CallAutomation_OutboundCalling/CallAutomation_OutboundCalling/Program.cs +++ b/CallAutomation_OutboundCalling/CallAutomation_OutboundCalling/Program.cs @@ -3,37 +3,33 @@ using Azure.Messaging; using Azure.Messaging.EventGrid; using Azure.Messaging.EventGrid.SystemEvents; +using Microsoft.Extensions.Logging; var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // Your ACS resource connection string -var acsConnectionString = ""; +var acsConnectionString = ""; // Your ACS resource phone number will act as source number to start outbound call -var acsPhonenumber = ""; +var acsPhonenumber = ""; // Target phone number you want to receive the call. -var targetPhonenumber = ""; +var targetPhonenumber = ""; // Base url of the app -var callbackUriHost = ""; +var callbackUriHost = ""; // Your cognitive service endpoint -var cognitiveServiceEndpoint = ""; +var cognitiveServiceEndpoint = ""; // text to play const string SpeechToTextVoice = "en-US-NancyNeural"; -const string MainMenu = - """ - Hello this is Contoso Bank, we’re calling in regard to your appointment tomorrow - at 9am to open a new account. Please say confirm if this time is still suitable for you or say cancel - if you would like to cancel this appointment. - """; +const string MainMenu = "Please say confirm or say cancel to proceed further."; const string ConfirmedText = "Thank you for confirming your appointment tomorrow at 9am, we look forward to meeting with you."; const string CancelText = """ -Your appointment tomorrow at 9am has been cancelled. Please call the bank directly +Your appointment tomorrow at 9am has been cancelled. Please call the bank directly s if you would like to rebook for another date and time. """; const string CustomerQueryTimeout = "I’m sorry I didn’t receive a response, please try again."; @@ -41,8 +37,10 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct const string InvalidAudio = "I’m sorry, I didn’t understand your response, please try again."; const string ConfirmChoiceLabel = "Confirm"; const string RetryContext = "retry"; +const string dtmfPrompt = "Thank you for the update. Please type one two three four on your keypad to close call."; +string cancelLabel = "Cancel"; -CallAutomationClient callAutomationClient = new CallAutomationClient(acsConnectionString); +CallAutomationClient callAutomationClient = new CallAutomationClient(new Uri(""), acsConnectionString); var app = builder.Build(); app.MapPost("/outboundCall", async (ILogger logger) => @@ -51,6 +49,29 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct PhoneNumberIdentifier caller = new PhoneNumberIdentifier(acsPhonenumber); var callbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"); CallInvite callInvite = new CallInvite(target, caller); + + MediaStreamingOptions mediaStreamingOptions = new MediaStreamingOptions( + new Uri("wss://t9x01h42-5000.inc1.devtunnels.ms/ws"), + MediaStreamingContent.Audio, + MediaStreamingAudioChannel.Mixed, + MediaStreamingTransport.Websocket, + false); + var createCallOptions = new CreateCallOptions(callInvite, callbackUri) + { + CallIntelligenceOptions = new CallIntelligenceOptions() { CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) }, + //MediaStreamingOptions = mediaStreamingOptions, + //TranscriptionOptions = new TranscriptionOptions(new Uri("wss://jg1tlgbv-5000.inc1.devtunnels.ms/ws"), "en-US", false, TranscriptionTransport.Websocket) + }; + CreateCallResult createCallResult = await callAutomationClient.CreateCallAsync(createCallOptions); + + logger.LogInformation($"Created call with connection id: {createCallResult.CallConnectionProperties.CallConnectionId}"); +}); +app.MapPost("/createPSTNCall", async (ILogger logger) => +{ + PhoneNumberIdentifier target = new PhoneNumberIdentifier("+18332638155"); + PhoneNumberIdentifier caller = new PhoneNumberIdentifier("+18772119545"); + var callbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"); + CallInvite callInvite = new CallInvite(target, caller); var createCallOptions = new CreateCallOptions(callInvite, callbackUri) { CallIntelligenceOptions = new CallIntelligenceOptions() { CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) } @@ -65,6 +86,7 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct { foreach (var cloudEvent in cloudEvents) { + PhoneNumberIdentifier target = new PhoneNumberIdentifier(targetPhonenumber); CallAutomationEventBase parsedEvent = CallAutomationEventParser.Parse(cloudEvent); logger.LogInformation( "Received call event: {type}, callConnectionID: {connId}, serverCallId: {serverId}", @@ -74,14 +96,105 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct var callConnection = callAutomationClient.GetCallConnection(parsedEvent.CallConnectionId); var callMedia = callConnection.GetCallMedia(); + logger.LogInformation($"CALL CONNECTION ID ----> {parsedEvent.CallConnectionId}"); + logger.LogInformation($"CORRELATION ID ----> {parsedEvent.CorrelationId}"); + var connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + logger.LogInformation($"ANSWERED FOR ----> {connectionProperties.Value.AnsweredFor}"); + + if (parsedEvent is CallConnected callConnected) - { + { + #region Transfer Call + //PhoneNumberIdentifier caller = new PhoneNumberIdentifier("+18772119545"); + //var transferOption = new TransferToParticipantOptions(target); + ////transferOption.Transferee = caller; + //transferOption.OperationContext = "transferCallContext"; + //transferOption.SourceCallerIdNumber = caller; + + //// Sending event to a non-default endpoint. + //transferOption.OperationCallbackUri = new Uri(callbackUriHost); + //TransferCallToParticipantResult result = await callConnection.TransferCallToParticipantAsync(transferOption); + //logger.LogInformation($"Call Transfered successfully"); + //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + #endregion + + #region Media streaming + //StartMediaStreamingOptions options = new StartMediaStreamingOptions() + //{ + // OperationCallbackUri = new Uri(callbackUriHost), + // OperationContext = "startMediaStreamingContext" + //}; + //await callMedia.StartMediaStreamingAsync(options); + //logger.LogInformation("Start Media Streaming....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + //await Task.Delay(5000); + + ////Stop Media Streaming + //StopMediaStreamingOptions stopOptions = new StopMediaStreamingOptions() + //{ + // OperationCallbackUri = new Uri(callbackUriHost) + //}; + + //await callMedia.StopMediaStreamingAsync(stopOptions); + //logger.LogInformation("Stop Media Streaming....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + //await Task.Delay(5000); + + ////Start media streaming + //await callMedia.StartMediaStreamingAsync(options); + //logger.LogInformation("Start Media Streaming....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + #endregion + + #region Transcription + //StartTranscriptionOptions options = new StartTranscriptionOptions() + //{ + // OperationContext = "startMediaStreamingContext", + // //Locale = "en-US", + //}; + //await callMedia.StartTranscriptionAsync(options); + //logger.LogInformation("Start Transcription....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Transcription Subscription state ----> {connectionProperties.Value.TranscriptionSubscription.State}"); + //await Task.Delay(5000); + + ////Stop Transcription + //StopTranscriptionOptions stopOptions = new StopTranscriptionOptions() + //{ + // OperationContext = "stopTranscription" + //}; + + //await callMedia.StopTranscriptionAsync(stopOptions); + //logger.LogInformation("Stop Transcription....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Transcription Subscription state ----> {connectionProperties.Value.TranscriptionSubscription.State}"); + + ////Start Transcription + //await callMedia.StartTranscriptionAsync(options); + //logger.LogInformation("Start Transcription....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Transcription Subscription state ----> {connectionProperties.Value.TranscriptionSubscription.State}"); + //await Task.Delay(5000); + #endregion + logger.LogInformation("Fetching recognize options..."); - // prepare recognize tones + // prepare recognize tones Choice var recognizeOptions = GetMediaRecognizeChoiceOptions(MainMenu, targetPhonenumber); + //// prepare recognize tones DTMF + //var recognizeOptions = GetMediaRecognizeDTMFOptions(dtmfPrompt, targetPhonenumber); + + //// prepare recognize tones Speech + //var recognizeOptions = GetMediaRecognizeSpeechOptions(dtmfPrompt, targetPhonenumber); + + //// prepare recognize tones Speech or dtmf + //var recognizeOptions = GetMediaRecognizeSpeechOrDtmfOptions(dtmfPrompt, targetPhonenumber); + logger.LogInformation("Recognizing options..."); // Send request to recognize tones @@ -95,7 +208,96 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct // 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; + //var textToPlay = labelDetected.Equals(ConfirmChoiceLabel, StringComparison.OrdinalIgnoreCase) ? ConfirmedText : CancelText; + var textToPlay = "Recognized DTMF tone"; + + #region Hold and Unhold + ////Hold + //var holdOptions = new HoldOptions(target) { + // OperationCallbackUri = new Uri(callbackUriHost), + // OperationContext = "holdPstnParticipant" + //}; + //////hold participant with options + ////var holdParticipant = await callMedia.HoldAsync(holdOptions); + + ////hold participant without options + //var holdParticipant = await callMedia.HoldAsync(target); + + //var isParticipantHold = (await callConnection.GetParticipantAsync(target)).Value.IsOnHold; + //logger.LogInformation($"Is participant on hold ----> {isParticipantHold}"); + ////Un-Hold + //var unHoldOptions = new UnholdOptions(target) + //{ + // OperationContext = "UnHoldPstnParticipant" + //}; + //////Un-Hold participant with options + ////var UnHoldParticipant = await callMedia.UnholdAsync(unHoldOptions); + + ////Un-Hold participant without options + //var UnHoldParticipant = await callMedia.UnholdAsync(target); + //var isParticipantUnHold = (await callConnection.GetParticipantAsync(target)).Value.IsOnHold; + //logger.LogInformation($"Is participant on hold ----> {isParticipantUnHold}"); + #endregion + + #region Media Streaming + //StopMediaStreamingOptions options = new StopMediaStreamingOptions() + //{ + // OperationCallbackUri = new Uri(callbackUriHost) + //}; + + //await callMedia.StopMediaStreamingAsync(options); + //logger.LogInformation("Stop Media Streaming....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + //await Task.Delay(5000); + + ////Start media streaming + //StartMediaStreamingOptions startOptions = new StartMediaStreamingOptions() + //{ + // OperationCallbackUri = new Uri(callbackUriHost), + // OperationContext = "startMediaStreamingContext" + //}; + //await callMedia.StartMediaStreamingAsync(startOptions); + //logger.LogInformation("Start Media Streaming....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + //await Task.Delay(5000); + + //await callMedia.StopMediaStreamingAsync(options); + //logger.LogInformation("Stop Media Streaming....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + #endregion + + #region Transcription + //StopTranscriptionOptions stopOptions = new StopTranscriptionOptions() + //{ + // OperationContext = "stopTranscription" + //}; + + //await callMedia.StopTranscriptionAsync(stopOptions); + //logger.LogInformation("Stop Transcription....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Transcription Subscription state ----> {connectionProperties.Value.TranscriptionSubscription.State}"); + + ////Start Transcription + //StartTranscriptionOptions options = new StartTranscriptionOptions() + //{ + // OperationContext = "startMediaStreamingContext", + // //Locale = "en-US", + //}; + //await callMedia.StartTranscriptionAsync(options); + //logger.LogInformation("Start Transcription....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Transcription Subscription state ----> {connectionProperties.Value.TranscriptionSubscription.State}"); + //await Task.Delay(5000); + + ////Stop Transcription + //await callMedia.StopTranscriptionAsync(stopOptions); + //logger.LogInformation("Stop Transcription....."); + //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + //logger.LogInformation($"Transcription Subscription state ----> {connectionProperties.Value.TranscriptionSubscription.State}"); + #endregion await HandlePlayAsync(callMedia, textToPlay); } @@ -124,11 +326,47 @@ var _ when reasonCode.Equals(MediaEventReasonCode.RecognizeIncorrectToneDetected var recognizeOptions = GetMediaRecognizeChoiceOptions(replyText, targetPhonenumber, RetryContext); await callMedia.StartRecognizingAsync(recognizeOptions); } + else if ((parsedEvent is MediaStreamingStarted)) + { + logger.LogInformation($"MediaStreamingStarted event triggered."); + } + else if ((parsedEvent is MediaStreamingStopped)) + { + logger.LogInformation($"MediaStreamingStopped event triggered."); + } + else if ((parsedEvent is MediaStreamingFailed)) + { + logger.LogInformation($"MediaStreamingFailed event triggered."); + } + else if ((parsedEvent is TranscriptionStarted)) + { + logger.LogInformation($"TranscriptionStarted event triggered."); + } + else if ((parsedEvent is TranscriptionStopped)) + { + logger.LogInformation($"TranscriptionStopped event triggered."); + } + else if ((parsedEvent is TranscriptionFailed)) + { + logger.LogInformation($"TranscriptionFailed event triggered."); + } else if ((parsedEvent is PlayCompleted) || (parsedEvent is PlayFailed)) { logger.LogInformation($"Terminating call."); await callConnection.HangUpAsync(true); } + else if (parsedEvent is PlayStarted) + { + logger.LogInformation($"PlayStarted event triggered."); + } + else if (parsedEvent is CallTransferAccepted) + { + logger.LogInformation($"CallTransferAccepted event triggered."); + } + else if (parsedEvent is CallTransferFailed) + { + logger.LogInformation($"CallTransferFailed event triggered."); + } } return Results.Ok(); }).Produces(StatusCodes.Status200OK); @@ -142,20 +380,128 @@ var _ when reasonCode.Equals(MediaEventReasonCode.RecognizeIncorrectToneDetected CallMediaRecognizeChoiceOptions GetMediaRecognizeChoiceOptions(string content, string targetParticipant, string context = "") { var playSource = new TextSource(content) { VoiceName = SpeechToTextVoice }; + #region Recognize prompt list + ////Multiple TextSource prompt + //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new TextSource("recognize prompt two") { VoiceName = SpeechToTextVoice }, new TextSource(content) { VoiceName = SpeechToTextVoice } }; + + ////Multiple FileSource Prompts + //var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")) }; + + ////Multiple TextSource prompt + //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; + + ////Empty play sources + var playSources = new List() { }; + #endregion var recognizeOptions = new CallMediaRecognizeChoiceOptions(targetParticipant: new PhoneNumberIdentifier(targetParticipant), GetChoices()) { InterruptCallMediaOperation = false, InterruptPrompt = false, InitialSilenceTimeout = TimeSpan.FromSeconds(10), - Prompt = playSource, + //Prompt = playSource, + PlayPrompts = playSources, OperationContext = context }; return recognizeOptions; } +CallMediaRecognizeDtmfOptions GetMediaRecognizeDTMFOptions(string content, string targetParticipant, string context = "") +{ + var playSource = new TextSource(content) { VoiceName = SpeechToTextVoice }; + #region Recognize prompt list + ////Multiple TextSource prompt + //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new TextSource("recognize prompt two") { VoiceName = SpeechToTextVoice }, new TextSource(content) { VoiceName = SpeechToTextVoice } }; + + ////Multiple FileSource Prompts + //var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")) }; + + ////Multiple TextSource and file source prompt + var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; + + ////Empty play sources + //var playSources = new List() { }; + + #endregion + + var recognizeOptions = + new CallMediaRecognizeDtmfOptions( + targetParticipant: new PhoneNumberIdentifier(targetParticipant), maxTonesToCollect: 8) + { + InterruptPrompt = false, + InterToneTimeout = TimeSpan.FromSeconds(5), + OperationContext = context, + InitialSilenceTimeout = TimeSpan.FromSeconds(15), + PlayPrompts = playSources, + }; + return recognizeOptions; +} + + +CallMediaRecognizeSpeechOptions GetMediaRecognizeSpeechOptions(string content, string targetParticipant, string context = "") +{ + var playSource = new TextSource(content) { VoiceName = SpeechToTextVoice }; + #region Recognize prompt list + ////Multiple TextSource prompt + //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new TextSource("recognize prompt two") { VoiceName = SpeechToTextVoice }, new TextSource(content) { VoiceName = SpeechToTextVoice } }; + + ////Multiple FileSource Prompts + //var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")) }; + + ////Multiple TextSource and file source prompt + var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; + + ////Empty play sources + //var playSources = new List() { }; + + #endregion + + var recognizeOptions = + new CallMediaRecognizeSpeechOptions( + targetParticipant: new PhoneNumberIdentifier(targetParticipant)) + { + InterruptPrompt = false, + OperationContext = context, + InitialSilenceTimeout = TimeSpan.FromSeconds(15), + PlayPrompts = playSources, + EndSilenceTimeout = TimeSpan.FromSeconds(15) + }; + return recognizeOptions; +} + +CallMediaRecognizeSpeechOrDtmfOptions GetMediaRecognizeSpeechOrDtmfOptions(string content, string targetParticipant, string context = "") +{ + var playSource = new TextSource(content) { VoiceName = SpeechToTextVoice }; + #region Recognize prompt list + ////Multiple TextSource prompt + //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new TextSource("recognize prompt two") { VoiceName = SpeechToTextVoice }, new TextSource(content) { VoiceName = SpeechToTextVoice } }; + + ////Multiple FileSource Prompts + //var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")) }; + + ////Multiple TextSource and file source prompt + var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; + + ////Empty play sources + //var playSources = new List() { }; + + #endregion + + var recognizeOptions = + new CallMediaRecognizeSpeechOrDtmfOptions( + targetParticipant: new PhoneNumberIdentifier(targetParticipant), maxTonesToCollect: 8) + { + InterruptPrompt = false, + OperationContext = context, + InitialSilenceTimeout = TimeSpan.FromSeconds(15), + PlayPrompts = playSources, + EndSilenceTimeout = TimeSpan.FromSeconds(5) + }; + return recognizeOptions; +} + List GetChoices() { return new List { @@ -179,14 +525,58 @@ List GetChoices() async Task HandlePlayAsync(CallMedia callConnectionMedia, string text) { Console.WriteLine($"Playing text to customer: {text}."); - + PhoneNumberIdentifier target = new PhoneNumberIdentifier(targetPhonenumber); + var playTo = new List { target }; // Play goodbye message var GoodbyePlaySource = new TextSource(text) { VoiceName = "en-US-NancyNeural" }; - await callConnectionMedia.PlayToAllAsync(GoodbyePlaySource); + PlayToAllOptions playOptions = new PlayToAllOptions(GoodbyePlaySource) + { + InterruptCallMediaOperation = false, + OperationCallbackUri = new Uri(callbackUriHost), + Loop = false + }; + + await callConnectionMedia.PlayToAllAsync(playOptions); + + //PlayOptions playOptions = new PlayOptions(GoodbyePlaySource, playTo) + //{ + // OperationCallbackUri = new Uri(callbackUriHost), + // Loop = false + //}; + //await callConnectionMedia.PlayAsync(playOptions); + //var interrupt = new TextSource("Interrupt prompt message") + //{ + // VoiceName = "en-US-NancyNeural" + //}; + + //PlayToAllOptions playInterrupt = new PlayToAllOptions(interrupt) + //{ + // InterruptCallMediaOperation = false, + // OperationCallbackUri = new Uri(callbackUriHost), + // Loop = false + //}; + //await callConnectionMedia.PlayToAllAsync(playInterrupt); + + ////file source + //var interruptFile = new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")); + //PlayToAllOptions playInterrupt = new PlayToAllOptions(interruptFile) + //{ + // InterruptCallMediaOperation = true, + // OperationCallbackUri = new Uri(callbackUriHost), + // Loop = false + //}; + //await callConnectionMedia.PlayToAllAsync(playInterrupt); + + //PlayOptions playOptions = new PlayOptions(interruptFile, playTo) + //{ + // OperationCallbackUri = new Uri(callbackUriHost), + // Loop = false + //}; + //await callConnectionMedia.PlayAsync(playOptions); } app.Run(); From 2769780205debb96dcf326d8442bd3f13e8b3133 Mon Sep 17 00:00:00 2001 From: Pilli Vamshi Date: Tue, 20 Aug 2024 11:02:14 +0530 Subject: [PATCH 2/2] added beta4 feature --- .../CallAutomation_OutboundCalling/Program.cs | 378 +++++++++++++----- 1 file changed, 271 insertions(+), 107 deletions(-) diff --git a/CallAutomation_OutboundCalling/CallAutomation_OutboundCalling/Program.cs b/CallAutomation_OutboundCalling/CallAutomation_OutboundCalling/Program.cs index c832975a..be5b90ef 100644 --- a/CallAutomation_OutboundCalling/CallAutomation_OutboundCalling/Program.cs +++ b/CallAutomation_OutboundCalling/CallAutomation_OutboundCalling/Program.cs @@ -3,7 +3,9 @@ using Azure.Messaging; using Azure.Messaging.EventGrid; using Azure.Messaging.EventGrid.SystemEvents; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +using System.Text.Json; var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); @@ -24,6 +26,7 @@ // Your cognitive service endpoint var cognitiveServiceEndpoint = ""; + // text to play const string SpeechToTextVoice = "en-US-NancyNeural"; const string MainMenu = "Please say confirm or say cancel to proceed further."; @@ -40,7 +43,9 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct const string dtmfPrompt = "Thank you for the update. Please type one two three four on your keypad to close call."; string cancelLabel = "Cancel"; -CallAutomationClient callAutomationClient = new CallAutomationClient(new Uri(""), acsConnectionString); +bool isPlayInterrupt = false; + +CallAutomationClient callAutomationClient = new CallAutomationClient(acsConnectionString); var app = builder.Build(); app.MapPost("/outboundCall", async (ILogger logger) => @@ -49,9 +54,9 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct PhoneNumberIdentifier caller = new PhoneNumberIdentifier(acsPhonenumber); var callbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"); CallInvite callInvite = new CallInvite(target, caller); - + MediaStreamingOptions mediaStreamingOptions = new MediaStreamingOptions( - new Uri("wss://t9x01h42-5000.inc1.devtunnels.ms/ws"), + new Uri("wss://0rv989s0-8081.inc1.devtunnels.ms/ws"), MediaStreamingContent.Audio, MediaStreamingAudioChannel.Mixed, MediaStreamingTransport.Websocket, @@ -59,8 +64,8 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct var createCallOptions = new CreateCallOptions(callInvite, callbackUri) { CallIntelligenceOptions = new CallIntelligenceOptions() { CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) }, - //MediaStreamingOptions = mediaStreamingOptions, - //TranscriptionOptions = new TranscriptionOptions(new Uri("wss://jg1tlgbv-5000.inc1.devtunnels.ms/ws"), "en-US", false, TranscriptionTransport.Websocket) + MediaStreamingOptions = mediaStreamingOptions, + TranscriptionOptions = new TranscriptionOptions(new Uri("wss://0rv989s0-8081.inc1.devtunnels.ms/ws"), "en-US", false, TranscriptionTransport.Websocket) }; CreateCallResult createCallResult = await callAutomationClient.CreateCallAsync(createCallOptions); @@ -82,6 +87,29 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct logger.LogInformation($"Created call with connection id: {createCallResult.CallConnectionProperties.CallConnectionId}"); }); +app.MapPost("/createGroupCall", async (ILogger logger) => +{ + var callbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"); + var pstnEndpoint = new PhoneNumberIdentifier("+18772119545"); + var voipEndpoint = new CommunicationUserIdentifier("8:acs:19ae37ff-1a44-4e19-aade-198eedddbdf2_00000021-e5a7-40d5-0d8b-08482200d459"); + + MediaStreamingOptions mediaStreamingOptions = new MediaStreamingOptions( + new Uri("wss://0rv989s0-8081.inc1.devtunnels.ms/ws"), + MediaStreamingContent.Audio, + MediaStreamingAudioChannel.Mixed, + MediaStreamingTransport.Websocket, + false); + + var groupCallOptions = new CreateGroupCallOptions(new List { pstnEndpoint, voipEndpoint }, callbackUri) + { + MediaStreamingOptions = mediaStreamingOptions, + CallIntelligenceOptions = new CallIntelligenceOptions() { CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) }, + SourceCallerIdNumber = new PhoneNumberIdentifier(acsPhonenumber), // This is the Azure Communication Services provisioned phone number for the caller + }; + CreateCallResult response = await callAutomationClient.CreateGroupCallAsync(groupCallOptions); + logger.LogInformation($"Group call is created : {JsonSerializer.Serialize(response)}"); +}); + app.MapPost("/api/callbacks", async (CloudEvent[] cloudEvents, ILogger logger) => { foreach (var cloudEvent in cloudEvents) @@ -99,7 +127,7 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct logger.LogInformation($"CALL CONNECTION ID ----> {parsedEvent.CallConnectionId}"); logger.LogInformation($"CORRELATION ID ----> {parsedEvent.CorrelationId}"); var connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); - logger.LogInformation($"ANSWERED FOR ----> {connectionProperties.Value.AnsweredFor}"); + //logger.LogInformation($"ANSWERED FOR ----> {connectionProperties.Value.AnsweredFor}"); @@ -120,43 +148,48 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct #endregion #region Media streaming - //StartMediaStreamingOptions options = new StartMediaStreamingOptions() - //{ - // OperationCallbackUri = new Uri(callbackUriHost), - // OperationContext = "startMediaStreamingContext" - //}; - //await callMedia.StartMediaStreamingAsync(options); - //logger.LogInformation("Start Media Streaming....."); - //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); - //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); - //await Task.Delay(5000); - - ////Stop Media Streaming - //StopMediaStreamingOptions stopOptions = new StopMediaStreamingOptions() - //{ - // OperationCallbackUri = new Uri(callbackUriHost) - //}; - - //await callMedia.StopMediaStreamingAsync(stopOptions); - //logger.LogInformation("Stop Media Streaming....."); - //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); - //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); - //await Task.Delay(5000); + StartMediaStreamingOptions options = new StartMediaStreamingOptions() + { + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), + OperationContext = "startMediaStreamingContext" + }; + await callMedia.StartMediaStreamingAsync(options); + logger.LogInformation("Start Media Streaming....."); + connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + await Task.Delay(5000); + //var voipUser = new CommunicationUserIdentifier("8:acs:19ae37ff-1a44-4e19-aade-198eedddbdf2_00000021-e5ee-8396-2c8a-08482200dcc8"); + + var addCallInvite = new CallInvite(new PhoneNumberIdentifier("+918712321814"), new PhoneNumberIdentifier(acsPhonenumber)); + var addpart = await callConnection.AddParticipantAsync(addCallInvite); + await Task.Delay(5000); + + //Stop Media Streaming + StopMediaStreamingOptions stopOptions = new StopMediaStreamingOptions() + { + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks") + }; - ////Start media streaming - //await callMedia.StartMediaStreamingAsync(options); - //logger.LogInformation("Start Media Streaming....."); - //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); - //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + await callMedia.StopMediaStreamingAsync(stopOptions); + logger.LogInformation("Stop Media Streaming....."); + connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + await Task.Delay(5000); + + //Start media streaming + await callMedia.StartMediaStreamingAsync(options); + logger.LogInformation("Start Media Streaming....."); + connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); #endregion #region Transcription - //StartTranscriptionOptions options = new StartTranscriptionOptions() + //StartTranscriptionOptions tOptions = new StartTranscriptionOptions() //{ // OperationContext = "startMediaStreamingContext", // //Locale = "en-US", //}; - //await callMedia.StartTranscriptionAsync(options); + //await callMedia.StartTranscriptionAsync(tOptions); //logger.LogInformation("Start Transcription....."); //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); //logger.LogInformation($"Transcription Subscription state ----> {connectionProperties.Value.TranscriptionSubscription.State}"); @@ -209,64 +242,88 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct // 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; - var textToPlay = "Recognized DTMF tone"; - + var textToPlay = "Recognized tone"; + //await HandlePlayAsync(callMedia, textToPlay); #region Hold and Unhold ////Hold - //var holdOptions = new HoldOptions(target) { - // OperationCallbackUri = new Uri(callbackUriHost), - // OperationContext = "holdPstnParticipant" + //var holdPlaySource = new TextSource("You are in hold... please wait") { VoiceName = SpeechToTextVoice }; + //var holdOptions = new HoldOptions(target) + //{ + // OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), + // OperationContext = "holdPstnParticipant", + // PlaySourceInfo = holdPlaySource, //}; - //////hold participant with options - ////var holdParticipant = await callMedia.HoldAsync(holdOptions); + ////hold participant with options and music + //var holdParticipant = await callMedia.HoldAsync(holdOptions); - ////hold participant without options - //var holdParticipant = await callMedia.HoldAsync(target); + //////hold participant without options and with music + ////var holdParticipant = await callMedia.HoldAsync(target, holdPlaySource); + //////hold participant without options and music + ////var holdParticipant = await callMedia.HoldAsync(target); + + ////without async + //////hold participant with options and music + ////var holdParticipant = callMedia.Hold(holdOptions); + + //////hold participant without options and with music + ////var holdParticipant = callMedia.Hold(target, holdPlaySource); + + //////hold participant without options and music + ////var holdParticipant = callMedia.Hold(target); //var isParticipantHold = (await callConnection.GetParticipantAsync(target)).Value.IsOnHold; //logger.LogInformation($"Is participant on hold ----> {isParticipantHold}"); + + //await Task.Delay(5000); ////Un-Hold //var unHoldOptions = new UnholdOptions(target) //{ // OperationContext = "UnHoldPstnParticipant" //}; + ////Un-Hold participant with options + //var UnHoldParticipant = await callMedia.UnholdAsync(unHoldOptions); + + //////Un-Hold participant without options + ////var UnHoldParticipant = await callMedia.UnholdAsync(target); + + ////without async //////Un-Hold participant with options - ////var UnHoldParticipant = await callMedia.UnholdAsync(unHoldOptions); + ////var UnHoldParticipant = callMedia.Unhold(unHoldOptions); - ////Un-Hold participant without options - //var UnHoldParticipant = await callMedia.UnholdAsync(target); + //////Un-Hold participant without options + ////var UnHoldParticipant = callMedia.Unhold(target); //var isParticipantUnHold = (await callConnection.GetParticipantAsync(target)).Value.IsOnHold; //logger.LogInformation($"Is participant on hold ----> {isParticipantUnHold}"); #endregion #region Media Streaming - //StopMediaStreamingOptions options = new StopMediaStreamingOptions() - //{ - // OperationCallbackUri = new Uri(callbackUriHost) - //}; - - //await callMedia.StopMediaStreamingAsync(options); - //logger.LogInformation("Stop Media Streaming....."); - //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); - //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); - //await Task.Delay(5000); + StopMediaStreamingOptions options = new StopMediaStreamingOptions() + { + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks") + }; - ////Start media streaming - //StartMediaStreamingOptions startOptions = new StartMediaStreamingOptions() - //{ - // OperationCallbackUri = new Uri(callbackUriHost), - // OperationContext = "startMediaStreamingContext" - //}; - //await callMedia.StartMediaStreamingAsync(startOptions); - //logger.LogInformation("Start Media Streaming....."); - //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); - //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); - //await Task.Delay(5000); + await callMedia.StopMediaStreamingAsync(options); + logger.LogInformation("Stop Media Streaming....."); + connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + await Task.Delay(5000); - //await callMedia.StopMediaStreamingAsync(options); - //logger.LogInformation("Stop Media Streaming....."); - //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); - //logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + //Start media streaming + StartMediaStreamingOptions startOptions = new StartMediaStreamingOptions() + { + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), + OperationContext = "startMediaStreamingContext" + }; + await callMedia.StartMediaStreamingAsync(startOptions); + logger.LogInformation("Start Media Streaming....."); + connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); + await Task.Delay(5000); + + await callMedia.StopMediaStreamingAsync(options); + logger.LogInformation("Stop Media Streaming....."); + connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); + logger.LogInformation($"Media Streaming Subscription state ----> {connectionProperties.Value.MediaStreamingSubscription.State}"); #endregion #region Transcription @@ -298,16 +355,21 @@ Your appointment tomorrow at 9am has been cancelled. Please call the bank direct //connectionProperties = await callConnection.GetCallConnectionPropertiesAsync(); //logger.LogInformation($"Transcription Subscription state ----> {connectionProperties.Value.TranscriptionSubscription.State}"); #endregion + //await Task.Delay(5000); + //await callConnection.HangUpAsync(true); await HandlePlayAsync(callMedia, textToPlay); } - else if (parsedEvent is RecognizeFailed { OperationContext: RetryContext }) + else if (parsedEvent is RecognizeFailed { OperationContext: RetryContext } recognizeFailedEvent1) { logger.LogError("Encountered error during recognize, operationContext={context}", RetryContext); + logger.LogError($"Recognize failed with index : {recognizeFailedEvent1.FailedPlaySourceIndex}"); await HandlePlayAsync(callMedia, NoResponse); } else if (parsedEvent is RecognizeFailed recognizeFailedEvent) { + logger.LogError($"Recognize failed with index : {recognizeFailedEvent.FailedPlaySourceIndex}"); + var resultInformation = recognizeFailedEvent.ResultInformation; logger.LogError("Encountered error during recognize, message={msg}, code={code}, subCode={subCode}", resultInformation?.Message, @@ -326,6 +388,14 @@ var _ when reasonCode.Equals(MediaEventReasonCode.RecognizeIncorrectToneDetected var recognizeOptions = GetMediaRecognizeChoiceOptions(replyText, targetPhonenumber, RetryContext); await callMedia.StartRecognizingAsync(recognizeOptions); } + else if ((parsedEvent is AddParticipantSucceeded)) + { + logger.LogInformation($"AddParticipantSucceeded event triggered."); + } + else if ((parsedEvent is AddParticipantFailed)) + { + logger.LogInformation($"AddParticipantFailed event triggered."); + } else if ((parsedEvent is MediaStreamingStarted)) { logger.LogInformation($"MediaStreamingStarted event triggered."); @@ -350,14 +420,34 @@ var _ when reasonCode.Equals(MediaEventReasonCode.RecognizeIncorrectToneDetected { logger.LogInformation($"TranscriptionFailed event triggered."); } - else if ((parsedEvent is PlayCompleted) || (parsedEvent is PlayFailed)) + else if (parsedEvent is PlayCompleted) { logger.LogInformation($"Terminating call."); await callConnection.HangUpAsync(true); } + else if (parsedEvent is PlayFailed playFailed) + { + logger.LogInformation($"playFailed with the index : {playFailed.FailedPlaySourceIndex}"); + //await callConnection.HangUpAsync(true); + } else if (parsedEvent is PlayStarted) { logger.LogInformation($"PlayStarted event triggered."); + + //if (isPlayInterrupt) + //{ + // var playTo = new List { target }; + // var interrupt = new TextSource("Interrupt prompt message") + // { + // VoiceName = "en-US-NancyNeural" + // }; + // PlayOptions interruptPlayOptions = new PlayOptions(interrupt, playTo) + // { + // OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), + // Loop = false, + // }; + // await callMedia.PlayAsync(interruptPlayOptions); + //} } else if (parsedEvent is CallTransferAccepted) { @@ -379,11 +469,15 @@ var _ when reasonCode.Equals(MediaEventReasonCode.RecognizeIncorrectToneDetected CallMediaRecognizeChoiceOptions GetMediaRecognizeChoiceOptions(string content, string targetParticipant, string context = "") { - var playSource = new TextSource(content) { VoiceName = SpeechToTextVoice }; + //var playSource = new TextSource(content) { VoiceName = SpeechToTextVoice }; + //var playSource = new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")); + var ssmlToPlay = "Say confirm"; + + var playSource = new SsmlSource(ssmlToPlay); #region Recognize prompt list ////Multiple TextSource prompt //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new TextSource("recognize prompt two") { VoiceName = SpeechToTextVoice }, new TextSource(content) { VoiceName = SpeechToTextVoice } }; - + ////Multiple FileSource Prompts //var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")) }; @@ -391,7 +485,23 @@ CallMediaRecognizeChoiceOptions GetMediaRecognizeChoiceOptions(string content, s //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; ////Empty play sources - var playSources = new List() { }; + //var playSources = new List() { }; + + //Invalid Prompt + var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://dummy/dummy.wav")) }; + + //Multiple + //var playSources = new List() { + // new TextSource("Play Media prompt 1") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 2") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 3") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 4") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 5") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 6") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 7") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 8") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 9") { VoiceName = SpeechToTextVoice }, + // new TextSource(content) { VoiceName = SpeechToTextVoice }}; #endregion var recognizeOptions = @@ -400,8 +510,8 @@ CallMediaRecognizeChoiceOptions GetMediaRecognizeChoiceOptions(string content, s InterruptCallMediaOperation = false, InterruptPrompt = false, InitialSilenceTimeout = TimeSpan.FromSeconds(10), - //Prompt = playSource, - PlayPrompts = playSources, + Prompt = playSource, + //PlayPrompts = playSources, OperationContext = context }; @@ -419,13 +529,16 @@ CallMediaRecognizeDtmfOptions GetMediaRecognizeDTMFOptions(string content, strin //var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")) }; ////Multiple TextSource and file source prompt - var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; + //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; ////Empty play sources //var playSources = new List() { }; + //Invalid Prompt + var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://dummy/dummy.wav")) }; + #endregion - + var recognizeOptions = new CallMediaRecognizeDtmfOptions( targetParticipant: new PhoneNumberIdentifier(targetParticipant), maxTonesToCollect: 8) @@ -451,11 +564,14 @@ CallMediaRecognizeSpeechOptions GetMediaRecognizeSpeechOptions(string content, s //var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")) }; ////Multiple TextSource and file source prompt - var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; + //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; ////Empty play sources //var playSources = new List() { }; + //Invalid Prompt + var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://dummy/dummy.wav")) }; + #endregion var recognizeOptions = @@ -482,11 +598,14 @@ CallMediaRecognizeSpeechOrDtmfOptions GetMediaRecognizeSpeechOrDtmfOptions(strin //var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")) }; ////Multiple TextSource and file source prompt - var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; + //var playSources = new List() { new TextSource("recognize prompt one") { VoiceName = SpeechToTextVoice }, new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new TextSource(content) { VoiceName = SpeechToTextVoice } }; ////Empty play sources //var playSources = new List() { }; + //Invalid Prompt + var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://dummy/dummy.wav")) }; + #endregion var recognizeOptions = @@ -524,6 +643,7 @@ List GetChoices() async Task HandlePlayAsync(CallMedia callConnectionMedia, string text) { + isPlayInterrupt = true; Console.WriteLine($"Playing text to customer: {text}."); PhoneNumberIdentifier target = new PhoneNumberIdentifier(targetPhonenumber); var playTo = new List { target }; @@ -532,33 +652,77 @@ async Task HandlePlayAsync(CallMedia callConnectionMedia, string text) { VoiceName = "en-US-NancyNeural" }; + //var playSource = new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")); + var ssmlToPlay = "SSML prompt from play media."; - PlayToAllOptions playOptions = new PlayToAllOptions(GoodbyePlaySource) + var playSource = new SsmlSource(ssmlToPlay); + PlayToAllOptions playOptions = new PlayToAllOptions(playSource) { InterruptCallMediaOperation = false, - OperationCallbackUri = new Uri(callbackUriHost), + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), Loop = false }; await callConnectionMedia.PlayToAllAsync(playOptions); - //PlayOptions playOptions = new PlayOptions(GoodbyePlaySource, playTo) - //{ - // OperationCallbackUri = new Uri(callbackUriHost), - // Loop = false - //}; - //await callConnectionMedia.PlayAsync(playOptions); - //var interrupt = new TextSource("Interrupt prompt message") - //{ - // VoiceName = "en-US-NancyNeural" - //}; + var playSource2 = new TextSource("Play media promt 2") + { + VoiceName = "en-US-NancyNeural" + }; - //PlayToAllOptions playInterrupt = new PlayToAllOptions(interrupt) - //{ - // InterruptCallMediaOperation = false, - // OperationCallbackUri = new Uri(callbackUriHost), - // Loop = false - //}; + PlayToAllOptions playOptions2 = new PlayToAllOptions(playSource2) + { + InterruptCallMediaOperation = false, + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), + Loop = false + }; + + //await callConnectionMedia.PlayToAllAsync(playOptions); + + ////Multiple + //var playSources = new List() { + // new TextSource("Play Media prompt 1") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 2") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 3") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 4") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 5") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 6") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 7") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 8") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 9") { VoiceName = SpeechToTextVoice }, + // new TextSource("Play Media prompt 10") { VoiceName = SpeechToTextVoice }}; + + //Invalid Prompt + var playSources = new List() { new FileSource(new Uri("https://www2.cs.uic.edu/~i101/SoundFiles/StarWars3.wav")), new FileSource(new Uri("https://dummy/dummy.wav")) }; + + PlayToAllOptions multyPlayOptions = new PlayToAllOptions(playSources) + { + InterruptCallMediaOperation = false, + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), + Loop = false + }; + + //await callConnectionMedia.PlayToAllAsync(multyPlayOptions); + + + + PlayOptions targetPlayOptions = new PlayOptions(GoodbyePlaySource, playTo) + { + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), + Loop = true + }; + //await callConnectionMedia.PlayAsync(targetPlayOptions); + var interrupt = new TextSource("Interrupt prompt message") + { + VoiceName = "en-US-NancyNeural" + }; + + PlayToAllOptions playInterrupt = new PlayToAllOptions(interrupt) + { + InterruptCallMediaOperation = true, + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), + Loop = false + }; //await callConnectionMedia.PlayToAllAsync(playInterrupt); ////file source @@ -571,12 +735,12 @@ async Task HandlePlayAsync(CallMedia callConnectionMedia, string text) //}; //await callConnectionMedia.PlayToAllAsync(playInterrupt); - //PlayOptions playOptions = new PlayOptions(interruptFile, playTo) - //{ - // OperationCallbackUri = new Uri(callbackUriHost), - // Loop = false - //}; - //await callConnectionMedia.PlayAsync(playOptions); + PlayOptions interruptPlayOptions = new PlayOptions(interrupt, playTo) + { + OperationCallbackUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"), + Loop = false, + }; + //await callConnectionMedia.PlayAsync(interruptPlayOptions); } app.Run();