I’ve been running a live audio pipeline on Livepeer BYOC for the last week, and it’s at the point where another Orchestrator could run the capability.
The shape: a publisher (a phone, or a box) sends live audio to an Orchestrator; the capability there transcribes it with whisper and pushes [ the audio, the captions and the playlists ] into Swarm; listeners play it in a browser straight out of Swarm via an in-browser node, captions and all. The Orchestrator is paid per second in PM tickets. Nobody in the middle holds the publisher’s key.
In one picture
Black arrows carry media; red dashed arrows carry the publisher’s signatures. The publisher is the only box with a key. The Orchestrator carries; Swarm stores; the browser is its own Swarm node.
Where to look first
Two things to try before reading any further:
-
Listen. Open https://chrisradio.eth.limo/ in Brave or Chrome. That page is a weeb-3 build (GitHub - lat-murmeldjur/weeb-3: Weebery · GitHub) served out of Swarm behind an ENS name: the browser joins Swarm as a light node in WASM, follows the station’s pointer feed to the current broadcast, reads the playlists and the chunks itself, and hls.js plays them with captions in sync. No gateway, no CDN, no server of mine anywhere in the path — when the phone is on air, that is the phone talking to an Orchestrator and nothing else. weeb-3 is what makes the listener side of this real; without it “on Swarm” still means “behind somebody’s gateway”.
-
Publish. The Android app (Radicle Explorer) is the publisher: microphone in, ten-second segments out to an Orchestrator running donkey-push, tickets, stamps and feed updates all signed on the phone with the publisher’s own key. Point it at your Orchestrator and the audio comes out of the page above.
Why “donkey”
A donkey carries what it’s given and owns none of it. You pay it for the carrying. That’s the whole contract of this capability: it carries chunks to Swarm on the publisher’s stamps, and it cannot write anything on its own account. It’s the Swarm donkey, not the Trojan horse: it helps you distribute the value, and nobody jumps out and kills everyone.
Segments and chunks are different things
The publisher cuts the audio into HLS segments, ten seconds each, and sends those to the Orchestrator. The capability splits each segment into 4 KB Swarm chunks (a ten-second segment is about 25 of them), asks the publisher over the session to stamp each chunk, and pushes them. The publisher then signs the updated playlist as a Swarm feed update. So the Orchestrator sees segments; Swarm sees chunks; the publisher signs both the stamps and the playlists.
What the Operator runs
One container, podman pull registry.hobcroft.org/donkey-push:0.2.0 (the registry itself is served from Swarm), registered with go-livepeer as a static live runner via -liveRunnerConfig runners.json. It listens on loopback; the publisher only ever talks to your Orchestrator. Price is yours to set, per hour of audio. You need -ticketEV raised — at the stock 8 gwei a session can’t be funded, since clients cap at 100 tickets per payment. The README with the exact steps is in the spine repo: Radicle Explorer (capability/README.md).
One caveat, tracked in go-livepeer #4077 (Remote signer: live session pays once and is then released for insufficient balance · Issue #4077 · livepeer/go-livepeer · GitHub): the stock Orchestrator releases every live session on a single missed 3-second health poll, and a container answering a few hundred milliseconds late is enough to trigger it. A one-file patch that waits for three consecutive misses is at GitHub - chrishobcroft/go-livepeer at health-poll-threshold · GitHub; my Orchestrator runs it.
What the capability does not hold
No postage batch, no BZZ, no chequebook, no key of the publisher’s — and no chain access at all: no Gnosis endpoint, no Arbitrum endpoint. The only process on the Operator’s box that touches a chain is go-livepeer itself, for the tickets. Every chunk the capability pushes carries a stamp the publisher signed during the session, and every playlist it pushes is a feed update the publisher signed. If the container disappears mid-stream, the publisher reconnects to a fresh session and carries on.
Captions
faster-whisper tiny.en (int8, two threads): about 4.5x realtime on a 2 vCPU VPS, which is what my Orchestrator is. base.en is baked in too and is one environment variable away. Larger models aren’t in this image — it’s deliberately offline for HuggingFace, since a network-reachable model load measured 1080 seconds — so small, medium or large-v3 mean a rebuilt image with the weights baked. An Operator with a GPU could absolutely offer that (large-v3 runs at 16x realtime on a 4060 Ti), advertised in runners.json at its own price; that’s a build target, not something that exists today.
What the publisher runs
Either a Python publisher on a box — built on Josh’s livepeer-python-gateway (GitHub - j0sh/livepeer-python-gateway: Python Livepeer Gateway SDK · GitHub), which is where the live-runner client protocol lives — or an Android app (API 21+, no native code) that speaks the same protocol in Kotlin. The app holds the publisher’s key — you import your existing gateway keystore file — and signs the PM tickets and the Swarm stamps and feed updates on the phone. Payments are plain HTTP against the Orchestrator’s 402 challenge: no gRPC, no remote signer. Code: Radicle Explorer. The Swarm side needs a postage volume owned by the same key — BZZ on Gnosis, one transaction through the volume registry (GitHub - shtukaresearch/swarm-volume-registry: Onchain volume lifecycle management for Swarm · GitHub). That’s the one genuinely new thing for a Livepeer person, and it’s also the point: the publisher’s key pays for both the transport and the storage.
Where it stands
Publishing from a box has run for days at a time on my Orchestrator (sessions of 5h19m, 13h30m and 30h21m; captions in sync in Brave throughout). Publishing from a Pixel 8 passed a decoy-gated listening test on 14 Sep. Capacity is one broadcast per runner at the moment. Audio only, by design.
If you’d like to try it: run the capability, tell me the Orchestrator, and I’ll publish into it from the phone before you set up a key of your own.
