Intro: Add Aux to Sonos Using Raspberry Pi
I have always been fascinated by the Raspberry Pi but never had a real need for one until now. We have three Sonos components in our house: A Play 5 in the living room, a Play 3 in the bedroom and a Sonos CONNECT:AMP powering outdoor speakers on our patio. With them we can listen to practically anything except our local radio station which doesn't stream over the Internet. I have a tabletop radio upstairs in my office that has a line-out and wanted to be able to listen to it throughout the house mainly for live sports broadcasts. I could have accomplished this by buying another Play 5 or CONNECT and use their line-in but I didn't have enough room in my little office nor did I want to invest that much more money just to have that capability. I decided to learn how to program a Raspberry Pi to add a remote line-in for our Sonos speakers. I wrote this Instructable for the complete Raspberry Pi NOOB, which I was until just a few days ago, with what I feel is the most concise, least amount of steps necessary to have a Raspberry Pi automatically start serving a live 320 kbps stereo mp3 stream to Sonos within seconds of booting up. This is also the perfect way to listen to your turntable throughout the house on Sonos.
What you will need:
A desktop or laptop computer with a microSD card reader
Monitor or TV with HDMI input (for initial setup only)
USB or bluetooth keyboard and mouse (for initial setup only)
BEHRINGER U-CONTROL UCA202 External USB Soundcard (has stereo RCA inputs)
UPDATE: If you own a turntable with USB out you may be able to just plug that into the Pi and use that as the "soundcard" and forego buying the Behringer altogether.
EDIT: I wasn't aware that Behringer has another model for the same price called the BEHRINGER U-PHONO UFO202 that has a built-in Phono preamp for turntables.
The Raspberry Pi's on-board sound card does not have audio inputs and there are very few external USB sound cards that have stereo inputs. My second choice was a stereo sound card "hat" that plugs into the Raspberry's GPIO pins but I couldn't find a case for it and I really liked the look and functionality of the Flirc Raspberry Pi case.
Flirc Raspberry Pi Case Gen2 (New Model) (aluminum case acts as a heat sink)
Mediabridge 3.5mm Male to 2-Male RCA Adapter (6 Feet) (if your analog audio source has RCA outputs then you don't need this)
Navigate to https://www.raspberrypi.org/downloads/noobs on your regular computer and download NOOBS_v2_4_4.zip. It is a rather large file (~1.4 GB). Extract the contents of the zip file to your microSD card. I found it was faster writing to my SD card by first extracting the files to a temporary folder and then copying them to the card rather than extracting directly to the card.
Insert the microSD card with the extracted files into the SD card slot on the underside of the Raspberry Pi. Connect an HDMI cable from the Raspberry Pi to your monitor or TV. Connect the USB keyboard, mouse, ethernet cable (or you can configure Wi-Fi later), USB soundcard (the Behringer card doesn't require any additional software or drivers) and finally the Micro USB power cable.
The Pi will boot up to the operating system installation screen. Select only Raspbian and click Install. It will take a while to install. During my installation a little lightning bolt icon would appear intermittently at the top right of the screen. Online research revealed that if the Pi is accessing the microSD card a lot or otherwise working hard (and powering an external USB sound card in our case) and you are powering it using a USB cable plugged into a computer (not a dedicated USB power supply) you may see that icon which indicates a little undervoltage. It's perfectly normal and shouldn't affect anything. After the OS finishes installing you will get a confirmation dialog box. Click OK and the Pi will reboot.
After it reboots the Raspbian desktop will appear. The first thing we need to do is set a root password. Click the terminal icon on the upper left of the screen and type in "sudo passwd root" (without the quotes) and hit enter. Type in "raspberry" (without the quotes) as the password, hit enter and then type it in again and hit enter to confirm. BTW, the command "sudo" stands for "super user do" and allows you to execute commands as a super user aka root user.
sudo passwd root
Next we're going to enable the built-in VNC server. This makes things so much easier as you can simply copy and paste commands via VNC rather than typing them. Select GUI Menu (the little raspberry on the taskbar) > Preferences > Raspberry Pi Configuration > Interfaces. Click Enabled next to VNC and then OK. After a few seconds a VNC icon will appear on the taskbar. Click it and then the menu icon at the top right (box with 3 horizontal lines) and then Options. In the Security options set Encryption to "Prefer off" and Authentication as "VNC password". A password box will pop up. Enter "raspberry" (without the quotes) for the password into each box and click OK. You will get a second warning box that you have to click OK to confirm. We're setting up an audio streamer, not storing nuclear codes :)
Before we go any further we need to assign a static IP address. If your Pi's IP address is randomly assigned by your router's DHCP server, then the IP address could change later and you wouldn't be able to connect via VNC (or Sonos for that matter). RIGHT-click the network connections icon on the taskbar (the little up and down arrow icon) and select "Wireless and Wired Network Settings". LEFT-click the upper right box and select "eth0" to configure the ethernet connection or "wlan0" for wireless. I would advise assigning a static IP to only one or the other. I had a problem when I first set up my Pi where I assigned the same static IP address to both connections and my Pi's wireless locked up and I couldn't get it back working correctly so I had to start all over installing the OS. Anyway, enter the IP address you want in the IP address field and enter your router's IP address in both the Router and DNS Servers field. Click Apply and Close.
NOTE: It may be easier to assign a static IP address using your router's DHCP IP reservation feature if it has one. You may need the MAC address of the Pi or it may just show up in a list of connected devices on your router's admin page. If you need the MAC address then type in the command "ifconfig eth0" in the terminal window for ethernet or "ifconfig wlan0" for WiFi. Interestingly enough the WiFi's MAC address will show up on the line that begins with "ether"
Next we need to set the default screen resolution. This may seem silly seeing as how we're already connected to a monitor but later when you connect via VNC without a monitor attached (headless, as they say) it will revert back to the Pi's default 640x480 resolution which is a very tiny screen to work with! Select GUI Menu > Preferences > Raspberry Pi Configuration > Set Resolution. Set it to 1280x720 or higher and click OK and Yes to reboot.
At this point you may want to start using VNC to control the Pi. Open up the VNC control panel on the Raspbian desktop again and look for the IP address under "Connectivity". Install and run a VNC viewer on your regular computer and use that IP address to connect and enter "raspberry" (without the quotes) as the password. I used TightVNC for Windows. After you've connected you can save the Pi's VNC connection as a shortcut on your desktop to quickly connect in the future bypassing the logon screen. You will get a warning about saving the password within the shortcut. Again, the codes. To copy and paste into the Pi's terminal window, select or highlight the text or commands on your regular computer, hit Ctrl-C (literally hit the Ctrl and C key on your keyboard at the same time) or right-click and select "Copy", then activate the Pi's VNC viewer window and RIGHT-click inside the terminal window right on the cursor and select Paste.
Next we are going to test the sound card to make sure it is working properly. Plug a live audio source into the USB sound card's RCA line inputs. Open the terminal window and type in "arecord -l" (that's a lowercase "L") and hit enter. That will list your attached sound card devices. The number after the word "card" is your device number. Substitute that number in the next command after the word "plughw:" In my case my card number was "1" so I typed in (actually copied and pasted using VNC) "arecord -D plughw:1,0 -f cd temp.wav". That will start recording a CD-quality .wav file from the sound card's inputs. After a few seconds hit Ctrl-C (literally hit the Ctrl and C key on your keyboard at the same time) to stop the recording. To play it back you will need to plug headphones into the headphone jack located on the Raspberry Pi card itself or the headphone jack of the external USB sound card. RIGHT-click the speaker icon on the taskbar and select the corresponding device you just plugged your headphones into and turn up the volume (Analog = Raspberry Pi headphone jack; USB AUDIO CODEC = External USB sound card headphone jack). Type in "aplay temp.wav" and hit enter and you should hear what you just recorded. The sound card on the Pi is not very good so if you are listening via its built-in headphone jack, don't be alarmed if it doesn't sound all that great. Our audio stream will be all digital and will sound great on Sonos.
arecord -D plughw:1,0 -f cd temp.wav
Next we are going to install two programs, Darkice and Icecast2. Darkice is what will be encoding our live audio source into an mp3 stream and Icecast2 is what will be serving it to Sonos as a Shoutcast stream. Type in each of these lines in the terminal window one at a time followed by the enter key each time:
mv darkice_1.0.1-999~mp3+1_armhf.deb?raw=true darkice_1.0.1-999~mp3+1_armhf.deb
sudo apt-get install libmp3lame0 libtwolame0
sudo dpkg -i darkice_1.0.1-999~mp3+1_armhf.deb
Now to install Icecast2. Type in "sudo apt-get install icecast2" followed by enter. After it installs a window will pop up asking if you want to configure Icecast2. Hit the left arrow key and enter to select Yes. On the second screen hit the down arrow key and enter to select OK to use the default hostname "localhost". On the next three screens hit the down arrow and enter key to agree to use "hackme" as the default source, relay and administration password. Even though we are agreeing to all of the default settings, these steps must be completed to activate the Icecast2 server.
sudo apt-get install icecast2
Next we need to run the GUI file manager as root user. To do this, select GUI Menu > Run. Type in "sudo pcmanfm" and hit enter. That will open up the file manager (the equivalent of file explorer for us Windows users) to the home directory (/home/pi) and you will see the leftover darkice installation file we previously downloaded along with the temp.wav file we created to test the sound card. RIGHT-click on an empty space in the explorer window and select Create New and then Empty File. Name it "darkice.cfg" and click OK. Then RIGHT-click that newly created file and choose to open it with Leafpad (the equivalent of Windows notepad). Copy the lines below and paste them into Leafpad then click File and Save. The settings I have selected are for the best quality mp3 stream but you may want to tweak them to lower quality settings if you are going to be streaming outside your network e.g. the Internet. Make sure your sound card number is correct in the line "device = plughw:1,0" You'll notice the "quality" line is commented out with a # in front of it. It is used only if you set "bitrateMode = vbr" (variable bitrate). You can't have a quality value set when using cbr (constant bitrate) or the stream will stutter and skip. I only discovered this little gem after many hours of frustration. I assumed the quality value would be ignored if you were using cbr but it turns out that is not the case and really throws a monkey wrench into the works. Conversely, if you decide to use vbr then you need to comment out the "bitrate = 320" line and uncomment the "quality" line.
[general] duration = 0 # duration in s, 0 forever bufferSecs = 1 # buffer, in seconds reconnect = yes # reconnect if disconnected [input] device = plughw:1,0 # Soundcard device for the audio input sampleRate = 44100 # sample rate 11025, 22050 or 44100 bitsPerSample = 16 # bits channel = 2 # 2 = stereo [icecast2-0] bitrateMode = cbr # constant bit rate ('cbr' constant, 'abr' average) #quality = 1.0 # 1.0 is best quality (use only with vbr) format = mp3 # format. Choose 'vorbis' for OGG Vorbis bitrate = 320 # bitrate server = localhost # or IP port = 8000 # port for IceCast2 access password = hackme # source password for the IceCast2 server mountPoint = rapi.mp3 # mount point on the IceCast2 server .mp3 or .ogg name = Raspberry Pi
Next we need follow the same steps as before to create an empty file called "darkice.sh". An .sh file is the equivalent of a .bat or batch file for DOS or Windows. Open using Leafpad, copy and paste the lines below and save.
#!/bin/bash sudo /usr/bin/darkice -c /home/pi/darkice.cfg
Next we need to run a command to make the darkice.sh file executable. Open the terminal window and type in "sudo chmod 777 /home/pi/darkice.sh" and hit enter. Now it's time to start the Icecast2 server service. Type in "sudo service icecast2 start" and hit enter.
sudo chmod 777 /home/pi/darkice.sh
sudo service icecast2 start
Next we need to tell Darkice to start automatically whenever the Pi is booted (the Icecast2 server runs as a service and already starts automatically after booting). First we need to select which text editor to use. In the terminal window type "select-editor" and hit enter. Type "2" to select nano editor and hit enter. Then type "crontab -e" and enter. Next hold the down arrow key down to scroll all the way to the bottom of the text file that appears and add this line "@reboot sleep 10 && sudo /home/pi/darkice.sh". Then hit Ctrl-X to exit and it will prompt "Save modified buffer?". Hit the Y key for Yes then enter to confirm whatever filename is automatically generated. The sleep 10 switch tells the Pi to wait 10 seconds after booting before starting the audio stream. This gives the OS time to initialize the USB sound card. If you start the stream before the USB sound card is active, the stream will never start.
@reboot sleep 10 && sudo /home/pi/darkice.sh
Click the GUI menu icon and select reboot. If you followed all these steps precisely then the stream will start automatically anywhere from 30 seconds to a minute after clicking reboot.
UPDATE: I cannot get my stream to play directly in Google Chrome anymore. I think it got broken with a Chrome update. It still works fine on Sonos and my other streaming apps.
To test that the stream is working correctly, open the web browser on your regular computer and navigate to "http://192.168.1.146:8000" (with your Pi's correct IP address substituted for mine of course) to view the status of your Pi's Icecast2 server. To listen, click on the M3U icon in the upper right or you can manually enter "http://192.168.1.146:8000/rapi.mp3" to open the stream directly and skip downloading the .m3u playlist file altogether. If you hear your live source then the Pi is working correctly and it's time to add it to Sonos.
You must use the Sonos desktop controller app to add a custom stream to Sonos. Click on Manage > Add Radio Station and enter the url for the stream which in my case was "http://192.168.1.146:8000/rapi.mp3". Also enter a Station Name and click OK.
To play the custom radio station we just added, select "Radio by Tunein" and then "My Radio Stations" and then you will see your Raspberry Pi listed. LEFT DOUBLE-click to play or RIGHT-click to edit or add the station to your Sonos favorites.
After adding the custom radio station it will immediately be available on your Sonos mobile app. Sonos recently updated their app to a ghastly white motif as well as renaming "Sonos Favorites" to "My Sonos" and using overly large thumbnails for everything. There has been a lot of backlash on the Sonos forums as the old format looked and worked so well with everything easily accessible without blinding you in a dark room. Hopefully they will revert back to the old style soon. Anyway, on the new app, tap "My Sonos" at the bottom, scroll down to "Stations" and tap "See All". On the next screen scroll down until you see "Raspberry Pi". Tap on it and it will start playing in your selected room(s).
The last thing to do is to install the Pi in a case. I chose the Flirc Raspberry Pi Case because it both looks good and is functional. The entire aluminum case acts as a heat sink for the Pi's processor. If you get this case, peel off the sticky side of the spongy thermal pad that is included and stick it on the part of the case that reaches down to touch the processor and then peel off the thin plastic film on the other, non-sticky side (the side that touches the processor) before closing up the case.
Just a bit of house cleaning: If you plan to leave your Pi connected via ethernet then you may want to turn off its Wi-Fi radio to conserve a little juice. To do this LEFT-click the network connections icon (the little up and down arrow icon) and select "Turn Off Wi-Fi". You can also turn off the bluetooth radio by LEFT-clicking the bluetooth icon. Also, the Darkice program runs hidden in the background so if you ever need to stop it then open a terminal window, type in "ps aux | grep darkice.cfg" and hit enter and then "sudo kill 976" (or whatever the first process ID is) and hit enter. To restart the stream type in "sudo darkice -c ~/darkice.cfg" and hit enter or just simply reboot. I was curious how much bandwidth the Pi used when there were no clients attached to the Icecast server so I installed a bandwidth monitoring tool called vnstat and the answer is 0 kbps. If there are no clients connected then there is absolutely no bandwidth used whatsoever. Good luck and thanks for looking!
ps aux | grep darkice
sudo kill 976
sudo darkice -c ~/darkice.cfg
Runner Up in the
Raspberry Pi Contest 2017