9cast

Building a internet radio with mq(1) and 9front

mq

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.

Setup

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
}

Mixfs

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.

Links

mq(1)