Stream audio from a PulseAudio source to HTTP (MP3)
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

This is a daemon and companion website to stream audio. I use it to stream from my system's audio to an <audio> element. It outputs MP3 audio.

I thought it would be fun to be able to share what I am playing on my local media player on a simple website. I wanted to take the audio directly from PulseAudio and make it available in an <audio> element.

To do this, I've written a C library to read/decode audio from PulseAudio and then encode/write it out as MP3. I use the library in Go with cgo.

Essentially this gives me a simple daemon I can start that will livestream my system's audio.


  • ffmpeg (libavcodec, libavformat, libavdevice, libavutil, libswresample). I developed using 3.2.2. On Debian this is in the package libavutil-dev.
  • C compiler. I developed using gcc 6.2.1.
  • Go. I developed using 1.7.3.
  • The track display feature depends on accessing a song_tracker API. This is optional however.


  • go get
  • go build
  • Place index.html somewhere accessible. Update the song_tracker_url and the <audio> element src attribute. If you don't want to use the song tracker, then set song_tracker_url to a blank string.
  • Run the daemon. Its usage output shows the possible flags. There is no configuration file.


  • audiostreamer: A Go daemon that serves HTTP requests to stream audio as MP3.
  • audiostreamer.h: A library that uses ffmpeg to read/decode from PulseAudio and encode/write to MP3.
  • index.html: A website containing an <audio> element that lets us stream audio from the daemon. It also displays the currently playing track (by polling a song_tracker API). In the case of daemon restart, clients try to reconnect endlessly.
  • transcode_example: A sample C program that uses audiostreamer.h to transcode to a file.


  • In general MP3 is not a streamable format. To make it possible to slice and start streaming from anywhere (if an encode is already in progress), I disable the MP3 bit reservoir. This means I can have just one encoded stream for any number of streaming clients.
  • In theory output can be any audio format/codec. In a few places I have hardcoded use of MP3. To switch to a different output format/codec, it is likely sufficient to change the outputFormat and outputEncoder in encoder(), and adjust the Content-Type in audioRequest(). You must make sure the format/codec is streamable and that it is valid to send audio frames starting from any point, as that is the current behaviour.
  • In theory input can be from a file. In fact this does work, for a given value of work. Right now the daemon decodes as quickly as it can. When taken from a PulseAudio input the daemon is throttled as the audio is real time. From a file however there is no such limit, and it will consume 100% CPU (one thread). As well, it decodes the same file over and over. As my main use case is to stream from PulseAudio I have chosen to leave this as is as adjusting it introduces complexity.