Live-stream ascii terminal
April 06, 2026
Live-streaming a _picture_ of your terminal (via e.g. twitch.tv) is cool and all, but what if we sent the actual text instead??
That’s what the latest version of asciinema does, approximately.
They’ve added a “live streaming” version, and the ability to embed an audio URI.
The Setup
So that all sounds great. Indeed, when using asciinema stream --remote a new livestream apprears in my account, and it looks great.
The “hard part” is that “audio stream”.
What we need is:
- something that can broadcast to anyone watching the livestream (on asciinema.org)
- can be embedded (I think just in an
<audio>tag) - needs to have TLS (because asciinema.org does, and browsers don’t like mixed content)
- …
- profit!
Icecast2!
The fantastic and long-lived Xiph / Vorbis project has a thing called Icecast2, generally for “Internet radio”.
This seems like just the thing to broadcast audio.
Following the basic setup documentation is straightforward enough. I installed this on a Digital Ocean VPS running latest Debian, which has packages for most of these things.
In short order, I was able to get a thing working. ices2 or butt for the client worked decently.
However, we need TLS!
This proves to be a bit of a “hard” part. So we sign up “baltica.meejah.ca” for Let’s Encrypt, get a certificate, and follow more of the tutorial.
This does enable TLS properly, and I can use Firefox to browse the Icecast server. However, the streaming clients seem a bit more prickly about encrypting things.
Pipelines and OSS and WirePlumber and ALSA
So, Linux audio generally gets crapped upon regularly.
(insert XKCD? there _is_ at least one XKCD I assume??)
These days, it seems that “PipeWire” is the latest hotness, or at least that’s what my Debian Trixie install comes with. Generally, this works well for me for screen-sharing, and pair-programming (we use ShWiM generally).
However, some of the Icecast tools are fairly old, and there’s lots of mention of “OSS” and “ALSA”. These tools also still exist, and WirePlumber (or whatever actually controls this) alleges to play nicely.
So the trick is to get something that can get input from my microphone, AND encode Ogg audio, AND stream that to HTTPS endpoints.
One Cool Trick
Before it gets buried too far, the secret sauce for the shout client for Icecast2 is --tls-mode rfc2818
The Final Pipeline
Okay, this is by no means final.
But what I have that mostly works right now is this monster:
ffmpeg -f alsa -sample_rate 44100 -i hw:4 -f wav -c:a pcm_u8 - | oggenc --bitrate 96 --managed --raw --raw-bits 8 - | shout --tls-mode "rfc2818" --host baltica.meejah.ca --port 8443 --user source --pass seekrit --format ogg --mount "/live.ogg"
Lets break that down a bit, into three parts:
ffmpeggrabs raw audio samples from a microphoneoggencencodes those raw samples into a Ogg streamshoutstreams the Ogg to the Icecast2 server (encrypted via TLS)
Thanks to phschafft in the #icecast channel (on Libera) for some assists with, especially, the TLS options on shout.
So starting backwards, we use “shout” to stream this audio via “https://baltica.meejah.ca:8443/live.ogg” (using several of the options). The --format ogg is NOT about transcoding or anything, it tells “shout” what the incoming stream is encoded using. You must use --tls-mode rfc2818 to get TLS to work.
The “middle” piece is somewhat straightforward (even if I barely understand most of the options): we tell oggenc to take the incoming raw 8-bit samples and produce a 96KiB-per-second (average) output OGG stream.
The ffmpeg part tells it to use device -i hw:4 (hopefully my wireless mic) via the ALSA libraries (-f alsa), sample at voice rates (44.1KHz) and output raw WAV (-f wav) as 8-bit unsigned samples (-c:a pcm_u8).
Some Improvements?
Okay, so this “works”. I don’t love it yet.
Some of the problems:
- Why not just
ffmpeg? It can stream to Icecast2, it can ogg-encode .. I haven’t found the magic that makes it work with my setup (TLS issues, probably?) - The “butt” streaming GUI tool doesn’t work with TLS (it might be more convenient)
- I sometimes get a “error muxing packet” from some part of the pipeline, which completely kills the audio
- Starting the audio back up doesn’t sync the same
The most reliable way I have for the audio so far is to start both the audio and the asciinema livestream at the same time, and set the delay to 7 seconds. I found this experimentally: play your own livestream and then start counting. When you hear “one” the delay needs to be whatever the last number you said is.
More Ideal Setup
Fixing the audio is probably number one. Having a reliable way to stream (and pause, stop and re-start) audio is key.
I’d like to understand more about what’s going on with the “raw -> encoded -> stream -> client -> player” setup here. Can we get less than 7 seconds of delay? (Do we even care?) What are better settings to use – maybe Speex or Opus codec (it’s just talking, right?) etc?
It would be ideal to have a text-only version of “live chat”. This could be as simple as “use a vanity-channel on Libera” – probably makes sense, given the “target audience” here are people who find “streaming real ASCII is way cooler than pictures on Twitch” ;)
Further Thoughts?
Let me know what you think: see this Mastodon thread to leave your feedback.
txtorcon
carml
cuv’ner