The pipeline
screen → encode → packets → relay → decode → screen
Drops beat stalls
If a packet goes missing you lose one frame, which you won't notice. You never get a spinner or a stream that quietly falls behind. The frames that matter most travel on a guaranteed channel.
The server never touches the video
It copies packets, nothing more — no re-encoding. It keeps the last full frame handy, so anyone who joins late sees a picture right away.
Why not WebRTC?
A deliberate choice. Building lower down means owning the whole path instead of inheriting a heavy stack, and it was a real chance to use newer browser APIs. The trade-offs are written down in the docs.
The viewer decides what to trade
Speed and reliability pull against each other, and the right answer depends on the connection you're on. So it isn't baked in: every viewer picks, from the player's own settings, and can switch mid-stream.
Live edge
Stay as close to now as the network allows. Anything that arrives late is skipped rather than waited for. Best on a good connection, and the default.
Deep buffer
Sit a little further back and let the server re-send whatever went missing. You give up some latency and get a picture that holds together on flaky Wi-Fi or mobile.
Both modes are one control in the player, not a deployment setting. In between there are opt-ins that buy a bit of resilience for almost no delay — extra recovery data sent alongside the video, and the stream spread over several connections so one bad path can't take the picture down.
Any server, any viewer
Viewers land on whichever server is free. If that one isn't hosting the broadcast, it fetches the stream from the one that is. Add servers and the audience grows with them — hundreds of broadcasts at once, and around a thousand people on one popular stream.
How fast is it, really
From the broadcaster's screen to the viewer's, measured on machines where the graphics card does the video work. The target is anything under 500 ms. If either end falls back to doing it in software it gets much slower — we've seen up to 2.5 seconds. That's what decides the number, more than the network.
Both ends sync their clocks over the connection, so this is measured rather than estimated. How it was measured is written up in the docs.
All three numbers are our own measurements. We haven't put gawk up against other streaming stacks, so there's no comparison here.
Run it
gawk.ioio.fi runs exactly this. The repository has everything you need to stand up your own.
$ git clone https://github.com/Tuhis/gawk && cd gawk $ docker compose up
Open localhost:8080/#/broadcast, pick a screen, and you get a 6-character code. Open the join link in a second tab and it connects. No browser flags to set, and the code still works after a restart. You need Docker and a Chromium browser.
$ helm upgrade --install gawk-server \ oci://ghcr.io/tuhis/charts/gawk-server \ --version <X.Y.Z> -n gawk -f relay-values.yaml $ helm upgrade --install gawk-app \ oci://ghcr.io/tuhis/charts/gawk-app \ --version <X.Y.Z> -n gawk -f app-values.yaml
Two charts, two images, versions always in step. Read the self-hosting guide first: your DNS and certificates decide whether it works at all, because this is fussier about them than a normal website. The compose stack above is for trying things out, not for production.
Get the app
Broadcasting doesn't have to happen in a browser tab. The native apps use your graphics card directly, can share one window along with just that app's audio, and on Linux they're the only way to broadcast with hardware encoding. Viewers still need nothing but a browser.
Linux
x86-64 · tar.gzLatest release
Download for LinuxUbuntu 24.04+ or Debian 13+: sudo apt install ./gawk-broadcast_*_amd64.deb brings the packages it needs, the launcher entry and the icon. If you used the tarball's install-desktop.sh before, run it with --uninstall first.
The tarball, for other distributions: unpack it and run gawk-broadcast-linux; install-desktop.sh adds it to your launcher. Needs Ubuntu 24.04 or newer (or equivalent) and a hardware H.264 encoder; tested on KDE Plasma (Wayland). The INSTALL.md inside lists the packages.
sha256
Linux
x86-64 · tar.gzLatest release
Download for LinuxUnpack it and run gawk-broadcast-gui. Needs glibc 2.34 or newer, a Wayland session and a hardware H.264 encoder; the INSTALL.md inside has the checklist and the list of shared libraries.
sha256
Windows
x86-64 · portable .exeLatest release
Download for WindowsOne file, nothing to install. It's unsigned, so SmartScreen will object the first time: More info → Run anyway, or untick Unblock in the file's properties. Needs Windows 10 or newer and a hardware H.264 encoder.
sha256
macOS
Apple silicon · .app in a .zipLatest release
Download for MacUnzip it and open gawk-broadcast-macos; drag it to Applications first if you like. It's signed and notarized, so it opens without a warning, and it picks what to share through macOS's own picker. Needs macOS 14 or newer on Apple silicon.
sha256
The Linux and Windows binaries aren't signed, so for them the checksum is the only integrity check you get; the Mac app is signed and notarized by Apple. Each release also ships a SHA256SUMS file: sha256sum -c SHA256SUMS on Linux, Get-FileHash on Windows, shasum -a 256 -c SHA256SUMS on a Mac. Older versions and release notes are on the releases page.
Hosting a LAN party? The experimental party relay keeps the party's streams off the venue's internet line.
Browser support
Chromium first, and if a browser can't join, the app says so on load instead of failing quietly.
Broadcasting doesn't have to happen in a browser at all: the native apps for Linux and Windows get more out of your graphics card, and on Linux they're the way to broadcast, since browsers can't use the graphics card to encode there. The design notes explain why.
Also in the box
Sound
Your whole system's audio, or just one app's, kept in step with the picture.
Holds up on bad Wi-Fi
Extra recovery data, a re-send buffer on the server, and the option to spread the stream over several connections.
Diagnostics
Per-session stats and a dashboard, for when you need to know why a stream misbehaved.
Moderation
Kill a broadcast across every server, and ban by an ID or an IP address.
Metrics
Prometheus metrics on a private port, plus a stats overlay on both ends you can copy in one click.
Tested in a real browser
Every change runs a headless Chrome that actually decodes relayed video, plus a two-server cluster test.
Every decision is written down
For each piece of work there's a document: what was decided, what was rejected, and why. Start with how a frame gets from one screen to another.
It's also the fastest way to bring an AI up to speed — the whole design is spelled out in prose, which is far easier to absorb than reading the code.