A while back we created the audio block as a way of simplifying the work needed to write applications that dealt with audio on embedded devices. balenaSound is the biggest demonstration of what’s possible with it but it’s a tad bit complicated for newcomers to understand everything that’s happening under the hood. So I set out to create a sample project that would serve this purpose.
I thought capturing audio with a microphone and streaming it somewhere was about the easiest thing I could build that was not boring, playing a wav file is not very exciting right? Of course I got carried away with the project and before I knew it I was sketching a case for a Pi Zero on 3D CAD software but oh well… from the software side of things the project was simple enough that I had enough room to experiment a bit and get something else out of it.
These are the requirements I came up with:
- Needs to capture audio and stream it over the internet so you can listen in remotely (hello public URL). This means the device could be used as a “spybug” to eavesdrop conversations but also has some less nefarious uses such as monitoring a sleeping baby.
- Needs to be small and portable, no cables allowed! Batteries? Yes please.
- It’s been brought to my attention that I don’t give the Pi Zero enough love, so naturally I wanted to fix that… Lies, I wanted to use a Nano Pi Air board because they are cool, but ran into some problems which felt a bit out of scope for this time so I had no choice (sorry @chrisys).
Here is all the stuff we need:
- Raspberry Pi Zero W. We need WiFi and we probably don’t want the GPIO header soldered to keep a minimal footprint.
- A USB microphone. I went with the cheapest I could find because it was also the smallest, we can always spend more for better audio quality! Here is the one I bought.
- A USB female connector breakout board. We won’t be using the Pi Zero’s micro usb port as we would need a bulky USB micro to type A adapter and space is a premium for this build.
- We also need a battery and some way of charging it. Of course I went over the top and got a Powerboost 1000C charger from Adafruit. There are a lot of cheaper alternatives and you don’t necessarily need to have an on-device charger but hey I never said this was a frugal build.
- An on/off switch to shutdown the device.
- A case of some sort to fit all these components. More about this later!
The audio block readme reads: “Provides an easy way to work with audio applications in a containerized environment”. So unless we messed up this audio block thing this should be pretty straight forward. With two or three lines of configuration we can grab audio from the microphone and pipe it into the audio jack for testing purposes. Make sure you use headphones and not a speaker for testing otherwise you’ll create an audio feedback loop which probably won’t be to pleasant to listen to.
Now we need to stream the audio we captured over http. There are many options here: gstreamer, VLC, PulseAudio itself, MPD, raspicast, omxplayer… I tried some and eventually settled with Icecast + Darkice combo. What I liked about it is that you get a M3U/XSPF audio stream which is easily played back by most audio software. What I didn’t like about it is the high latency that this solution has. Icecast is purposely built so that clients get a smooth playback experience without re-buffering audio, so this unfortunately means there is a large delay built into the system. In my case it turned out to be about 10 seconds, though if left running for long periods of time it would slowly increase (Pi Zero ).
I’m not super thrilled about this delay but for now it should be enough. If you have suggestions on how to reduce it or better ideas let me know, I didn’t spend much time checking all the alternatives so I’m pretty sure we can do better! Eventually I’d like to build the audio streamer myself by grabbing the audio directly from the audio block and creating my own server, but that’s a fun project for another day!
The entire source code for the project can be found here, as you can see it’s a really simple project with little to no coding so I’m quite happy the audio block lived up to its mission.
Next time I’ll talk about the hardware integration, the case I built and how the project took an interesting spin!