TermCall
Terminal-based P2P video calling app that renders live webcam feeds as ASCII art and streams them over WebRTC data channels.
TermCall
TermCall is a terminal video call client. Start it, pick a username and a room, and you're connected to anyone else in that room - video comes through as colored ASCII art in your terminal instead of a normal video window.
It's WebRTC under the hood: a signaling server introduces peers, then audio and video stream directly between them (full mesh, no media server in the middle). Frames get downsampled and drawn with half-block characters and ANSI color, so it works in any truecolor terminal.
https://github.com/user-attachments/assets/e4fcb05c-7089-4a93-8465-0f8415fcb790
Table of Contents
Features
- Reliable NAT traversal: when direct peer-to-peer connections fail (symmetric NATs, restrictive firewalls, hotel/corporate Wi-Fi), a bundled self-hostable TURN server relays packets so calls still connect when peers can't reach each other directly
- A self-hostable backend server:
termcall-serverruns the signaling server and TURN relay in one process — host it yourself on any Linux VPS with a singledocker compose up -dcommand, no C toolchain or manual binary build required - Public test server available: skip self-hosting and try TermCall right away at
ws://termcall-server.m4yank.com:8080/ws— the maintainer runs a live instance for anyone to join a room and see it work - Peer-to-peer video calls rendered as colored ASCII / half-block art, right in the terminal
- Full-mesh WebRTC: audio and video flow directly between peers once they're introduced
- Three render modes — ASCII, Color256, HalfBlock (HalfBlock by default)
- Live per-peer stats: bandwidth, packet loss, and ping
- Mic and camera toggles, mute state, and voice-activity bars
- One base16 color theme, consistent across the whole UI
Install
There are a couple of ways to install TermCall.
Precompiled binaries
Precompiled binaries for released versions are available on the releases page of the GitHub repo. Download the binary for your platform, make it executable, and run it:
chmod +x termcall
./termcall
Building the client from source
To build TermCall from source you need:
- Go 1.25+ (the version in
go.modor greater). - CGO enabled (required for camera and microphone access via
mediadevices). - A working C compiler toolchain — see the platform-specific guide below.
macOS
Prerequisites
- Xcode Command Line Tools — provides the C compiler CGO links against. Install via
xcode-select --installfrom the Terminal, or from Apple's developer downloads.
Build and run
git clone https://github.com/msk1039/termcall.git
cd termcall
go mod tidy
go build -o termcall ./cmd/termcall
./termcall
Or just run it directly without producing a binary:
go run ./cmd/termcall
Windows
Prerequisites
You need a 64-bit GCC toolchain for CGO. Pick one of the following:
- TDM-GCC 64-bit (recommended) — download the
tdm64installer from https://jmeubank.github.io/tdm-gcc/download/ (not the 32-bit version), run it, and keep the option that adds it to your PATH. - MSYS2 — install from https://www.msys2.org/, then in the MSYS2 UCRT64 terminal run:
and addpacman -S mingw-w64-ucrt-x86_64-gccC:\msys64\ucrt64\binto your system PATH.
Verify with gcc -v — the Target: line should say x86_64....
If you hit
cc1.exe: sorry, unimplemented: 64-bit mode not compiled in, you're on a 32-bitgcc. Remove any old 32-bit MinGW from your PATH, install a 64-bit compiler (TDM-GCC 64), and make sure it's first in PATH.
Build and run
From PowerShell (the env vars are required so go build uses CGO and targets amd64):
git clone https://github.com/msk1039/termcall.git
cd termcall
$env:GOARCH="amd64"
$env:CGO_ENABLED=1
go mod tidy
go build -o termcall.exe ./cmd/termcall
./termcall.exe
Usage
There are two ways to start a call.
1. The join form (default). Run the binary with no flags:
./termcall
You'll get a join screen — type a username, room ID, and server URL (pre-filled with a default), move between fields with ↑/↓, and press enter to join.
2. Flags. Skip the form by passing a username, room name and backend server url
./termcall -username alice -room my-room
./termcall -username alice -room my-room -server ws://localhost:8080/ws
Once you're in a call:
- [V] Toggle camera
- [M] Toggle microphone
- [S] Toggle stats overlay (bandwidth, loss, ping)
- [N] Cycle render mode (ASCII → Color256 → HalfBlock; defaults to HalfBlock)
- [Q] Quit
Self-hosting the server
TermCall needs a signaling + TURN server to pair peers and relay media when direct connections fail. The termcall-server binary runs both in one process, and you can host it on any Linux VPS with a public IP.
Run with Docker (Linux VMs)
For hosting on a Linux VM, the included Docker setup is the easiest path. It uses network_mode: host so the TURN server can bind its full relay port range (49152–65535) directly to the host — no need to map thousands of UDP ports.
Docker Desktop on macOS/Windows isn't supported here;
network_mode: hostonly behaves correctly on Linux.
Clone and configure
.env:git clone https://github.com/msk1039/termcall.git cd termcall cp .env.example .env curl -s ifconfig.me # your server's public IPEdit
.env: setTERMCALL_PUBLIC_IPto the address above and changeTERMCALL_TURN_SECRETto a random string. The full variable reference is in Configure `.env` below.Open the firewall ports (and the cloud firewall, if any):
sudo ./scripts/setup_firewall.shBuild and start the server:
docker compose up -d --buildVerify it's running:
docker ps docker compose logs
To secure the WebSocket signaling channel with TLS (recommended for production), see docs/tls-setup.md.
Configure .env
Copy the template and set your public IP:
cp .env.example .env
curl -s ifconfig.me # your server's public IP
Edit .env and set TERMCALL_PUBLIC_IP to that address. Only that field is required — ports, the relay range, max room size, and the TURN secret all have defaults you can leave as-is or tweak.
Open the firewall ports
By default the server uses a WebSocket port (8080/tcp), a TURN port (3478/tcp+udp), and a UDP relay range (49152-65535/udp). Open them with the included script, which reads your .env:
sudo ./scripts/setup_firewall.sh
If your VPS has a cloud firewall too (AWS Security Groups, Hetzner, DigitalOcean, etc.), open the same ports there — the script only configures the OS-level firewall.
On restrictive networks (some mobile carriers, corporate Wi-Fi), TURN on port 443 reaches clients that block 3478. Set
TERMCALL_TURN_PORT=443in.envif you run into that.
Point clients at it
Enter the server URL in the join form, or pass it with -server:
./termcall -username alice -room my-room -server ws://YOUR.VPS.IP:8080/ws
Anyone who joins the same room on your server gets connected.