Voice JavaScript SDK: Twilio.PreflightTest
A Twilio.PreflightTest
object represents a test call to Twilio which provides information to help troubleshoot call-related issues when using the Voice JavaScript SDK.
You will never instantiate a PreflightTest
instance directly, but it's returned when you call Device.runPreflight(token, options).
Example:
import { Device } from '@twilio/voice-sdk';
const preflightTest = Device.runPreflight(token, options);
preflightTest.on('completed', (report) => {
console.log(report);
});
preflightTest.on('failed', (error) => {
console.log(error);
});
Running PreflightTest
You will need an Access Token to initiate the test call. The Access Token will be associated with a TwiML application.
You likely already have a TwiML app with a Voice Request URL configured to send an HTTP POST request to an endpoint on your project's backend.
For the best test results, the endpoint with which you've configured your TwiML App should be able to record audio from a microphone and play it back to the browser.
Your backend application can be modified to handle this behavior, but you can also set up a new TwiML Application configured with TwiML bins specifically for PreflightTest
s. See the TwiML Apps for PreflightTest section below for more information.
Method Reference
preflightTest.stop()
Calling this method from the PreflightTest
object will stop the existing test and will raise a failed
event with an error code 31008
indicating that the call has been cancelled.
Event Reference
completedEvent
Raised when PreflightTest.status
has transitioned to PreflightTest.Status.Completed
. During this time, the report
is available and ready to be inspected. This will not trigger if a fatal error is encountered during the test.
Passes the report
object to the completed
event handler.
preflightTest.on('completed', handler(report));
See the Report section below to view an example of this report.
connectedEvent
Raised when PreflightTest.status
has transitioned to PreflightTest.Status.Connected
. This indicates that the connection to Twilio has been established.
failedEvent
Raised when PreflightTest.status
has transitioned to PreflightTest.Status.Failed
. This happens when establishing a connection to Twilio has failed or when a test call has encountered a fatal error. This is also raised if PreflightTest.stop
is called while the test is in progress. The error emitted from this event is coming from Device.on('error') and uses the same error format.
Passes a TwilioError
object or a DOMError
object to the failed
event handler.
preflightTest.on('failed', handler(error));
sampleEvent
Raised when the test Call gets a WebRTC sample object. The event is published every second.
Passes the RTCSample object to the sample
event handler.
preflightTest.on('sample', handler(sample));
warningEvent
Raised whenever the test Call encounters a warning.
Passes the name of the warning (string
) and the Warning object to the warning
event handler.
preflightTest.on('warning', handler(name, warning));
Accessor Reference
preflightTest.callSid
The Call SID for the test call. This is set when the test Device
instance has finished connecting to Twilio.
preflightTest.endTime
A timestamp in milliseconds of when the test ended. This is set when the test has completed and raised the completed event.
preflightTest.latestSample
The latest WebRTC sample collected. This is set whenever the Call emits a sample
.
Returns an RTCSample object or undefined
.
preflightTest.report
The report for this test. This is set when the test has completed and raised the completed
event.
See the Report section below for more information on the report object.
preflightTest.startTime
A timestamp in milliseconds of when the test started. This is set right after calling Device.runPreflight(token, options)
.
preflightTest.status
The status of the test. Below are the possible values for this property.
Value | Description |
---|---|
Completed | The connection to Twilio has been disconnected and the test call has completed. |
Connected | The connection to Twilio has been established. |
Connecting | Connecting to Twilio has started. |
Failed | The test has stopped and failed. |
Report
Below is an example report returned to the completed
event handler or accessed via preflightTest.report
.
{
"callSid": "CAa6a7a187a9cba2714d6fdccf472cc7b1",
"edge": "ashburn",
"iceCandidateStats": [...],
"networkTiming": {
"signaling": {
"start": 1628271850137,
"end": 1628271850958,
"duration": 821
},
"dtls": {
"start": 1628271851032,
"end": 1628271851192,
"duration": 160
},
"ice": {
"start": 1628271850956,
"end": 1628271851032,
"duration": 76
},
"peerConnection": {
"start": 1628271850965,
"end": 1628271851193,
"duration": 228
}
},
"samples": [
{
"audioInputLevel": 10999,
"audioOutputLevel": 1725,
"bytesReceived": 2880,
"bytesSent": 6080,
"codecName": "PCMU",
"jitter": 0,
"mos": null,
"packetsLost": 0,
"packetsLostFraction": 0,
"packetsReceived": 18,
"packetsSent": 38,
"rtt": 66,
"timestamp": 1628271851961.724,
"totals": {
"bytesReceived": 2880,
"bytesSent": 6080,
"packetsLost": 0,
"packetsLostFraction": 0,
"packetsReceived": 18,
"packetsSent": 38
}
}
],
"selectedEdge": "roaming",
"stats": {
"jitter": {
"average": 1.2273,
"max": 3,
"min": 0
},
"mos": {
"average": 4.4,
"max": 4.406226172226452,
"min": 4.390523592170177
},
"rtt": {
"average": 69.045,
"max": 84,
"min": 59
}
},
"testTiming": {
"start": 1628271849623,
"end": 1628271874932,
"duration": 25309
},
"totals": {
"bytesReceived": 109280,
"bytesSent": 182080,
"packetsLost": 0,
"packetsLostFraction": 0,
"packetsReceived": 683,
"packetsSent": 1138
},
"warnings": [
{
"name": "low-bytes-received",
"description": "Received an RTCWarning. See .rtcWarning for the RTCWarning",
"rtcWarning": {
"values": [
0,
0,
0
],
"samples": [
{
"audioInputLevel": 11718,
"audioOutputLevel": 0,
"bytesReceived": 0,
"bytesSent": 8000,
"codecName": "PCMU",
"jitter": 1,
"mos": 4.404255907879351,
"packetsLost": 0,
"packetsLostFraction": 0,
"packetsReceived": 0,
"packetsSent": 50,
"rtt": 61,
"timestamp": 1628271856961.176,
"totals": {
"bytesReceived": 29920,
"bytesSent": 46080,
"packetsLost": 0,
"packetsLostFraction": 0,
"packetsReceived": 187,
"packetsSent": 288
}
},
{
"audioInputLevel": 11261,
"audioOutputLevel": 0,
"bytesReceived": 0,
"bytesSent": 8000,
"codecName": "PCMU",
"jitter": 1,
"mos": 4.404255907879351,
"packetsLost": 0,
"packetsLostFraction": 0,
"packetsReceived": 0,
"packetsSent": 50,
"rtt": 61,
"timestamp": 1628271857960.764,
"totals": {
"bytesReceived": 29920,
"bytesSent": 54080,
"packetsLost": 0,
"packetsLostFraction": 0,
"packetsReceived": 187,
"packetsSent": 338
}
},
],
"name": "bytesReceived",
"threshold": {
"name": "min",
"value": 1
}
}
}
],
"selectedIceCandidatePairStats": {
"localCandidate": {
"id": "RTCIceCandidate_XXXXXXXX",
"timestamp": 1628271851961.724,
"type": "local-candidate",
"transportId": "RTCTransport_0_1",
"isRemote": false,
"networkType": "wifi",
"ip": "xx.xx.x.xx",
"address": "xx.xx.x.xx",
"port": 44444,
"protocol": "udp",
"candidateType": "prflx",
"priority": 1853759231
},
"remoteCandidate": {
"id": "RTCIceCandidate_XXXXXXXX",
"timestamp": 1628271851961.724,
"type": "remote-candidate",
"transportId": "RTCTransport_0_1",
"isRemote": true,
"ip": "xx.xxx.xxx.xxx",
"address": "xx.xxx.xxx.xxx",
"port": 11111,
"protocol": "udp",
"candidateType": "host",
"priority": 2130706431
}
},
"isTurnRequired": false,
"callQuality": "excellent"
}
Report Properties
Property | Description |
callSid |
The Call SID for the test call. |
edge |
The Edge location that the test call was connected to |
iceCandidateStats |
An array of WebRTC stats for the ICE candidates gathered when connecting to media. Each item is an RTCIceCandidateStats object which provides information related to an ICE candidate. |
networkTiming |
Measurements for establishing DTLS connection. Properties:
|
samples |
WebRTC samples collected during the test. See the object format on the RTCSample Interface reference page. |
selectedEdge |
The edge passed to |
stats |
RTC-related stats that are extracted from WebRTC samples. This information includes maximum, minimum, and average values calculated for each statistic. |
testTiming |
Timing measurement related to the test. Includes millisecond timestamps and duration. |
totals |
Calculated totals in RTC statistics samples. |
warnings |
PreflightTest.Warnings detected during the test |
selectedIceCandidatePairStats |
A WebRTC stats object for the ICE candidate pair used to connect to media, if candidates were selected. Each item is an RTCIceCandidatePairStats object which provides information related to an ICE candidate. |
isTurnRequired |
Whether a TURN server is required to connect to media. This is dependent on the selected ICE candidates, and will be See PreflightTest.Options.iceServers for more details. |
callQuality |
The quality of the call, determined by the MOS (Mean Opinion Score) of the audio stream. Possible values include:
|
TwiML Apps for PreflightTest
Please see our example application if you don't want to set up the required TwiML Apps manually.
Twilio.Device.runPreflight(token, options)
requires a Twilio Access Token to initiate the test call. This access token will be passed directly to the Device's constructor and will be used to connect to a TwiML app that you associated with your Twilio Access Token. In order to get better results, the TwiML app should be able to record audio from a microphone and play it back to the browser. Below are example TwiML Apps that you can use and some setup instructions.
Record and Play
If PreflightTest.Options.fakeMicInput
is set to false
, Device.runPreflight(token, options)
API requires a token with a TwiML app that can record an audio from a microphone and the ability to play the recorded audio back to the browser. In order to achieve this, we need two TwiML endpoints: one to capture and record the audio, and another one to play the recorded audio.
In this example, we will use TwiML Bins for our TwiML app. Start by going to the TwiML Bin page in the Twilio Console.
Playback TwiML Bin
Create a new TwiML Bin with the plus button on that screen and use "Playback" as the friendly name.
Then use the following TwiML under the TwiML section.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>You said:</Say>
<Play loop="1">{{RecordingUrl}}</Play>
<Say>Now waiting for a few seconds to gather audio performance metrics.</Say>
<Pause length="3"/>
<Say>Hanging up now.</Say>
</Response>
Record TwiML Bin
Using the TwiML Bin page, let's create another TwiML Bin by clicking the plus button on that screen and use "Record" as the friendly name.
Then replace the action url in the following template with your "Playback" TwiML Bin's URL that you created previously:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Record a message in 3, 2, 1</Say>
<Record maxLength="5" action="https://my-record-twimlBin-url"></Record>
<Say>Did not detect a message to record</Say>
</Response>
Creating the TwiML Application
Now that we have created our TwiML Bins, let's create our TwiML app by going to the TwiML Apps page.
- Click the plus button on that screen
- Enter a friendly name for the application like "PreflightTest".
- Under Voice request URL, enter your Record TwiML Bin's URL that you created in the previous section, and then click the Create button.
- On that same page, open the TwiML app that you just created by clicking on it and make note of the SID.
You can now use this TwiML app to generate your Access Token when calling Device.runPreflight(token, options)
.
Echo
If PreflightTest.Options.fakeMicInput
is set to true
, Device.runPreflight(token, options)
API requires an Access Token with a TwiML app that can capture and play audio.
Following the previous steps, create a TwiML Bin using the following TwiML and create a new TwiML Application pointed to that TwiML Bin's URL.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Echo/>
</Response>
Need some help?
We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Stack Overflow Collective or browsing the Twilio tag on Stack Overflow.