Loading...
Loading...
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.
npx skill4agent add team-telnyx/skills telnyx-webrtc-client-jsPrerequisites: Create WebRTC credentials and generate a login token using the Telnyx server-side SDK. See theskill in your server language plugin (e.g.,telnyx-webrtc-*,telnyx-python).telnyx-javascript
npm install @telnyx/webrtc --saveimport { TelnyxRTC } from '@telnyx/webrtc';const client = new TelnyxRTC({
login_token: 'your_jwt_token',
});
client.connect();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.
// When done, disconnect and remove listeners
client.disconnect();
client.off('telnyx.ready');
client.off('telnyx.notification');client.remoteElement = 'remoteMedia';<audio id="remoteMedia" autoplay="true" />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;
// Handle incoming call
if (activeCall.state === 'ringing') {
// Show incoming call UI
// Call activeCall.answer() to accept
}
}
});| Event | Description |
|---|---|
| Client connected and ready |
| Error occurred |
| Call updates, incoming calls |
| In-call quality metrics (when debug enabled) |
const call = client.newCall({
destinationNumber: '+18004377950',
callerNumber: '+15551234567',
});client.on('telnyx.notification', (notification) => {
const call = notification.call;
if (notification.type === 'callUpdate' && call.state === 'ringing') {
// Incoming call - show UI and answer
call.answer();
}
});// End call
call.hangup();
// Send DTMF tones
call.dtmf('1234');
// Mute audio
call.muteAudio();
call.unmuteAudio();
// Hold
call.hold();
call.unhold();const call = client.newCall({
destinationNumber: '+18004377950',
debug: true,
debugOutput: 'socket', // 'socket' (send to Telnyx) or 'file' (save locally)
});const call = client.newCall({
destinationNumber: '+18004377950',
debug: true, // Required for metrics
});
client.on('telnyx.stats.frame', (stats) => {
console.log('Quality stats:', stats);
// Contains jitter, RTT, packet loss, etc.
});import { PreCallDiagnosis } from '@telnyx/webrtc';
PreCallDiagnosis.run({
credentials: {
login: 'sip_username',
password: 'sip_password',
// or: loginToken: 'jwt_token'
},
texMLApplicationNumber: '+12407758982',
})
.then((report) => {
console.log('Diagnosis report:', report);
})
.catch((error) => {
console.error('Diagnosis failed:', error);
});const allCodecs = RTCRtpReceiver.getCapabilities('audio').codecs;
// Prefer Opus for AI/high quality
const opusCodec = allCodecs.find(c =>
c.mimeType.toLowerCase().includes('opus')
);
// Or PCMA for telephony compatibility
const pcmaCodec = allCodecs.find(c =>
c.mimeType.toLowerCase().includes('pcma')
);
client.newCall({
destinationNumber: '+18004377950',
preferred_codecs: [opusCodec],
});const isRegistered = await client.getIsRegistered();
console.log('Registered:', isRegistered);const client = new TelnyxRTC({
anonymous_login: {
target_id: 'your-ai-assistant-id',
target_type: 'ai_assistant',
},
});
client.connect();Note: The AI assistant must haveset totelephony_settings.supports_unauthenticated_web_calls.true
// After anonymous login, destinationNumber is ignored
const call = client.newCall({
destinationNumber: '', // Can be empty
remoteElement: 'remoteMedia',
});const allCodecs = RTCRtpReceiver.getCapabilities('audio').codecs;
const opusCodec = allCodecs.find(c =>
c.mimeType.toLowerCase().includes('opus')
);
client.newCall({
destinationNumber: '',
preferred_codecs: [opusCodec], // Opus recommended for AI
});| Platform | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| Android | ✓ | ✓ | - | - |
| iOS | - | - | ✓ | - |
| Linux | ✓ | ✓ | - | - |
| macOS | ✓ | ✓ | ✓ | ✓ |
| Windows | ✓ | ✓ | - | ✓ |
const webRTCInfo = TelnyxRTC.webRTCInfo;
console.log('WebRTC supported:', webRTCInfo.supportWebRTC);| 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 |
TelnyxRTC// Initialize the client
const client = new TelnyxRTC({
// Use a JWT to authenticate (recommended)
login_token: login_token,
// or use your Connection credentials
// login: username,
// password: password,
});
// Attach event listeners
client
.on('telnyx.ready', () => console.log('ready to call'))
.on('telnyx.notification', (notification) => {
console.log('notification:', notification);
});
// Connect and login
client.connect();
// You can call client.disconnect() when you're done.
// Note: When you call `client.disconnect()` you need to remove all ON event methods you've had attached before.
// Disconnecting and Removing listeners.
client.disconnect();
client.off('telnyx.ready');
client.off('telnyx.notification');audio?video?PromisebooleanaudiovideoPromiseconst client = new TelnyxRTC(options);
client.checkPermissions();voidvoidconst client = new TelnyxRTC(options);
client.disableMicrophone();voidvoidconst client = new TelnyxRTC(options);
client.enableMicrophone();PromiseMediaDeviceInfoPromisePromiseMediaDeviceInfoPromisedeviceIdPromiseanydeviceIdPromiseasync function() {
const client = new TelnyxRTC(options);
let result = await client.getDeviceResolutions();
console.log(result);
}PromiseMediaDeviceInfoPromiseasync function() {
const client = new TelnyxRTC(options);
let result = await client.getDevices();
console.log(result);
}PromiseMediaDeviceInfoPromiseasync function() {
const client = new TelnyxRTC(options);
let result = await client.getVideoDevices();
console.log(result);
}errorvoiderrorvoiddestinationNumberconst call = client.newCall().catch(console.error);
// => `destinationNumber is required`preferred_codecsnewCallclient.newCall({
destinationNumber: 'xxx',
prefetchIceCandidates: false,
});trickleIcenewCallclient.newCall({
destinationNumber: 'xxx',
trickleIce: true,
});recoveredCallIdaudionewCalleventNamecallbacksettingsPromiseMediaTrackConstraintssettingsPromise// within an async function
const constraints = await client.setAudioSettings({
micId: '772e94959e12e589b1cc71133d32edf543d3315cfd1d0a4076a60601d4ff4df8',
micLabel: 'Internal Microphone (Built-in)',
echoCancellation: false,
});StaticstringIWebRTCInfostringconst info = TelnyxRTC.webRTCInfo();
const isWebRTCSupported = info.supportWebRTC;
console.log(isWebRTCSupported); // => trueStaticIWebRTCSupportedBrowserIWebRTCSupportedBrowserconst browserList = TelnyxRTC.webRTCSupportedBrowserList();
console.log(browserList); // => [{"operationSystem": "Android", "supported": [{"browserName": "Chrome", "features": ["video", "audio"], "supported": "full"},{...}]Callcalltelnyx.notificationconst call = client.newCall({
// Destination is required and can be a phone number or SIP URI
destinationNumber: '18004377950',
callerNumber: '155531234567',
});client.on('telnyx.notification', (notification) => {
const call = notification.call;
if (notification.type === 'callUpdate' && call.state === 'ringing') {
call.answer();
}
});// Hangup or reject an incoming call
call.hangup();
// Send digits and keypresses
call.dtmf('1234');
// Call states that can be toggled
call.hold();
call.muteAudio();callbackconstraintsvoidcallbackconstraintsvoiddeviceIdmuted?PromisevoiddeviceIdmutedPromiseawait call.setAudioInDevice('abc123');deviceIdPromisebooleandeviceIdPromiseawait call.setAudioOutDevice('abc123');deviceIdPromisevoiddeviceIdPromiseawait call.setVideoDevice('abc123');