Video calls in your terminal. Places and receives WebRTC calls and renders the remote video as ANSI half-block art — no browser needed. Works peer-to-peer with other video-term instances (e.g. a Raspberry Pi home camera) or any client speaking the same signaling protocol.
┌──────────────┐ websocket ┌───────────────────┐ websocket ┌──────────────┐
│ video-term │◄──signaling───►│ signaling server │◄──signaling──►│ video-term │
│ (terminal) │ └───────────────────┘ │ (home camera)│
│ │◄════════════ WebRTC (H264/Opus over SRTP) ════════►│ │
└──────────────┘ └──────────────┘
| Menu | Enter peer ID | Dialing |
|---|---|---|
![]() |
![]() |
![]() |
Remote video rendered in the terminal during a call:
Prebuilt binaries of the latest release (version shown in the release badge above):
| Platform | Download |
|---|---|
| macOS Apple Silicon | video-term-darwin-arm64 |
| macOS Intel | video-term-darwin-amd64 |
| Windows amd64 | video-term-windows-amd64.exe |
| Linux amd64 | video-term-linux-amd64 |
| Linux arm64 (RPi) | video-term-linux-arm64 |
GStreamer (below) is required at runtime on every platform.
- Go 1.24+
- GStreamer (
gst-launch-1.0on PATH)- macOS:
brew install gstreamer - Debian/RPi:
apt install gstreamer1.0-tools gstreamer1.0-plugins-{base,good,bad} gstreamer1.0-libav
- macOS:
cp .env.example .env # then fill in your signaling server
make buildInteractive TUI (default):
./build/video-term-$(go env GOOS)-$(go env GOARCH)- The menu shows the peer ID assigned by the signaling server.
- Call a peer: enter the remote peer's ID; video appears once connected.
- Incoming calls ring in the TUI —
ato accept,rto reject. - In a call:
hhangs up. Logs go toLOG_FILE(defaultvideo-term.log).
Headless home-camera mode (auto-answers every incoming call):
./build/video-term-linux-arm64 -headless| Package | Responsibility |
|---|---|
config |
.env + environment loading |
signaling |
message protocol and client interface |
signalws |
websocket implementation of the signaling client |
peer |
Engine (signaling routing, call lifecycle) and Session (one call) |
media |
GStreamer capture/decode/playback pipelines, RTP pumps, ANSI renderer |
ui |
Bubbletea terminal interface |
Media flows through local UDP sockets: GStreamer captures the camera/mic and sends RTP to localhost, where pumps forward it into pion tracks; incoming tracks are forwarded the same way to a GStreamer decode pipeline whose raw RGB output is rendered as ANSI in the terminal.
Default pipelines use avfvideosrc/vtenc_h264/osxaudiosrc on macOS and
libcamerasrc/x264enc/alsasrc on Linux; override with
GST_VIDEO_PIPELINE / GST_AUDIO_PIPELINE (see .env.example).



