TermFace
Secure terminal video call. Your webcam rendered as color ASCII art, with end-to-end encrypted peer-to-peer calls — works internationally, no Docker required.
Features
International Calls (WebRTC)
- Free TURN relay — OpenRelay servers handle NAT traversal, no setup needed
- Cloudflare Worker signaling — deployed at
wss://termface-signaling.termface.workers.dev - Server-assigned roles — the signaling server atomically assigns offerer/answerer roles
- Welcome with peers list — server tells you who's already in the room
- Auto-reconnect — 2.5s retry on disconnect
- Remote video as ASCII art — receive and display peer's webcam in your terminal
- Audio playback — hear your peer through speakers (PyAudio)
- 10fps optimized rendering — smooth display without freezing the terminal
End-to-End Encryption
- X25519 key exchange — shared secret derivation
- XSalsa20-Poly1305 — authenticated encryption (AEAD)
- Sequence numbers with replay protection
- Key rotation every 256 messages
- Encryption enabled by default for all calls
Audio & Video
- Opus audio codec — 24kHz at 32kbps, echo cancellation, noise gate
- Camera capture — OpenCV-backed, multiple device support
- Screen sharing — share your terminal or desktop
- Mute/camera controls — toggle mic and camera during calls
Compression & Transport
- zstd compression — with backward-compatible header detection
- TCP fallback — for LAN calls when no signaling server is available
- Session strings — share
happy-sunset-oceaninstead of IP addresses
In-Call Features
- Structured terminal UI — status bar, participant list, chat panel, controls
- Chat — in-call text messaging via data channel
- File transfer — cancel, pause/resume, disk preflight, SHA-256 verification
- Screenshots — save ASCII art as .txt and .png
- Recording — crash-safe pause/resume, atomic writes, live indicator
- Background effects — blur and removal (requires MediaPipe)
- Call quality stats — real-time RTT, bandwidth, packet loss, jitter
- Adaptive bitrate — auto-adjusts quality based on network conditions
- Audio jitter buffer — smooth playback despite uneven network arrivals
- Mesh SFU — group call relay for 3+ participants
- Peer state broadcasting — mute/video/screen status shared with peers
Install
Mac / Linux
pip install TermFace
Windows
pip install TermFace
That's it. No Docker, no workarounds, no extra configuration.
From Source
git clone https://github.com/Yash12b/TermFace.git
cd TermFace
pip install -e ".[dev]"
Quick Start
International Call (WebRTC)
# Person A
termface call --room happy-ocean-sunset
# Person B (same room name)
termface call --room happy-ocean-sunset
The second person to join automatically becomes the answerer. No role selection needed.
Local ASCII Webcam
ascii-cam
TCP Call (LAN only)
# Person A (starts server)
termface facetime --session myroom
# Person B (connects to A's IP)
termface facetime --session myroom --target 192.168.1.100
WebRTC Call (manual roles)
# Person A (answerer)
termface webrtc --role answerer --room myroom
# Person B (offerer)
termface webrtc --role offerer --room myroom --camera --microphone
Keyboard Controls
| Key | Action |
|---|---|
m |
Toggle microphone mute |
v |
Toggle camera on/off |
q |
Quit / leave call |
t |
Open chat (Enter to send, Esc to cancel) |
f |
Send file |
p |
Toggle push-to-talk mode |
1-4 |
Color mode: mono / grayscale / color / invert |
e |
Toggle edge detection |
b |
Toggle background blur |
r |
Toggle recording (connected) / background removal (idle) |
c |
Cycle character set |
+/- |
Adjust brightness |
[/] |
Adjust contrast |
s |
Take screenshot (saves .txt and .png) |
Architecture
┌──────────────────────────────────────────────────┐
│ Terminal UI (TerminalUI + ASCII rendering) │
├──────────────────────────────────────────────────┤
│ WebRTC Layer │
│ ├── AiortcTransport (camera/mic RTP tracks) │
│ ├── MeshSFU (group call relay) │
│ ├── WebSocketSignaling (Cloudflare Worker) │
│ ├── Generation-based reconnect (2.5s delay) │
│ └── Server-assigned roles (offerer/answerer) │
├──────────────────────────────────────────────────┤
│ Media Layer │
│ ├── VideoProcessor (capture → resize → JPEG) │
│ ├── AdaptiveBitrate (AIMD quality control) │
│ ├── AudioSystem (PyAudio + Opus codec) │
│ ├── JitterBuffer (adaptive depth playback) │
│ ├── ASCIIRenderer (color/mono/grayscale) │
│ └── FrameCompressor (zstd compression) │
├──────────────────────────────────────────────────┤
│ Protocol Layer │
│ ├── Frame (binary framing) │
│ ├── Encryptor (XSalsa20-Poly1305) │
│ ├── MediaPacket (sequence numbers) │
│ └── FileTransferManager (cancel/pause/resume) │
├──────────────────────────────────────────────────┤
│ Network Layer │
│ ├── AiortcTransport (WebRTC, default) │
│ ├── TCPMediaServer/Client (TCP fallback) │
│ └── DiscoveryService (STUN + LAN) │
├──────────────────────────────────────────────────┤
│ ICE Configuration │
│ ├── Google STUN servers (free) │
│ ├── OpenRelay TURN servers (free) │
│ └── Cloudflare Worker signaling │
└──────────────────────────────────────────────────┘
Cloudflare Worker Signaling
The signaling server is a Cloudflare Worker with Durable Objects, deployed at:
wss://termface-signaling.termface.workers.dev
Deploy your own
cd deployment
npx wrangler deploy
Endpoints
| Endpoint | Description |
|---|---|
wss://.../ws/:room |
WebSocket signaling for WebRTC |
https://.../room/:room |
Room info (client count, IDs) |
https://.../health |
Health check |
Security
- Encryption enabled by default for all calls
- X25519 key exchange for shared secret derivation
- XSalsa20-Poly1305 authenticated encryption (AEAD)
- Sequence numbers with replay protection
- Key rotation every 256 messages
- Invite tokens with HMAC-SHA256 signatures and room scoping
- Rate limiting — 200 messages per 10s per client on the signaling server
- Message schema validation — only valid WebRTC/chat/file messages are forwarded
- Room capacity limit — max 2 peers per room for direct P2P calls
To disable encryption (not recommended):
termface facetime --no-encrypt
Diagnostics
# Check system requirements
termface doctor
# Update to latest version
termface update
Requirements
- Python 3.10+
- OpenCV (
opencv-python) - NumPy (
numpy) - PyNaCl (
PyNaCl) — for encryption
Optional (included with [webrtc]):
- aiortc — WebRTC transport
- websockets — WebSocket signaling
- PyAudio — audio playback
- opuslib — Opus audio codec
- mss — screen capture
- zstandard — compression
Platform Support
| Platform | Status |
|---|---|
| macOS (Apple Silicon) | Fully supported |
| macOS (Intel) | Fully supported |
| Windows (Python 3.10+) | Fully supported |
| Linux (Python 3.10+) | Fully supported |
License
MIT
Metadata
Release files for TermFace 3.6.10
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| termface-3.6.10.tar.gz | 87.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| termface-3.6.10-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 172.1 kB
Release files / termface-3.6.10.tar.gz
| Download URL | termface-3.6.10.tar.gz |
|---|---|
| Size | 87.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ba06ebf9669419e78a28ecea336bd41be1eed488c14ab7e6ae265221ed4e3419
|
|
BLAKE2b-256 checksum How to use checksums |
65817e45791d8cab62f7b7cf4f8884756c64ee84f6aee971e868c82c15d194e5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / termface-3.6.10-py3-none-any.whl
| Download URL | termface-3.6.10-py3-none-any.whl |
|---|---|
| Size | 84.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
399608bcb309e4bbde786917aff42a37808515f90d7dc8989d312f8cf61680bb
|
|
BLAKE2b-256 checksum How to use checksums |
2cea78eb8853f875d9c9c818d4783312a581cca6fa78092d2edec25cbe769b03
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|