MCPcopy Index your code
hub / github.com/JotaDev66/WaCalls

github.com/JotaDev66/WaCalls @v1.0.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.0.0 ↗ · + Follow
997 symbols 2,974 edges 162 files 360 documented · 36% updated 7d agov1.0.0 · 2026-06-25★ 2421 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

📞 WaCalls (Go)

Native WhatsApp voice calls in pure Go, straight from the browser. Built for native VoIP media, multi-account (multi-session) operation, and a modern browser client.

Go React whatsmeow pion License

Overview · Architecture · Quick Start · API · Security


Overview

WaCalls pairs one or more WhatsApp accounts via QR code and lets you place and receive 1:1 voice calls from any browser on the LAN. The browser microphone is sent as raw 16 kHz PCM over a WebRTC data channel to the Go server, which encodes it with Meta's MLow codec and injects the media into WhatsApp's SRTP relay mesh — and the reverse path brings the peer's audio back to the browser.

The entire VoIP stack runs natively in pure Go: the MLow voice codec, RTP/SRTP packetization, STUN, the WebRTC/SCTP relay transport and the <call> signaling, integrated with whatsmeow and served to a React 19 client. There is no cgo and no native DLL — the MLow codec is a vendored pure-Go package, so a plain go build produces a self-contained binary with live audio.

Multiple WhatsApp accounts can be paired and operated side by side, each with its own pairing QR, connection status, and history. A single account can also run several concurrent 1:1 calls at once — one per browser operator — routed independently by call ID.

Status: stable. Outgoing and incoming 1:1 calls reach ACTIVE with bidirectional audio, and a single account can hold several of them concurrently. Sessions persist in wacalls.db (pure-Go SQLite).


Architecture

┌──────────────────────────────────────────────────────────────────────────┐
│                          BROWSER (React client)                            │
│   mic + speaker  ·  WebRTC data channel (16 kHz PCM)  ·  HTTP + SSE         │
└───────────────────────────────┬──────────────────────────────────────────┘
                                 │  POST /api/sessions/{sid}/calls/{id}/webrtc  (SDP)
                                 │  GET  /api/events                            (SSE)
                                 ▼
┌──────────────────────────── GO SERVER (cmd/server) ────────────────────────┐
│  SessionManager   registry of accounts (client + CallManager + bridge)     │
│  Broker           SSE hub (sessions, auth, call lifecycle fan-out)          │
│  Bridge           pion WebRTC bridge (16 kHz PCM data channel ⇄ call core)  │
│                                                                            │
│  internal/wa      VoipSocket adapter over whatsmeow                        │
│  internal/voip    call · signaling · media · transport · core · wanode     │
└───────────────┬──────────────────────────────────────┬────────────────────┘
                │ <call> signaling (Signal/USync)       │ SRTP media
                ▼                                        ▼
        ┌───────────────┐                    ┌──────────────────────┐
        │  WhatsApp WS  │                    │   WhatsApp relay      │
        │  (whatsmeow)  │                    │  (SRTP over SCTP/DC)  │
        └───────────────┘                    └──────────────────────┘

Layout

Path Responsibility
cmd/server HTTP/SSE broker, session manager + store, WebRTC bridge, process lifecycle
internal/wa VoipSocket — sends/receives <call> stanzas via whatsmeow
internal/voip/core Domain types, constants, the VoipSocket interface
internal/voip/wanode Shared WhatsApp-node and JID helpers
internal/voip/media MLow codec (vendored pure-Go mlow/), RTP, SRTP, SSRC, PCM helpers, key derivation
internal/voip/transport SCTP relay, STUN, subscription encoding
internal/voip/signaling <call> stanza build/parse, call-key crypto, relay-ack parsing
internal/voip/call CallManager — orchestrates a single call end to end
client/ React 19 + Vite + Tailwind v4 + shadcn/ui (dialer, call cards, sessions, history)

How a call flows

The core is internal/voip/call.CallManager, which drives a call end to end. Outgoing call sequence:

1. POST .../calls            → CallManager.StartCall(peerJid)
                               generates a callID, builds the <call> offer, sends it

2. Browser opens WebRTC      → POST .../calls/{id}/webrtc (SDP offer)
                               the bridge answers with an SDP answer (pion)

3. Peer accepts              → events.CallAccept → HandleCallAccept
                               server receives <relay> + hop-by-hop keys

4. Relay transport           → STUN binding/allocate on WhatsApp relays
                               ICE + DTLS + SCTP DataChannel connect (pion)

5. SRTP media flowing        → state goes ACTIVE
   ├── uplink   (you → peer): browser 16 kHz PCM (data channel) → MLow encode → SRTP → relay
   └── downlink (peer → you): relay → SRTP → MLow decode → 16 kHz PCM (data channel) → browser

6. Teardown                  → DELETE .../calls/{id} or events.CallTerminate
                               CallManager.EndCall + bridge cleanup

Each protocol step (hop-by-hop SRTP key derivation, RTP packetization at PT=120/16 kHz, STUN relay registration, relay-ack and <call> stanza parsing) is implemented and covered by tests in internal/voip (go test ./...).


Requirements

  • Go 1.26+
  • Node 22+ and npm (only to build/run the React client)

No C compiler, cgo, or native libraries are required — the MLow codec is vendored pure Go (internal/voip/media/mlow).


Quick Start

# clone and enter the project
git clone <repo-url> wacalls-go
cd wacalls-go

# Go dependencies
go mod download

# React client dependencies
cd client && npm install && cd ..

Run

go run ./cmd/server -addr :8080          # add -debug for verbose logs

Live audio works out of the box — the MLow codec is pure Go, so a plain build includes it. No build tags, no CGO_ENABLED, no DLLs.

Open http://localhost:8080, click New session, and scan the QR shown in the browser (it is also printed in the terminal) with WhatsApp → Linked devices. Add more accounts the same way and switch between them in the sidebar.

React client in dev mode

cd client
npm run dev      # Vite on :5173, proxies /api → http://localhost:8080

For production, build the static client and serve it from the Go server:

cd client && npm run build && cd ..
go run ./cmd/server -static client/dist -addr :8080

Server flags

Flag Default Meaning
-addr :8080 HTTP listen address
-db wacalls.db SQLite session database path
-static client/dist Static client directory (optional)
-debug false Verbose logging (includes whatsmeow's internal log)
-max-calls-per-session 8 Max concurrent calls per session (0 = unlimited)

API

All routes are session-scoped. Events stream over a single SSE channel, tagged with the originating sessionId.

Method Route Purpose
GET /api/sessions List accounts (id, name, jid, status, paired)
POST /api/sessions Create an account and begin QR pairing
DELETE /api/sessions/{sid} Log out and remove an account
POST /api/sessions/{sid}/logout Disconnect an account (keep it for re-pairing)
POST /api/sessions/{sid}/pair Re-pair an account (emit a fresh QR)
POST /api/sessions/{sid}/calls Start an outgoing call ({ phone, duration_ms?, record? })
POST /api/sessions/{sid}/calls/{id}/webrtc Exchange the browser WebRTC SDP
POST /api/sessions/{sid}/calls/{id}/accept Accept an incoming call
POST /api/sessions/{sid}/calls/{id}/reject Reject an incoming call
DELETE /api/sessions/{sid}/calls/{id} End an active call
GET /api/sessions/{sid}/history Recent call history (up to 50 records)
GET /api/events Server-sent events (sessions, auth, call lifecycle)

Tests

go test ./...                 # media stack: SRTP, STUN, RTP, relay-ack, codec, state
cd client && npm run build    # client type-check + production build

Security

The API has no authentication — anyone with HTTP access can create accounts, place calls, and read history. Run it only on a trusted LAN. wacalls.db holds WhatsApp session credentials (secrets): do not commit it and keep it protected.


Contributors

This project builds on the work of:

jotadev66 jobasfernandes edgardmessias w3nder

@jotadev66 · @jobasfernandes · @edgardmessias · @w3nder


Acknowledgements

  • whatsmeow — Go WhatsApp Web protocol library
  • pion/webrtc — pure-Go WebRTC stack (ICE + DTLS + SCTP)
  • whatsapp-rust — reference MLow codec implementation (ported to the vendored pure-Go internal/voip/media/mlow)
  • zapo — VoIP media-stack reference

License

MIT

Extension points exported contracts — how you extend this code

Option (FuncType)
Option configures optional, non-behavioral aspects of the codec — currently the diagnostic logger. The zero configuratio
internal/voip/media/mlow/logging.go
SheetContentProps (Interface)
(no doc)
client/src/components/ui/sheet.tsx
Codec (Interface)
(no doc) [1 implementers]
internal/voip/media/codec.go
ButtonProps (Interface)
(no doc)
client/src/components/ui/button.tsx
VoipSocket (Interface)
(no doc) [1 implementers]
internal/voip/core/voipsocket.go
BadgeProps (Interface)
(no doc)
client/src/components/ui/badge.tsx
RelayTransport (Interface)
(no doc) [1 implementers]
internal/voip/call/callmanager_relay.go

Core symbols most depended-on inside this repo

Error
called by 43
internal/voip/media/srtp.go
cn
called by 35
client/src/lib/utils.ts
AttrString
called by 24
internal/voip/wanode/nodeutil.go
writeJSON
called by 24
cmd/server/httpapi.go
Close
called by 23
internal/voip/media/codec.go
DecodeCDF
called by 20
internal/voip/media/mlow/rangecoder.go
Encode
called by 15
internal/voip/media/codec.go
EncodeCDF
called by 15
internal/voip/media/mlow/rangecoder.go

Shape

Function 577
Method 277
Struct 122
TypeAlias 8
Class 6
Interface 6
FuncType 1

Languages

Go92%
TypeScript8%

Modules by API surface

internal/voip/media/mlow/celp_enc.go56 symbols
internal/voip/media/mlow/cc_tables.go40 symbols
internal/voip/media/mlow/rangecoder.go36 symbols
internal/voip/media/mlow/lsf_quant.go27 symbols
internal/voip/media/mlow/postfilter.go26 symbols
internal/voip/media/mlow/encoder.go26 symbols
internal/voip/transport/sctprelay.go25 symbols
internal/voip/media/mlow/vad.go25 symbols
internal/voip/media/mlow/perc.go24 symbols
internal/voip/media/mlow/lpc.go24 symbols
internal/voip/media/mlow/analysis.go24 symbols
cmd/server/broker.go24 symbols

For agents

$ claude mcp add WaCalls \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page