VoIP & Audio Calling
Relevant source files
The following files were used as context for generating this wiki page:
The VoIP (Voice over IP) and Audio Calling system in Baileys provides a comprehensive framework for handling real-time communication. It supports initiating, receiving, and managing voice and video calls through the WhatsApp protocol. The system is designed to handle signaling (call offers, acceptances, rejections) and provides a specialized VoipClient for streaming audio sources directly into active calls.
This module integrates deeply with the socket layer to process binary nodes associated with call events, such as offer, accept, terminate, and relay. It also includes mechanisms for handling group calls, call links, and media streaming using external audio files or pcm chunks.
Sources: lib/Voip/index.js, lib/Socket/messages-recv.js:106-250, assets/examples/example.js:189-204
System Architecture
The VoIP system is split between high-level socket methods for signaling and a specialized VoipClient for media handling. Call states are managed via a dedicated cache and event emitter system that notifies the application of incoming calls and state transitions.
Call Signaling Flow
The signaling process involves sending and receiving call stanzas. When a call is initiated, an offer node is sent containing media capabilities (codecs like Opus or VP8) and destination participant nodes.
Key Components
VoipClient
The VoipClient is the primary interface for advanced calling features, particularly media streaming. It loads a native or specialized VoIP module (index.mjs) to handle the heavy lifting of connection and call management.
| Method | Description |
|---|---|
initWithSocket(sock) | Initializes the client with an active socket and identity keys. |
call(phoneNumber, opts) | Initiates a call with an audio source (file path or PCM). |
connect() | Establishes the VoIP connection. |
disconnect() | Terminates the VoIP session. |
Sources: lib/Voip/index.js:20-48
Call State Management
Baileys uses an internal callOfferCache to track the lifecycle of a call. Statuses include offer, ringing, accept, reject, timeout, and terminate.
Core Implementation Details
Call Initialization Logic
Initiating a call involves verifying authentication and determining if the call is a 1-to-1 or group call. If an audioSource is provided, the VoipClient is utilized; otherwise, a standard protocol offer is generated.
// lib/Socket/messages-recv.js:189-205
const initiateCall = async (jid, options = {}) => {
const meId = authState.creds.me?.id;
if (!meId) throw new Error('Not authenticated');
if (options.audioSource) {
const client = await getVoipClient();
const call = await client.call(jid, options);
await callOfferCache.set(call.callId, { ...call, status: 'offer' });
return call;
}
// ... standard offer logic
};
Sources: lib/Socket/messages-recv.js:189-218
Signaling Stanzas
Calls are managed through binary nodes. Key attributes include call-id and call-creator.
- Offer Node: Contains
<audio>(e.g., enc:opus, rate:16000) and<video>capabilities, along with<destination>nodes for encrypted participant keys. - Accept Node: Sent to answer a call; specifies local media capabilities.
- Terminate Node: Ends the call, often including a
reason(e.g.,timeout,miscellaneous) andduration.
Sources: lib/Socket/messages-recv.js:225-276, lib/Utils/generics.js:525-565
Event Handling
The socket emits a call event whenever a call-related node is received.
| Attribute | Type | Description |
|---|---|---|
id | string | Unique Call ID. |
chatId | string | The remote JID involved in the call. |
status | string | Current state (offer, accept, terminate, etc.). |
isVideo | boolean | Whether the call includes video. |
isGroup | boolean | True if it is a group call or call link. |
participants | Array | List of participants and their states in group calls. |
Sources: lib/Types/Call.d.ts:39-65, lib/Socket/messages-recv.js:952-1045
Advanced Functionality
Media Streaming and Direct PCM
The ActiveCall instance returned by initiateCall (when using audioSource) provides event listeners for real-time interaction.
// assets/examples/example.js:195-201
const call = await sock.initiateCall(jid, {
audioSource: './audio.mp3',
durationMs: 30000
});
call.on('connected', () => console.log('Streaming audio!'));
call.on('audio', (pcmChunk) => { /* Incoming 16 kHz PCM data */ });
Sources: assets/examples/example.js:195-201
Group Call Links
Baileys supports querying and joining calls via tokens.
queryCallLink(token): Retrieves metadata about a call link.joinCallLink(token): Sends alink_joinnode to participate in the call.
Sources: lib/Socket/messages-recv.js:372-392
Summary
The VoIP system in Baileys provides a robust signaling layer integrated into the message reception loop, complemented by a specialized VoIP client for media processing. By handling both standard WhatsApp signaling stanzas and raw audio streaming, it enables developers to build automated voice response systems or custom calling interfaces.
Sources: lib/Socket/messages-recv.js, lib/Voip/index.js