One binary. Audio and video. Scales to six figures of listeners.
Icecast-compatible streaming server with RTMP/SRT/WebRTC ingest, pure-Go audio transcoding, HLS audio+video output, an AutoDJ with MPD remote control, and a built-in admin SPA. Deploy anywhere in seconds.
Dark and light themes, phone layouts for every page.
| Ingest | Icecast2 SOURCE/PUT · RTMP (H.264 + AAC/MP3) · SRT MPEG-TS · WebRTC browser broadcasting · Icecast relay pull |
| Output | Icecast passthrough · HLS audio · HLS audio + video · WHEP / WebRTC playback · OBS simulcast (master playlist) · embeddable player |
| Codecs | MP3 · Ogg Opus · Ogg Vorbis · FLAC / FLAC-in-Ogg · WAV (8/16/24/32-bit & float) · H.264 · AAC-LC |
| Transcoder | Pure-Go multi-codec decode → MP3 or Opus with automatic resampling. No FFmpeg dependency. |
| AutoDJ | Multi-instance, keyframe-accurate pacing, shuffle/loop/queue, MPD protocol per instance, external track hooks |
| Auth | Username + bcrypt · Passkeys (WebAuthn) · OIDC/OAuth2 · Bearer API tokens · per-mount source passwords |
| Player | 16:9 video layout · live poster thumbnails · stats overlay (codec/res/fps/GOP/bitrate, dropped frames, buffer, latency) · 60 s DVR seek |
| Admin UI | Dark and light console UI · command palette (Ctrl/Cmd+K) · guided first-run setup · browser broadcasting with level meters and limiter · live audience map · phone layouts |
| Ops | Prometheus metrics · structured logging · ACME auto-HTTPS · zero-downtime hot-swap · multi-arch Docker on GHCR |
| Deploy | One static Go binary (~25 MB), all assets embedded · multi-arch Docker image · .deb / .rpm packages |
- One binary, no runtime dependencies. Pure-Go SQLite, pure-Go audio decode/encode, embedded frontend — no FFmpeg, no GCC, no separate database. Cross-compiles to Linux, macOS, Windows, and FreeBSD.
- Faces the internet directly. Built-in ACME (Let's Encrypt) terminates TLS, and the shared circular-buffer broadcast path serves large listener counts from a single process. Run it straight on 80/443 — no reverse proxy required.
- Icecast-compatible, not Icecast-bound. Existing encoders and players keep working; HLS and WebRTC are layered on top for modern clients.
- Secure defaults. A token-protected first-run wizard creates the admin account and generates the source passwords (shown once), mutating admin actions are CSRF-protected, outbound webhook/relay URLs are SSRF-guarded, and the packaged systemd unit ships masked so an unconfigured daemon can't auto-start.
# Released binary
curl -LJO "https://github.com/DatanoiseTV/tinyice/releases/latest/download/tinyice-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m)"
chmod +x tinyice-* && mv tinyice-* tinyice && ./tinyice
# Or Docker — multi-arch images on GHCR (linux/amd64, linux/arm64)
# The image listens on 8080 and reads /data/config.json; reach it on :8000
docker run --rm -p 8000:8080 -v tinyice-data:/data ghcr.io/datanoisetv/tinyice:latest
# Or from source — Go 1.25+, Node 20+
git clone https://github.com/DatanoiseTV/tinyice.git && cd tinyice && make build.deb / .rpm packages are attached to every release. Full matrix and options:
Installation.
With no config file, TinyIce starts in setup mode and prints a one-time token:
FIRST RUN: SETUP MODE
Open your browser and navigate to:
http://localhost:8000/setup
Setup Token: 3f9a…
Open /setup and paste the token (with Docker, find it in docker logs <container>).
The wizard asks, in plain language, for your station name and tagline, the
address listeners will use, an accent colour (with a live preview and contrast
check), the expected audience (sets the listener limit per stream), the first
mount, and the admin account. Everything is applied in one step and nothing is
stored if an answer is invalid. Prefer defaults? Choose Quick setup: token
and admin account only.
The last screen shows the generated source passwords once, with ready-to-paste encoder settings for your mount. Then sign in at /admin.
| Source | How |
|---|---|
| BUTT / Mixxx / LadioCast | Icecast 2 · server host:8000 · mount /live · password = Live Mount Password |
| OBS | See below |
| FFmpeg | ffmpeg -re -i input.mp3 -f mp3 -content_type audio/mpeg icecast://source:<pw>@host:8000/live |
| SRT | srt://host:9000?streamid=#!::r=live,m=publish,key=<pw> from OBS, ffmpeg, or a DVB mux |
| Browser | Admin → Go Live for WebRTC mic/line broadcasting |
| Files | Configure an AutoDJ pointed at a directory of audio files |
More ingest detail: Streaming Sources.
TinyIce accepts H.264 + AAC (or H.264 + MP3) over RTMP and produces HLS
audio + video at /<mount>/playlist.m3u8.
- Enable RTMP in
tinyice.json:"ingest": { "rtmp_enabled": true, "rtmp_port": "1935" }
- Create a mount in Admin → Streams → Add Mount. The password is your OBS Stream Key.
- OBS → Settings → Stream (Service: Custom): Server
rtmp://<host>/<mount>(e.g.rtmp://radio.example.com/live), Stream Key = the mount's source password. - OBS → Settings → Output: video
x264(or hardware H.264), audioAACorMP3, 1 s keyframe interval (matches the default segment size for lowest latency). - Start Streaming. The log shows
RTMP: Publishing startedandParsed AVC config. - Watch it:
- Browser player
https://<host>/player/<mount>— 16:9 layout, STATS overlay (codec/res/fps/GOP/bitrate, dropped frames, buffer, latency), live viewer count. - Direct HLS
https://<host>/<mount>/playlist.m3u8— VLC, mpv, ffplay, Safari, iOS. - WebRTC (sub-second, opt-in) — append
?webrtc=1to the player URL; requires a B-frame-free encoder (bf=0).
- Browser player
Full pipeline notes, ABR/simulcast, and WHEP: Playback and Output.
The complete operator and developer reference lives in the Wiki.
| Getting started | Streaming | Operations |
|---|---|---|
| Quick Start | Streaming Sources | Authentication & Users |
| Installation | Playback & Output | Security |
| Configuration | AutoDJ | Deployment |
| Command Line & Signals | Transcoding | Observability |
| Troubleshooting & FAQ | Webhooks · HTTP API | Architecture · Developing |
Interactive API docs are served by every instance at /api/docs (Swagger UI),
with the OpenAPI spec at /api/openapi.yaml.
TinyIce is a single static binary with the admin UI, player, and assets embedded.
- Direct / ACME: enable
auto_https, list yourdomains, and run on 80/443. TinyIce obtains and renews Let's Encrypt certificates itself. A reverse proxy is optional, not required. - Docker: multi-arch images on GHCR —
:latest,:beta,:vX.Y.Z,:X.Y,:X. - Packages:
.deb/.rpminstall a hardened systemd unit, a dedicatedtinyiceuser, and/etc/tinyice+/var/lib/tinyice. The unit ships masked by design — unmask, thenenable --now. - Zero-downtime: hot-swap the binary (
SO_REUSEPORT) or reload config withSIGHUP. There is no in-process self-updater — update by replacing the binary, pulling a new image, orapt/dnf upgrade.
Sizing, reverse-proxy notes, and ACME details: Deployment.
Requires Go 1.25+ and Node.js 20+.
make build # frontend + Go binary
make generate # frontend only (go generate ./server/...)
make quick # Go-only (reuse existing dist/)
make dev # Vite frontend dev server (hot reload)Frontend is React 19 + Tailwind 4 + Radix primitives + Vite in
server/frontend/src/, with its own icon set and widgets. make dev serves it
at http://localhost:5199 against built-in fixtures (no server or login needed;
MOCK=0 make dev proxies to a real server on :8000). The design rules are in
server/frontend/DESIGN.md. All dist assets are embedded into the Go binary via
go:embed, so the released binary is self-contained. See
Developing and
Architecture.
Apache License 2.0 — see LICENSE. Security policy and disclosure:
SECURITY.md.
Built by DatanoiseTV · Wiki · file a bug









