💾 Archived View for posixcafe.org › blogs › 9radio.gem captured on 2022-06-11 at 20:51:27. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2021-12-17)
-=-=-=-=-=-=-
Building a internet radio with mq(1) and 9front
Mq is a filesystem written by kvik, that acts as a small in memory
ring buffer, that can be used for anything, from chat rooms to
tmux like saved shell sessions. It evolved from Mycroftiv's hubfs.
Since a simple internet radio is just really a ring buffer, we
can use this for sending audio to any number of clients.
First get the fs started and posted in /srv.
We will also create our radio stream as well as
making sure the user 'none' can mount it.
; mq -s radio -m /n/radio ; chmod 777 /srv/radio ; touch /n/radio/radio
That's about it, streams can write to /n/radio/radio, and
will be sent to all readers. For my own setup, I send the
audio information in over a network socket(since my audio
files are hosted in UNIX land). This can be setup with
aux/listen1 like so:
; cat /bin/radio/stream #!/bin/rc mount /srv/radio /n/radio audio/mp3enc -r --abr 128 > /n/radio/radio ; aux/listen1 tcp!*!7999 /bin/radio/stream
This will take raw audio (pcm_s16be) over a socket and send
it to mq. For sending audio I just use ffmpeg on a UNIX host
$ ffmpeg -re -i somefile.flac -f s16be - | nc -c chiri 7999
The -re flag will slow ffmpeg down so it writes at the same sample
rate of the source file, useful to not eagerly fill the mq buffer.
From here clients could either read over 9fs(by mounting the mq),
or you could export the stream over tcp or even http.
For my setup I have this exported over http using rc-httpd like so:
# somewhere in /rc/bin/rc-httpd/select-handler if(~ $location /stream.mp3){ echo 'HTTP/1.1 200 OK'^$cr echo 'Content-type: audio/mp3'^$cr echo $cr mount /srv/radio /n/radio exec cat /n/radio/radio }
For a bit of a fun thought experiment, since we're just using files.
We could take advantage of an overlay filesystem to act as a filter.
For this, we'll use mixfs(1) to mix multiple single streams together.
; mq -s radio -m /n/radio ; touch /n/radio/audio ; bind /n/radio/audio /dev/audio ; audio/mixfs -s mixer -m /mnt/mix
Now we could modify our /bin/radio/stream to bind our mixer
and send audio to mixfs instead of directly to mq, mixfs will
take care of mixing the multiple streams together and send the result
to mq's audio file. Since mixfs expects PCM audio, some tweaks
will have to be made to not encode on the way in(from a stream) and to
instead encode on the way out(to a client).
Also as it currently stands, this doesn't produce anything useful. Mixfs
is a tad slow and does not allow for gain to be set for each stream, but
I think this serves as an interesting proof of concept.