Cookie CSS

Saturday, February 28, 2015

Lync (Skype for Business) Making a Robocall

If you live where we do, you've gotten one.  Either a 6 am, informational call to let you know there is no school because of a blizzard, or the summer version, the 3 am, take shelter tornado warning robocall.  Robocalls are just a fact of life these days.  It's not 1920, there is no need for Alice to get out the paper directory and call 2000 parents one by one.  If she tried, it's likely the blizzard would be over before she finished.  The robocall is however almost becoming an endangered species, giving way to the robo-email, and robo-sms.  In an emergency though, nothing scares you at 3 am like your phone ringing.



Lync (Skype for Business) has a backend SDK called UCMA that makes a robocall a simple task.  The following example is going to give you the basic idea.  Really it's a 2 part problem to solve.

1.  I need to call someone and wait until they answer.
2.  Once they answer I need to play a pre-recorded sound file, or use Text to Speech to say something and hang-up.

Step 1.  The Call.

For this example I'm again going to assume you know how to establish and application endpoint in UCMA.  If you don't go here

So step one is we need to make a conversation object so we can call our party.

Conversation myc = new Conversation(_appEndpoint);

Then we add an AudioVidoCall object so the conversation, so we can talk.

AudioVideoCall _mycall = new AudioVideoCall(myc);

Then we dial, and wait for the call to be answered.

_mycall.BeginEstablish(_touser.Uri, new CallEstablishOptions(), myest => 
                {
                    _mycall.EndEstablish(myest);
                }, null);

                while (_mycall.State != CallState.Established)
                {
                    Thread.Sleep(100);
                }

Now we have a choice TTS or Sound File?

1.  TTS Route.

private void TTSSpeak(AudioVideoCall _call, string _whattosay)
{
SpeechSynthesisConnector speechSynthesisConnector = new SpeechSynthesisConnector();

            try
            {
                int x = 0;
                while (_call.Flow == null | _call.Flow.State != MediaFlowState.Active)
                {
                    Thread.Sleep(10);
                    x++;
                    if (x > 500)
                        break;
                }
                speechSynthesisConnector.AttachFlow(_call.Flow);

                _speechSynthesizer = new SpeechSynthesizer();
                SpeechAudioFormatInfo audioformat = new SpeechAudioFormatInfo(16000, AudioBitsPerSample.Sixteen, Microsoft.Speech.AudioFormat.AudioChannel.Mono);
                _speechSynthesizer.SetOutputToAudioStream(speechSynthesisConnector, audioformat);

                speechSynthesisConnector.Start();

                PromptBuilder prompt = new PromptBuilder();
                prompt.AppendText(_whattosay);
                _speechSynthesizer.Speak(prompt);
                prompt.ClearContent();

                speechSynthesisConnector.Stop();

                speechSynthesisConnector.DetachFlow();
            }
            catch (Exception ex)
            {
                _logger.Log(ex.Message);
            }
            finally
            {
                try
                {
                    speechSynthesisConnector.DetachFlow();
                }
                catch { }
            }
}

2.  Sound File Route

private void StartWAV(string wav)
        {
            SpeechSynthesisConnector speechSynthesisConnector = new SpeechSynthesisConnector();
            
            try
            {
                int x = 0;
                while (_call.Flow == null | _call.Flow.State != MediaFlowState.Active)
                {
                    Thread.Sleep(10);
                    x++;
                    if (x > 500)
                        break;
                }
                speechSynthesisConnector.AttachFlow(_call.Flow);

                _speechSynthesizer = new SpeechSynthesizer();
                SpeechAudioFormatInfo audioformat = new SpeechAudioFormatInfo(16000, AudioBitsPerSample.Sixteen, Microsoft.Speech.AudioFormat.AudioChannel.Mono);
                _speechSynthesizer.SetOutputToAudioStream(speechSynthesisConnector, audioformat);

                speechSynthesisConnector.Start();

                PromptBuilder prompt = new PromptBuilder();
                prompt.AppendAudio(wav);
                _speechSynthesizer.Speak(prompt);
                prompt.ClearContent();

                speechSynthesisConnector.Stop();

                speechSynthesisConnector.DetachFlow();
            }
            catch (Exception ex)
            {
                _logger.Log(ex.Message);
            }
            finally
            {
                try
                {
                    speechSynthesisConnector.DetachFlow();
                }
                catch { }
            }
        }

That's it, you can extend this by running it in a loop and tracking whether or not you got the message to your parties.

Doug Routledge, C# Lync, Skype for Business, SQL, Exchange, UC Developer  BridgeOC