Shane's World - Installment III

Leveraging the full power of the RELAY SDK

Jan 24, 2020

By Shane Bryldt, Senior Software Engineer

Hello world! My name is Shane Bryldt, and I am a Senior Software Engineer here at SignalWire. As a developer, I have made it my mission to explain everything that SignalWire can do, provide examples, and give the community my pro tips on how to leverage some of the more obscure options you can set. In my first installment, I talked about RELAY and covered the Calling.DialPhone API, Calling.NewPhoneCall, Call.Dial, and Call.Hangup. You can read all of that that right here!

In Installment II, we continued down the road into the RELAY SDK, and talked about some of the exciting API's we have to offer. We also covered the Call.Play API and its helpers, Call.PlayAudio, Call.PlayTTS, Call.PlaySilence, and Call.PlayRingtone.

And now it's time for Shane’s World – Installment III

The Feature Dive

Today we will look into a couple new API's of the RELAY SDK. We will cover the Call.Prompt API, and it’s helpers Call.PromptAudio and Call.PromptTTS. We will also cover Call.Tap.

I will start with a few links to the documentation, please review these for relevant information:

https://docs.signalwire.com/topics/relay-sdk-dotnet/v2/#api-reference-signalwire-relay-calling-call-methods-prompt

https://docs.signalwire.com/topics/relay-sdk-dotnet/v2/#api-reference-signalwire-relay-calling-call-methods-tap

Let’s start with the standard example code in C# just like before and we will build on the first example, then I will discuss what the code is doing.

Once again, not much has changed from the initial example in the first installment. This is a general skeleton template that shows the convenience of working with the Consumer layer. What we can take away from this example, is that there are helper methods like PromptTTS which encapsulate the more complicated Prompt method. Utilizing the helpers will make life easier, but may not always be the right answer.

Advanced Note: When using the Prompt method there is the ability to pass a list of different media to be played. These will be played in series, one after the other until all are completed, collection is available during all of the media and will end media early if something is collected.


There are currently 2 helper methods that can be used to send only 1 media more conveniently. These are PromptAudio and PromptTTS. The first allows you to play an audio file from an arbitrary Url, these can be in WAV or MP3 format just like PlayAudio. The second allows you to play TTS, which can have the synthetic voice altered with additional gender and language parameters, defaulted to female and en-US respectively again just like PlayTTS. In addition to the media to be played, you can also define exactly what you want to collect from the end user. This can include either digits or speech or both.

Whether collecting digits, speech, or both there is a parameter InitialTimeout which provides the timeout to wait for some input to occur before failing with no input, this timeout begins after the media is finished, and is defaulted to 4 seconds.

When collecting digits there are 3 parameters to fine tune your collection. The first is Max for the number of digits to collect. The second is Terminators for special input to use as DTMF terminators to end collection. The last is DigitTimeout which represents the timeout to use if multiple digits are being collected and at least 1 digit has been collected already, and is defaulted to 5 seconds.

When collecting speech there are 2 parameters to control the collection. The first is SpeechTimeout which provides the max duration of speech to collect after it has been heard, and is defaulted to 60 seconds. The second is EndSilenceTimeout which provides the duration of silence that must be heard after detecting something to terminate the collection, and is defaulted to 1 second.

As of SDK release 2.3, all of the Prompt operations also have an additional optional volume parameter which can be used to alter the volume for the duration of the media being played. This volume parameter ranges from -40dB to +40dB where 0dB represents no change to the volume.

Next we will cover the Tap API, which can be used to introduce an external listener to the media of an existing call. Let's look at another piece of example code.


The parameters for Tap are fairly simple, but extensible for the future. In the example above, we have initiated tapping both sides of the audio of a call and directed it to an RTP listener. There are no helper methods for Tap at this time, but stay tuned as that could change.

First we have a CallTap to define the type of the tapped media we want, currently only audio is supported. We used audio and for the audio parameters there is only a Direction that specifies what you want to capture (speak, listen, or both), with a default of speak that we changed to both to ensure we capture everything for this example.

Secondly we have a CallTapDevice to define where to send the tapped media. Currently, only rtp is supported. It takes the parameters Address and Port, which specify where to send the RTP traffic, and obviously both have no defaults.

Advanced Note: In the example we used the blocking API for Tap, this would cause the call to block until the tap has finished or errored out. A useful pattern is to sometimes use the TapAsync API instead. This pattern allows you to start tapping in the background and have it automatically end when a call is hung up.


Thank you for reading this article and I hope you find it helpful. The best way to learn about SignalWire is to tinker around with it, so sign up now to receive $5 in free credit and try it out yourself. You can also join us on our community Slack channel, where you can ask me any questions you have about SignalWire. Stay tuned as we dive down the rabbit hole together into more of SignalWire, on the next installment of Shane’s World!