Skip to content

Add WhatsApp call recording support via wavoip integration#1208

Draft
leifermendez wants to merge 6 commits intobuilderbotfrom
claude/bailey-call-recording-JIfaN
Draft

Add WhatsApp call recording support via wavoip integration#1208
leifermendez wants to merge 6 commits intobuilderbotfrom
claude/bailey-call-recording-JIfaN

Conversation

@leifermendez
Copy link
Member

Que tipo de Pull Request es?

  • Mejoras

Descripción

This PR adds comprehensive WhatsApp call recording and management capabilities to the Baileys provider through integration with the wavoip infrastructure.

Changes Overview

New Features

  1. Call Recording Infrastructure

    • Added CallRecord interface to track call metadata (ID, caller, status, duration, timestamps)
    • Implemented call history persistence as JSON metadata files
    • Support for configurable recording formats (WAV, MP3)
    • Automatic call record directory creation and management
  2. Wavoip Bridge Integration

    • Established Socket.IO connection to wavoip servers for call signaling
    • Forwarded critical Baileys methods to wavoip (onWhatsApp, profilePictureUrl, assertSessions, etc.)
    • Implemented bidirectional event forwarding for connection updates and raw call packets
    • Added proper connection lifecycle management (connect, disconnect, error handling)
  3. Call Management APIs

    • rejectCall(): Programmatically reject incoming calls
    • getCallHistory(): Retrieve all saved call records from disk
    • getActiveCall(): Get info about a specific active call
    • getActiveCalls(): Get all currently active calls
  4. Configuration Options

    • New callRecording config object with:
      • enabled: Toggle call recording
      • path: Custom recordings directory
      • format: Audio format preference (wav/mp3)
      • autoReject: Auto-reject incoming calls
      • wavoip: Wavoip server configuration (token, logger, softwareBase)

Technical Details

  • Added socket.io-client dependency for wavoip communication
  • Enhanced call event handler to track call lifecycle (offer → accept/reject/timeout → terminate)
  • Implemented proper cleanup of wavoip connections on provider shutdown
  • Call records include duration calculation and file path references for future audio integration

Files Modified

  • package.json: Added socket.io-client dependency
  • src/bailey.ts: Core implementation of wavoip bridge and call recording
  • src/type.ts: New TypeScript interfaces for call recording and wavoip events
  • src/index.ts: Exported new types for public API

Usage Example

const provider = new BaileysProvider({
  callRecording: {
    enabled: true,
    path: './recordings',
    format: 'wav',
    autoReject: false,
    wavoip: {
      token: 'your-wavoip-token',
      logger: true
    }
  }
})

// Get call history
const history = await provider.getCallHistory()

// Reject a call programmatically
await provider.rejectCall(callId, callFrom)

// Check active calls
const activeCalls = provider.getActiveCalls()

Forma parte de este proyecto:

https://claude.ai/code/session_01MBVnTKbwmRhfiyHYZoPmP9

Implement call recording infrastructure for the Bailey provider, similar
to wavoip's approach. Tracks the full call lifecycle (offer, accept,
reject, timeout, terminate), saves call metadata as JSON with expected
audio file paths (wav/mp3), and exposes methods to reject calls, query
active calls, and retrieve call history.

https://claude.ai/code/session_01MBVnTKbwmRhfiyHYZoPmP9
…l recording

Implement the same call recording pattern used by voice-calls-baileys:
- Forward raw CB:call and CB:ack,class:call WebSocket packets to wavoip
- Bridge all required Baileys methods (onWhatsApp, assertSessions,
  createParticipantNodes, getUSyncDevices, sendNode, decryptMessage)
- Forward connection updates and QR codes to wavoip server
- Add socket.io-client dependency for wavoip communication
- Add WavoipOptions config (token, softwareBase, logger)
- Add complete TypeScript types for wavoip server/client events
- Proper cleanup on disconnect/shutdown

Usage:
  callRecording: {
    enabled: true,
    format: 'mp3',
    wavoip: { token: 'YOUR_WAVOIP_TOKEN' }
  }

https://claude.ai/code/session_01MBVnTKbwmRhfiyHYZoPmP9
Replace wavoip bridge with fully native call recording implementation:

- Parse CB:call and CB:ack binary nodes to extract SRTP keys and relay endpoints
- Build call signaling response nodes (preaccept, accept) locally
- Connect to WhatsApp relay servers via UDP (dgram)
- STUN binding request/response handling for relay negotiation
- SRTP decryption using AES-128-CM + HMAC-SHA1 (RFC 3711) via Node crypto
- FFmpeg pipeline (already a dependency) to encode Opus audio as WAV/MP3
- Full call lifecycle tracking (offer→accept→terminate) with metadata JSON
- Public methods: startCallRecording(), stopCallRecording(), rejectCall()
- Remove socket.io-client dependency - zero external service dependencies

https://claude.ai/code/session_01MBVnTKbwmRhfiyHYZoPmP9
…otocol

- Rewrite callRecording.ts with protocol structures verified from WPPConnect
  wa-js and WA-Calls repos (te2 6-byte binary, HKDF-SHA256, WASP STUN)
- Add custom ACK sending after CB:call offer (required by protocol)
- Add Signal Protocol decryption flow to extract 32-byte callKey from enc nodes
- Replace buildPreacceptNode with proper buildCustomAck and buildTerminateNode
- Update parseCallAckPacket to return relayKey + tokens Map
- Add relayId/tokenId fields to RelayEndpoint type
- Pass tokens to updateRelays for relay-token association

https://claude.ai/code/session_01MBVnTKbwmRhfiyHYZoPmP9
…ting

Fixes found from live testing with actual WhatsApp calls:

- Fix `invalid children for header "audio": null` — Baileys rejects
  `content: null`, changed to `content: undefined` (omitted) in
  buildAcceptNode and buildTerminateNode
- Remove custom ACK sending that caused `xml-not-well-formed` stream
  errors and connection drops — Baileys handles ACKs internally
- Add duplicate CB:call guard (processedCallIds Set) to prevent
  processing the same callId multiple times
- Rename encKeys → encNodes with full EncNodeData type that preserves
  enc node attrs (type: 'pkmsg'|'msg', version, count) for Signal
  Protocol decryption
- Resolve @lid JIDs to @s.whatsapp.net via getPNForLID before Signal
  Protocol decryption (sessions are keyed on phone number JIDs)
- Add detailed logging for each decrypt attempt with method/type/error
- Try both 'pkmsg' and 'msg' types as fallback during decryption
- Await decryptCallKey before handleAutoAcceptCall to ensure keys
  are available before accepting

https://claude.ai/code/session_01MBVnTKbwmRhfiyHYZoPmP9
Two fixes from live testing:

1. Accept/terminate nodes missing required `id` attribute — Baileys
   serializer produces xml-not-well-formed error when `id` is absent.
   Added random hex ID generation (matching WPPConnect generateId).

2. Signal Protocol decrypted buffer (80 bytes) has unpadRandomMax16
   padding — last byte N indicates N bytes of padding to strip before
   protobuf decode. Added unpadding step so proto.Message.decode can
   find msg.call.callKey (32 bytes SRTP master secret).

https://claude.ai/code/session_01MBVnTKbwmRhfiyHYZoPmP9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants