Skip to main content

Push to Talk

Push to Talk (PTT) is a communication method where audio is only transmitted while the user actively holds down a button. This is useful in scenarios where you want to give users explicit control over when they are broadcasting, such as in gaming, conferencing, or radio-style communication.

This guide explains how to configure an

AudioInput

for PTT functionality using the volumeGate setting.

Understanding VAD Defaults

Before implementing PTT, it's important to understand the default Voice Activity Detection (VAD) settings. The SDK provides VAD_DEFAULTS with two key components:

VAD_DEFAULTS
{
voiceActivity: {
attackThreshold: 0.9,
releaseThreshold: 0.8,
},
volumeGate: {
attackThreshold: -30,
releaseThreshold: -40,
},
}

voiceActivity (unit: %)

Controls voice activity detection based on the probability that the audio contains speech:

  • attackThreshold: 0.9 - The probability (90%) required to start transmission
  • releaseThreshold: 0.8 - The probability (80%) below which transmission stops

volumeGate (unit: dBFS)

Controls volume-based gating to filter out quiet sounds:

  • attackThreshold: -30 - The volume level (in dBFS) required to open the gate and start transmission
  • releaseThreshold: -40 - The volume level (in dBFS) below which the gate closes and transmission stops

Creating an AudioInput for PTT

The best way to implement Push to Talk is to configure the

InputSettings

on an

AudioInput

by setting the volumeGate to -90. This very low threshold effectively keeps the gate closed until you explicitly open it when the PTT button is pressed.

Creating an AudioInput with PTT settings
const audioInput = await DeviceManager.createAudioInput(
{},
{
// Set volumeGate to -90 dBFS to keep the gate closed by default
volumeGate: -90,
}
);

Adding AudioInput to a Room

Once you've created the

AudioInput

with PTT settings, you need to attach it to a

Room

to enable audio transmission. The AudioInput can be added before or after joining the room.

Adding AudioInput to a room
const room = new Room();

// AudioInput can be added before joining
room.addAudioInput(audioInput);

await room.join(token);

// Or added after joining - both work
// room.addAudioInput(audioInput);
info

Audio is only transmitted after an AudioInput has been attached to a room using room.addAudioInput(audioInput). With the PTT configuration, the volumeGate prevents transmission until the PTT button is pressed.

voiceActivity Variants

There are two approaches when implementing PTT, depending on whether you keep voiceActivity enabled or disabled.

Keeping voiceActivity enabled has the advantage that you won't transmit background noise even while the PTT button is held down. The downside is that the onAudioActivity indicator won't be active when pressing the PTT button if there's no detected speech.

This is the recommended approach for most use cases.

Option 2: Disable voiceActivity

If you want the audio activity indicator to always reflect the PTT button state (active when pressed, regardless of speech detection), you can disable voiceActivity:

Disabling voiceActivity for PTT
await audioInput.setInputSettings({
voiceActivity: false,
});

With this configuration, audio will transmit whenever the PTT button is pressed, regardless of whether speech is detected. This may result in transmitting background noise.

Implementing PTT Button Logic

To complete the PTT implementation, you need to handle the button press and release events. When the user presses the PTT button, set volumeGate to false to disable gating and allow transmission. When released, set it back to -90 to close the gate.

PTT button event handlers
const pttButton = document.getElementById("ptt-button");

// When the PTT button is pressed, open the gate
pttButton.addEventListener("pointerdown", async () => {
await audioInput.setInputSettings({
volumeGate: false,
});
});

// When the PTT button is released, close the gate
pttButton.addEventListener("pointerup", async () => {
await audioInput.setInputSettings({
volumeGate: -90,
});
});

// Also handle pointer leaving the button while pressed
pttButton.addEventListener("pointerleave", async () => {
await audioInput.setInputSettings({
volumeGate: -90,
});
});
warning

Make sure to handle the pointerleave event as well. This ensures the gate closes if the user moves their pointer away from the button while holding it down.

Complete Example

Here's a complete example bringing all the pieces together:

Complete PTT implementation
let audioInput;

async function setupPTT(room) {
// Create AudioInput with PTT settings
audioInput = await DeviceManager.createAudioInput(
{},
{
volumeGate: -90, // Gate closed by default
}
);

// Add to room
room.addAudioInput(audioInput);

// Setup PTT button handlers
const pttButton = document.getElementById("ptt-button");

pttButton.addEventListener("pointerdown", async () => {
await audioInput.setInputSettings({ volumeGate: false });
});

pttButton.addEventListener("pointerup", async () => {
await audioInput.setInputSettings({ volumeGate: -90 });
});

pttButton.addEventListener("pointerleave", async () => {
await audioInput.setInputSettings({ volumeGate: -90 });
});
}