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.7.1
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.7.1.tar.gz | 91.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| termface-3.7.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 179.7 kB
Release files / termface-3.7.1.tar.gz
| Download URL | termface-3.7.1.tar.gz |
|---|---|
| Size | 91.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
787aa022f0aee658c27cf86145f97a18d5066f48deebe0be7aaa3f7e2e6cafb3
|
|
BLAKE2b-256 checksum How to use checksums |
cf90ad9a8e21518f4ef57c283d3301f7dccbefd91d21d5037689c546ebf92920
|
| 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.7.1-py3-none-any.whl
| Download URL | termface-3.7.1-py3-none-any.whl |
|---|---|
| Size | 88.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2c705186d55609f4da89da844055dafdf010a0ea9beeb7bc945ffddd9e784dba
|
|
BLAKE2b-256 checksum How to use checksums |
3beb944e3e6fed88501a062b5a5e50290eae06a69c81ea48b286cd76d20a321a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|