Menu

Expand
Rate this page:

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 PreflightTests. 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:

  • dtls: This is measured from RTCDtlsTransport connecting to connected state.
  • ice: Measurements for establishing ICE connection.
  • peerConnection: Measurements for establishing a Peer Connection
  • signaling: Measurements for establishing Signaling connection.
    • This is measured from initiating a connection using device.connect() up to when RTCPeerConnection.signalingState transitions to stable state. See the documentation for RTCPeerConnection.signalingState for more information.
samples

WebRTC samples collected during the test. See the object format on the RTCSample Interface reference page.

selectedEdge

The edge passed to Device.runPreflight

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 true if either is of type "relay", false if both are of another type, or undefined if there are no selected ICE candidates.

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:

  • Excellent - If the average mos is over 4.2
  • Great - If the average mos is between 4.1 and 4.2 both inclusive
  • Good - If the average mos is between 3.7 and 4.0 both inclusive
  • Fair - If the average mos is between 3.1 and 3.6 both inclusive
  • Degraded - If the average mos is 3.0 or below

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.

  1. Click the plus button on that screen
  2. Enter a friendly name for the application like "PreflightTest".
  3. Under Voice request URL, enter your Record TwiML Bin's URL that you created in the previous section, and then click the Create button.
  4. 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>
Rate this page:

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 Community Forums or browsing the Twilio tag on Stack Overflow.

        
        
        

        Thank you for your feedback!

        We are always striving to improve our documentation quality, and your feedback is valuable to us. How could this documentation serve you better?

        Sending your feedback...
        🎉 Thank you for your feedback!
        Something went wrong. Please try again.

        Thanks for your feedback!

        Refer us and get $10 in 3 simple steps!

        Step 1

        Get link

        Get a free personal referral link here

        Step 2

        Give $10

        Your user signs up and upgrade using link

        Step 3

        Get $10

        1,250 free SMSes
        OR 1,000 free voice mins
        OR 12,000 chats
        OR more