Skip to contentSkip to navigationSkip to topbar
On this page

Twilio.Device.audio


When using the The Voice JavaScript SDK, a Device instance has access to a device.audio property containing an AudioHelper(link takes you to an external page) object. This allows you to control the way a Device instance interacts with speaker and microphone resources.

The AudioHelper(link takes you to an external page) is an EventEmitter(link takes you to an external page), so it provides a variety of event-related methods and properties. That functionality will not be covered here. For more information on EventEmitter functionality, see the Node.js Events documentation(link takes you to an external page) or click on the method/property below.


Browser Support

browser-support page anchor
(warning)

Warning

Many device.audio features are browser-dependent.

Currently Chrome 49+ is the only browser that fully supports device.audio.

Audio output selection requires support for setSinkId(link takes you to an external page).

Audio input selection requires support for AudioContext(link takes you to an external page).

If these features are used in a browser that does not support them, the get method will return an empty Set, whereas the set and test methods will return a rejected Promise.


Below are explanations of the audio-related methods on the AudioHelper object provided by device.audio.

device.audio.addProcessor(processor)

deviceaudioaddprocessorprocessor page anchor

Adds an AudioProcessor object and returns a Promise representing the result. Once added, the AudioHelper will route the input audio stream through the processor before sending the audio stream to Twilio. Only one AudioProcessor can be added at this time.

See the AudioProcessor interface for an example.

device.audio.disconnect(doEnable)

deviceaudiodisconnectdoenable page anchor

Enable or disable the disconnect sound. Passing true will enable the sound and false will disable the sound. Not passing this parameter will not alter the enable-status of the sound.

Returns a Boolean value that represents the enable-status of the sound.

device.audio.incoming(doEnable)

deviceaudioincomingdoenable page anchor

Enable or disable the incoming sound. Passing true will enable the sound and false will disable the sound. Not passing this parameter will not alter the enable-status of the sound.

Returns a Boolean value that represents the enable-status of the sound.

device.audio.outgoing(doEnable)

deviceaudiooutgoingdoenable page anchor

Enable or disable the outgoing sound. Passing true will enable the sound and false will disable the sound. Not passing this parameter will not alter the enable-status of the sound.

Returns a Boolean value that represents the enable-status of the sound.

device.audio.removeProcessor(processor)

deviceaudioremoveprocessorprocessor page anchor

Removes an AudioProcessor and returns a Promise representing the result. Once removed, the AudioHelper will start using the audio stream from the selected input device for existing or future calls.

device.audio.setAudioConstraints(audioConstraints)

deviceaudiosetaudioconstraintsaudioconstraints page anchor

Set the MediaTrackConstraints(link takes you to an external page) to be applied on every getUserMedia(link takes you to an external page) call for new input device audio. Any deviceId specified here will be ignored. Instead, device IDs should be specified using device.audio.setInputDevice(). The returned Promise resolves when the media is successfully reacquired, or immediately if no input device is set.

Example:

1
const device = new Device(token);
2
3
device.audio.setAudioConstraints({ echoCancellation: true })
4
.then(()=> {
5
device.audio.setInputDevice('default');
6
});
7
8
// Now we have a live input audio track, opened with echoCancellation:true
9
device.audio.setAudioConstraints({
10
autoGainControl: false,
11
echoCancellation: false,
12
noiseSuppression: false,
13
}).then(() => {
14
// We successfully applied the new constraints and should automatically hear the difference.
15
// Future calls to setInputDevice will also use these constraints until they're cleared.
16
}, err => {
17
// Something went wrong, most likely err is an OverconstrainedError. Let's roll back.
18
await device.audio.unsetAudioConstraints();
19
// We should now have a working input audio track again
20
});

device.audio.setInputDevice(deviceId)

deviceaudiosetinputdevicedeviceid page anchor

Set the current input device by deviceId. Once this is set, the input device will be used in the current call, if any, and used by default for any subsequent calls. In addition, whenever an input device is set, the device.audio's inputVolume event will fire on every animation frame(link takes you to an external page).

Returns a Promise that resolves if the input device was set successfully.

Note: This is not supported in Firefox (as recent as 51) due to its lack of support for multiple input devices.

Example:

1
const device = new Device(token);
2
3
device.audio.setInputDevice('default').then(() => {
4
console.info('Success!');
5
});

device.audio.unsetAudioConstraints()

deviceaudiounsetaudioconstraints page anchor

Unset the MediaTrackConstraints(link takes you to an external page) to be applied on every getUserMedia(link takes you to an external page) call for new input device audio. The returned Promise resolves when the media is successfully reacquired, or immediately if no input device is set.

device.audio.unsetInputDevice(deviceId)

deviceaudiounsetinputdevicedeviceid page anchor

Unset the active input device. This will stop the device.audio's inputVolumeEvent polling and stop the input stream.

Example:

1
const device = new Device(token);
2
3
// ...
4
5
device.audio.unsetInputDevice().then(()=> {
6
console.info('Success!');
7
});

device.audio.availableInputDevices

deviceaudioavailableinputdevices page anchor

A Map(link takes you to an external page) containing the MediaDeviceInfo(link takes you to an external page) object of all available input devices (hardware devices capable of providing an input audio stream), indexed by deviceId.

(warning)

Warning

Due to browser-imposed security restrictions, MediaDeviceInfos available in availableInDevices may contain auto-generated labels (e.g. "Unknown Audio Input Device 1"), or an incomplete / empty list of devices, until the user grants the application access to these resources in response to a call to the browser's getUserMedia()(link takes you to an external page) API.

In an effort to reduce device fingerprinting, all major browsers are getting more strict in this regard. We strongly recommend your application calls getUserMedia()(link takes you to an external page) before rendering your input / output device selection UI for the cleanest user experience.

After the user accepts the getUserMedia() prompt, the AudioHelper's deviceChange event will be fired to indicate that the application UI should be updated.

device.audio.availableOutputDevices

deviceaudioavailableoutputdevices page anchor

A Map(link takes you to an external page) containing the MediaDeviceInfo(link takes you to an external page) object of all available output devices (hardware devices capable of outputting audio), indexed by deviceId.

(warning)

Warning

Due to browser-imposed security restrictions, MediaDeviceInfos available in availableOutputDevices may contain auto-generated labels (e.g. "Unknown Audio Output Device 1"), or an incomplete / empty list of devices, until the user grants the application access to these resources in response to a call to the browser's getUserMedia()(link takes you to an external page) API.

In an effort to reduce device fingerprinting, all major browsers are getting more strict in this regard. We strongly recommend your application calls getUserMedia()(link takes you to an external page) before rendering your input / output device selection UI for the cleanest user experience.

After the user accepts the getUserMedia() prompt, the AudioHelper's deviceChange event will be fired to indicate that the application UI should be updated.

(warning)

Warning

Firefox (as recent as 51) does not list any audiooutput devices, and Edge (as recent as 38) does not label its audiooutput devices even after user permission is granted.

Example:

1
const device = new Device(token);
2
3
device.audio.availableOutputDevices.forEach((device, id) => {
4
console.info('Available device:', id, '(labeled', device.label, ')');
5
});

device.audio.isOutputSelectionSupported

deviceaudioisoutputselectionsupported page anchor

Returns a Boolean. Returns false if the browser does not support HTMLAudioElement.setSinkId()(link takes you to an external page) or MediaDevices.enumerateDevices()(link takes you to an external page) and Twilio cannot facilitate output selection functionality.

device.audio.isVolumeSupported

deviceaudioisvolumesupported page anchor

Returns a Boolean. Returns false if the browser does not support AudioContext(link takes you to an external page) and Twilio can not analyze the volume in real-time.

device.audio.ringtoneDevices

deviceaudioringtonedevices page anchor

ringtoneDevices is an OutputDeviceCollection(link takes you to an external page) that controls which output devices are used to play the ringing sound when receiving an incoming call. Changing this set of devices will switch the devices used for the incoming call sound.

Note: This is not supported in Firefox (as recent as 51) or Edge (as recent as 38) due to their lack of support for HTMLAudioElement.setSinkId().

device.audio.ringtoneDevices.delete(device)

Delete a device from the collection. If no devices remain, the default device will be added as the sole device. If no default device exists, the first available device will be used.

The device parameter is a MediaDeviceInfo(link takes you to an external page) object.

This method returns a Boolean for whether the device was present before it was deleted.

device.audio.ringtoneDevices.get()

Returns the current set of devices (as MediaDeviceInfo(link takes you to an external page) objects).

1
const device = new Device(token);
2
3
device.audio.ringtoneDevices.get(); // Returns a Set<MediaDeviceInfo>
4

device.audio.ringtoneDevices.set(deviceIdOrIds).

Replace the current device/set of devices with a new device or set of devices.

The deviceIdOrIds parameter can be either a single deviceId (as a string) or an array of deviceIds (as an array of strings).

Returns an empty Promise. Rejects if this feature is not supported, or if any of the supplied deviceIds are not found, or if no deviceIds are passed.

1
const device = new Device(token);
2
3
device.audio.ringtoneDevices.set('default'); // Set active device
4
device.audio.ringtoneDevices.set(['default', 'ABC123']); // Set active devices

device.audio.ringtoneDevices.test(soundUrl?)

Test the devices by playing audio through them.

The optional soundUrl parameter is a URL string for a test sound. If no soundUrl is passed, the test will be run with the 'outgoing' sound.

Returns a Promise. It will resolve with the result of the underlying HTMLAudioElement's play() calls.

1
const device = new Device(token);
2
3
device.audio.ringtoneDevices.test(); // Test with 'outgoing' sound
4
device.audio.ringtoneDevices.test('cowbell.mp3'); // Test with custom sound

device.audio.speakerDevices

deviceaudiospeakerdevices page anchor

speakerDevices is an OutputDeviceCollection(link takes you to an external page) that controls which output devices are used to play standard speaker sounds: the ringtone you hear when initiating a call, the disconnect sound, DTMF tones the user might press and the audio received from the remote participant.

Changing this set of devices will switch the device(s) used for these sounds. If you change these during an active call, the remote participant's audio will immediately be played through the new set of outputs.

Note: This is not supported in Firefox (as recent as 51) or Edge (as recent as 38) due to their lack of support for HTMLAudioElement.setSinkId().

device.audio.speakerDevices.delete(device)

Delete a device from the collection. If no devices remain, the default device will be added as the sole device. If no default device exists, the first available device will be used.

The device parameter is a MediaDeviceInfo(link takes you to an external page) object.

This method returns a Boolean for whether the device was present before it was deleted.

device.audio.speakerDevices.get()

Returns the current set of devices (as MediaDeviceInfo(link takes you to an external page) objects).

1
const device = new Device(token);
2
3
device.audio.speakerDevices.get(); // Returns a Set<MediaDeviceInfo>
4

device.audio.speakerDevices.set(deviceIdOrIds).

Replace the current device/set of devices with a new device or set of devices.

The deviceIdOrIds parameter can be either a single deviceId (as a string) or an array of deviceIds (as an array of strings).

Returns an empty Promise. Rejects if this feature is not supported, or if any of the supplied deviceIds are not found, or if no deviceIds are passed.

1
const device = new Device(token);
2
3
device.audio.speakerDevices.set('default'); // Set active device
4
device.audio.speakerDevices.set(['default', 'ABC123']); // Set active devices

device.audio.speakerDevices.test(soundUrl?)

Test the devices by playing audio through them.

The optional soundUrl parameter is a URL string for a test sound. If no soundUrl is passed, the test will be run with the 'outgoing' sound.

Returns a Promise. It will resolve with the result of the underlying HTMLAudioElement's play() calls.

1
const device = new Device(token);
2
3
device.audio.speakerDevices.test(); // Test with 'outgoing' sound
4
device.audio.speakerDevices.test('cowbell.mp3'); // Test with custom sound

device.audio.audioConstraints

deviceaudioaudioconstraints page anchor

The current audio constraints (as a MediaTrackConstraints(link takes you to an external page) object) set by device.audio.setAudioConstraints(). Starts as null.

device.audio.inputDevice

deviceaudioinputdevice page anchor

Returns the active input device (as a MediaDeviceInfo(link takes you to an external page) object).

Having no inputDevice specified by device.audio.setInputDevice() will disable functionality related to input selection.

device.audio.inputStream

deviceaudioinputstream page anchor

Returns the current input stream (as a MediaStream(link takes you to an external page) object).


1
const device = new Device(token);
2
3
device.audio.on('deviceChange', handler(lostActiveDevices));
4

Register a handler that will be fired whenever a new audio device is found, an existing audio device is lost or the label of an existing device is changed. This typically happens when the user plugs in or unplugs an audio device, like a headset or a microphone.

This will also trigger after the customer has given access to user media via getUserMedia for the first time, as the labels will become populated. If you want to allow users to choose a specific audio device in your application's UI, attach a listener to this event.

(warning)

Warning

This does not detect a customer plugging in headphones or other speakers through the headphone jack, as the headphone jack only redirects audio from the internal audio device.

The parameter, lostActiveDevices, is an array of MediaDeviceInfo(link takes you to an external page) objects that represents all devices that were currently active in either .speakerDevices or .ringtoneDevices at the time they were lost, if any. A non-empty array is an indicator that the user's experience was likely affected by this event.

1
const device = new Device(token);
2
3
device.audio.on('inputVolume', handler(volume))
4

Register a handler that will be fired every animation frame(link takes you to an external page) with the current volume of the selected input device, if one is set. The handler will be invoked up to 60 times per second, and will scale down dynamically on slower devices to preserve performance. The handler receives volume as a percentage of maximum volume represented by a floating point number between 0.0 and 1.0, inclusive. This value represents a range of relative decibel values between -100dB and -30dB.

Note: This will not work in Firefox (as recent as 51) as there is no supported way to set the input device.


Both device.audio.speakerDevices and device.audio.ringtoneDevices are instances of an OutputDeviceCollection. An OutputDeviceCollection represents active audio devices, and can be updated to redirect speaker and ringtone sounds to different devices in real time.

An OutputDeviceCollection provides delete, get, set, and test methods. Descriptions and examples for each of these methods can be found in the device.audio.ringtoneDevices and device.audio.speakerDevices sections above.

Below is an example on how one might work with an OutputDeviceCollection using a multi-select HTML element:

1
const device = new Device(token);
2
3
var speakerDeviceSelect = document.getElementById('speaker-devices');
4
5
// When a device is found or lost, update a multi-select element with the
6
// new set of available devices.
7
device.audio.on('deviceChange', function updateAvailableDevices() {
8
speakerDeviceSelect.innerHtml = '';
9
10
device.audio.availableOutputDevices.forEach((device, id) => {
11
var deviceOption = document.createElement('option');
12
deviceOption.label = device.label;
13
deviceOption.setAttribute('data-id', id);
14
15
// If the device is present in device.audio.speakerDevices, then it is
16
// currently active, and should be selected in the multi-select element.
17
var speakerDevices = device.audio.speakerDevices.get();
18
speakerDevices.forEach((speakerDevice) => {
19
if (speakerDevice.deviceId === id) {
20
deviceOption.setAttribute('selected', 'selected');
21
}
22
});
23
24
speakerDeviceSelect.appendChild(deviceOption);
25
});
26
});
27
28
// When a device is selected or unselected, update device.audio.speakerDevices
29
// with the devices the user selected to immediately change where the audio
30
// is playing from.
31
speakerDeviceSelect.addEventListener('change',() => {
32
var selectedDeviceIds = [].slice.call(speakerDevices.childNodes)
33
.filter(function(node) { return node.selected; })
34
.map(function(node) { return node.getAttribute('data-id'); });
35
36
device.audio.speakerDevices.set(selectedDeviceIds);
37
});
38

Need some help?

Terms of service

Copyright © 2024 Twilio Inc.