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.
Landing
|
Admin dashboard
|
AutoDJ
|
Developer portal
|
Video stream player |
|
| 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 |
| 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. Credentials are generated on first run, 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.
On first start TinyIce prints generated credentials once — save them:
FIRST RUN: SECURE CREDENTIALS GENERATED
Admin Password: Oy9…
Default Source Password: Rm3…
Live Mount Password: 8fX…
Then open http://localhost:8000 (and /admin to log in as 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 Preact + @preact/signals + Vite in server/frontend/src/; 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





