| name | telnyx-webrtc-client-js |
| description | Build browser-based VoIP calling apps using Telnyx WebRTC JavaScript SDK. Covers authentication, voice calls, events, debugging, call quality metrics, and AI Agent integration. Use for web-based real-time communication. |
| metadata | {"author":"telnyx","product":"webrtc","language":"javascript","platform":"browser"} |
Telnyx WebRTC - JavaScript SDK
Build real-time voice communication into browser applications.
Prerequisites: Create WebRTC credentials and generate a login token using the Telnyx server-side SDK. See the telnyx-webrtc-* skill in your server language plugin (e.g., telnyx-python, telnyx-javascript).
Installation
npm install @telnyx/webrtc --save
Import the client:
import { TelnyxRTC } from '@telnyx/webrtc';
Authentication
Option 1: Token-Based (Recommended)
const client = new TelnyxRTC({
login_token: 'your_jwt_token',
});
client.connect();
Option 2: Credential-Based
const client = new TelnyxRTC({
login: 'sip_username',
password: 'sip_password',
});
client.connect();
Important: Never hardcode credentials in frontend code. Use environment variables or prompt users.
Disconnect
client.disconnect();
client.off('telnyx.ready');
client.off('telnyx.notification');
Media Elements
Specify an HTML element to play remote audio:
client.remoteElement = 'remoteMedia';
HTML:
<audio id="remoteMedia" autoplay="true" />
Events
let activeCall;
client
.on('telnyx.ready', () => {
console.log('Ready to make calls');
})
.on('telnyx.error', (error) => {
console.error('Error:', error);
})
.on('telnyx.notification', (notification) => {
if (notification.type === 'callUpdate') {
activeCall = notification.call;
if (activeCall.state === 'ringing') {
}
}
});
Event Types
| Event | Description |
|---|
telnyx.ready | Client connected and ready |
telnyx.error | Error occurred |
telnyx.notification | Call updates, incoming calls |
telnyx.stats.frame | In-call quality metrics (when debug enabled) |
Making Calls
const call = client.newCall({
destinationNumber: '+18004377950',
callerNumber: '+15551234567',
});
Receiving Calls
client.on('telnyx.notification', (notification) => {
const call = notification.call;
if (notification.type === 'callUpdate' && call.state === 'ringing') {
call.answer();
}
});
Call Controls
call.hangup();
call.dtmf('1234');
call.muteAudio();
call.unmuteAudio();
call.hold();
call.unhold();
Debugging & Call Quality
Enable Debug Logging
const call = client.newCall({
destinationNumber: '+18004377950',
debug: true,
debugOutput: 'socket',
});
In-Call Quality Metrics
const call = client.newCall({
destinationNumber: '+18004377950',
debug: true,
});
client.on('telnyx.stats.frame', (stats) => {
console.log('Quality stats:', stats);
});
Pre-Call Diagnosis
Test connectivity before making calls:
import { PreCallDiagnosis } from '@telnyx/webrtc';
PreCallDiagnosis.run({
credentials: {
login: 'sip_username',
password: 'sip_password',
},
texMLApplicationNumber: '+12407758982',
})
.then((report) => {
console.log('Diagnosis report:', report);
})
.catch((error) => {
console.error('Diagnosis failed:', error);
});
Preferred Codecs
Set codec preference for calls:
const allCodecs = RTCRtpReceiver.getCapabilities('audio').codecs;
const opusCodec = allCodecs.find(c =>
c.mimeType.toLowerCase().includes('opus')
);
const pcmaCodec = allCodecs.find(c =>
c.mimeType.toLowerCase().includes('pcma')
);
client.newCall({
destinationNumber: '+18004377950',
preferred_codecs: [opusCodec],
});
Registration State
Check if client is registered:
const isRegistered = await client.getIsRegistered();
console.log('Registered:', isRegistered);
AI Agent Integration
Anonymous Login
Connect to an AI assistant without SIP credentials:
const client = new TelnyxRTC({
anonymous_login: {
target_id: 'your-ai-assistant-id',
target_type: 'ai_assistant',
},
});
client.connect();
Note: The AI assistant must have telephony_settings.supports_unauthenticated_web_calls set to true.
Make Call to AI Assistant
const call = client.newCall({
destinationNumber: '',
remoteElement: 'remoteMedia',
});
Recommended Codec for AI
const allCodecs = RTCRtpReceiver.getCapabilities('audio').codecs;
const opusCodec = allCodecs.find(c =>
c.mimeType.toLowerCase().includes('opus')
);
client.newCall({
destinationNumber: '',
preferred_codecs: [opusCodec],
});
Browser Support
| Platform | Chrome | Firefox | Safari | Edge |
|---|
| Android | ✓ | ✓ | - | - |
| iOS | - | - | ✓ | - |
| Linux | ✓ | ✓ | - | - |
| macOS | ✓ | ✓ | ✓ | ✓ |
| Windows | ✓ | ✓ | - | ✓ |
Check Browser Support
const webRTCInfo = TelnyxRTC.webRTCInfo;
console.log('WebRTC supported:', webRTCInfo.supportWebRTC);
Troubleshooting
| Issue | Solution |
|---|
| No audio | Check microphone permissions in browser |
| Echo/feedback | Use headphones or enable echo cancellation |
| Connection fails | Check network, firewall, or use TURN relay |
| Quality issues | Enable debug: true and check telnyx.stats.frame events |
references/webrtc-server-api.md has the server-side WebRTC API — credential creation, token generation, and push notification setup. You MUST read it when setting up authentication or push notifications.
API Reference
TelnyxRTC
The TelnyxRTC client connects your application to the Telnyx backend,
enabling you to make outgoing calls and handle incoming calls.
const client = new TelnyxRTC({
login_token: login_token,
});
client
.on('telnyx.ready', () => console.log('ready to call'))
.on('telnyx.notification', (notification) => {
console.log('notification:', notification);
});
client.connect();
client.disconnect();
client.off('telnyx.ready');
client.off('telnyx.notification');
Methods
checkPermissions
▸ checkPermissions(audio?, video?): Promise<boolean>
Params: audio (boolean), video (boolean)
Returns: Promise
const client = new TelnyxRTC(options);
client.checkPermissions();
disableMicrophone
▸ disableMicrophone(): void
Returns: void
const client = new TelnyxRTC(options);
client.disableMicrophone();
enableMicrophone
▸ enableMicrophone(): void
Returns: void
const client = new TelnyxRTC(options);
client.enableMicrophone();
getAudioInDevices
▸ getAudioInDevices(): Promise<MediaDeviceInfo[]>
Returns: Promise
getAudioOutDevices
▸ getAudioOutDevices(): Promise<MediaDeviceInfo[]>
Returns: Promise
getDeviceResolutions
▸ getDeviceResolutions(deviceId): Promise<any[]>
Params: deviceId (string)
Returns: Promise
async function() {
const client = new TelnyxRTC(options);
let result = await client.getDeviceResolutions();
console.log(result);
}
getDevices
▸ getDevices(): Promise<MediaDeviceInfo[]>
Returns: Promise
async function() {
const client = new TelnyxRTC(options);
let result = await client.getDevices();
console.log(result);
}
getVideoDevices
▸ getVideoDevices(): Promise<MediaDeviceInfo[]>
Returns: Promise
async function() {
const client = new TelnyxRTC(options);
let result = await client.getVideoDevices();
console.log(result);
}
handleLoginError
▸ handleLoginError(error): void
Params: error (any)
Returns: void
Error handling
An error will be thrown if destinationNumber is not specified.
const call = client.newCall().catch(console.error);
Setting Custom Headers
client.newCall({
Setting Preferred Codec
You can pass preferred_codecs to the newCall method to set codec preference during the call.
ICE Candidate Prefetching
ICE candidate prefetching is enabled by default. This pre-gathers ICE candidates when the
client.newCall({
destinationNumber: 'xxx',
prefetchIceCandidates: false,
});
Trickle ICE
Trickle ICE can be enabled by passing trickleIce to the newCall method.
client.newCall({
destinationNumber: 'xxx',
trickleIce: true,
});
Call Recovery and recoveredCallId
When a call is recovered after a network reconnection (reattach), the SDK
Voice Isolation
Voice isolation options can be set by passing an audio object to the newCall method. This property controls the settings of a MediaStreamTrack object. For reference on available audio constraints, see MediaTrackConstraints.
Events
TelnyxRTC
Params: eventName (string), callback (Function)
setAudioSettings
▸ setAudioSettings(settings): Promise<MediaTrackConstraints>
Params: settings (IAudioSettings)
Returns: Promise
const constraints = await client.setAudioSettings({
micId: '772e94959e12e589b1cc71133d32edf543d3315cfd1d0a4076a60601d4ff4df8',
micLabel: 'Internal Microphone (Built-in)',
echoCancellation: false,
});
webRTCInfo
▸ Static webRTCInfo(): string | IWebRTCInfo
Returns: string
const info = TelnyxRTC.webRTCInfo();
const isWebRTCSupported = info.supportWebRTC;
console.log(isWebRTCSupported);
webRTCSupportedBrowserList
▸ Static webRTCSupportedBrowserList(): IWebRTCSupportedBrowser[]
Returns: IWebRTCSupportedBrowser
const browserList = TelnyxRTC.webRTCSupportedBrowserList();
console.log(browserList);
Call
A Call is the representation of an audio or video call between
two browsers, SIP clients or phone numbers. The call object is
created whenever a new call is initiated, either by you or the
remote caller. You can access and act upon calls initiated by
a remote caller in a telnyx.notification event handler.
To create a new call, i.e. dial:
const call = client.newCall({
destinationNumber: '18004377950',
callerNumber: '155531234567',
});
To answer an incoming call:
client.on('telnyx.notification', (notification) => {
const call = notification.call;
if (notification.type === 'callUpdate' && call.state === 'ringing') {
call.answer();
}
});
Both the outgoing and incoming call has methods that can be hooked up to your UI.
call.hangup();
call.dtmf('1234');
call.hold();
call.muteAudio();
Properties
Accessors
Methods
getStats
▸ getStats(callback, constraints): void
Params: callback (Function), constraints (any)
Returns: void
setAudioInDevice
▸ setAudioInDevice(deviceId, muted?): Promise<void>
Params: deviceId (string), muted (boolean)
Returns: Promise
await call.setAudioInDevice('abc123');
setAudioOutDevice
▸ setAudioOutDevice(deviceId): Promise<boolean>
Params: deviceId (string)
Returns: Promise
await call.setAudioOutDevice('abc123');
setVideoDevice
▸ setVideoDevice(deviceId): Promise<void>
Params: deviceId (string)
Returns: Promise
await call.setVideoDevice('abc123');
ICallOptions
ICallOptions
ICallOptions
Properties
IClientOptions
IClientOptions
IClientOptions
Properties