Aug. 10., 2012

Live mp3 streaming from audio-in with DarkIce and Icecast2 on Raspberry Pi

By Steffen Müller. Licensed under the Creative Commons License CC BY-SA 3.0, published on t3node.com

As a response to my lastest article about Streaming audio with MPD and Icecast2 on Raspberry Pi, I was asked for some ideas about live streaming. I took the chance to plug in an usb audio device with microphone to RasPi and tried to get it working.

Update (2012/08/11): Added a step to update package version number and added "devscripts" to the list of suggested packages .

What you need to have

  • Raspberry Pi with Raspbian installed,
  • USB sound stick with an input device,
  • DarkIce to capture audio from the audio input and send it to Icecast2,
  • Icecast2 to distribute the audio stream.

Compiling and installing DarkIce

The default darkice package comes without mp3 support. Since mp3 is the most widespread codec, I decided to build my own package of darkice with mp3 support.

Add a deb-src repository to your sources list at /etc/apt/sources.list:

$ sudo sh -c "echo 'deb-src http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi' >> /etc/apt/sources.list"
$ sudo apt-get update
(...)

To fullfill the build dependencies, you have to install some additional packages:

$ sudo apt-get --no-install-recommends install build-essential devscripts autotools-dev fakeroot dpkg-dev debhelper autotools-dev dh-make quilt ccache libsamplerate0-dev libpulse-dev libaudio-dev lame libjack-jackd2-dev libasound2-dev libtwolame-dev libfaad-dev libflac-dev libmp4v2-dev libshout3-dev libmp3lame-dev
(...)

(Not sure if you need all these packages. But it won't hurt.)

Create a working directory:

$ mkdir src && cd src/

Get the source package of darkice:

$ apt-get source darkice
(...)

Change the compile configuration to match Raspbian environment:

$ cd darkice-1.0/
$ vi debian/rules

 

#!/usr/bin/make -f

%:
dh $@

.PHONY: override_dh_auto_configure
override_dh_auto_configure:
ln -s /usr/share/misc/config.guess .
ln -s /usr/share/misc/config.sub .
dh_auto_configure -- --prefix=/usr --sysconfdir=/usr/share/doc/darkice/examples --with-vorbis-prefix=/usr/lib/arm-linux-gnueabihf/ --with-jack-prefix=/usr/lib/arm-linux-gnueabihf/ --with-alsa-prefix=/usr/lib/arm-linux-gnueabihf/ --with-faac-prefix=/usr/lib/arm-linux-gnueabihf/ --with-aacplus-prefix=/usr/lib/arm-linux-gnueabihf/ --with-samplerate-prefix=/usr/lib/arm-linux-gnueabihf/ --with-lame-prefix=/usr/lib/arm-linux-gnueabihf/ CFLAGS='-march=armv6 -mfpu=vfp -mfloat-abi=hard'

Change the version of the package to reflect mp3 support. debchange will ask you to add some comments to the changelog.

$ debchange -v 1.0-999~mp3+1

darkice (1.0-999~mp3+1) UNRELEASED; urgency=low

* New build with mp3 support

-- <pi@raspberrypi> Sat, 11 Aug 2012 13:35:06 +0000

Build and install the darkice package:

$ dpkg-buildpackage -rfakeroot -uc -b
(...)
$ sudo dpkg -i ../darkice_1.0-999~mp3+1_armhf.deb
(...)
Preparing to replace darkice 1.0-999 (using .../darkice_1.0-999~mp3+1_armhf.deb) ...
Unpacking replacement darkice ...
Setting up darkice (1.0-999~mp3+1) ...
(...)

Now you have installed DarkIce with mp3 support.

Configuring DarkIce

Add a configuration by copying the template file:

$ sudo cp /usr/share/doc/darkice/examples/darkice.cfg /etc/

Here's an example configuration to have:

  • read input from an usb device using the alsa audio device hw1,0
  • stream mp3 output to an icecast2 server
# see the darkice.cfg man page for details

# this section describes general aspects of the live streaming session
[general]
duration = 0 # duration of encoding, in seconds. 0 means forever
bufferSecs = 5 # size of internal slip buffer, in seconds
reconnect = yes # reconnect to the server(s) if disconnected

# this section describes the audio input that will be streamed
[input]
device = hw:1,0 # Alsa soundcard device for the audio input
sampleRate = 44100 # sample rate in Hz. try 11025, 22050 or 44100
bitsPerSample = 16 # bits per sample. try 16
channel = 1 # channels. 1 = mono, 2 = stereo

# this section describes a streaming connection to an IceCast2 server
# there may be up to 8 of these sections, named [icecast2-0] ... [icecast2-7]
# these can be mixed with [icecast-x] and [shoutcast-x] sections
[icecast2-0]
bitrateMode = vbr # variable bit rate
format = mp3 # format of the stream: mp3
quality = 0.6 # quality of the stream sent to the server
server = localhost # host name of the server
port = 8000 # port of the IceCast2 server, usually 8000
password = SOURCE_PASSWORD # source password to the IceCast2 server
mountPoint = raspi # mount point of this stream on the IceCast2 server
name = RasPi # name of the stream
description = DarkIce on RasPi # description of the stream
url = http://localhost # URL related to the stream
genre = my genre # genre of the stream
public = no # advertise this stream?
localDumpFile = recording.mp3 # Record also to a file

This is just an example and neither optimized nor secure! Learn more about darkice in the documentation section below /usr/share/doc/darkice/. The configuration options are explained in the manpage:

$ man darkice.cfg

Btw., to find your alsa input devices, ask arecord:

$ arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: U0x46d0x825 [USB Device 0x46d:0x825], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0

This particular input device is the microphone of a Logitech H270 webcam. It can be addressed using hw:1,0 (Card 1, Subdevice 0).

Keep in mind that Raspberry Pi has no input audio devices on board. You have to plug additional soundcard hardware to usb.

Installing Icecast2

If you don't have an icecast2 server running somewhere, you could set one up on RasPi.

$ sudo aptitude install icecast2

The package manager will ask you to configure Icecast2. You should do so and set a hostname and passwords for source, relay and administration. Needless to say to use strong passwords. The source password will be needed in the darkice.cfg configuration. (See SOURCE_PASSWORD in the above example)

Running DarkIce to stream audio

$ darkice
(...)
Using config file: /etc/darkice.cfg
Using ALSA DSP input device: hw:1,0
Could not set POSIX real-time scheduling, this may cause recording skips.
Try to run darkice as the super-user.

When you run into the following "sink error" message, check if icecast is running and passwords are matching:

DarkIce: LameLibEncoder.cpp:75: lame lib opening underlying sink error [0]

Now grab your favorite instrument and start a live jam. To listen to it, open your browser, navigate to the Raspberry Pi host at http://your.raspberry.hostname:8000/raspi and hook up into the stream with your favorite player.

Performance

I have done some very basic measurements. With the above configurations, the CPU load is about 50%. Very nice!

Credits

Thanks to Patrick Adams for inspiration. Looking forward for a turntable session to listen to ;-)

--> Back to the list of articles

License

Licensed under creative commonsThis article is licensed under the Creative Commons License CC BY-SA 3.0. You are free to share (copy, distribute and transmit) and to remix (to adapt) the work under the following conditions:

  • You must attribute the work by mentioning the name of the author (Steffen Müller) and setting a link back to the original article using its URL.
  • If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one.

Comments

  1. tobie wrote on September 7, 2012 at 10:21

    hi, could I ask about audio input quality?

    I'm using arecord to get audio in from a usb device at plughw:1,0, but sound quality is not good.

    Are you getting good quality sound input? Are you using a USB hub?

  2. Steffen wrote on September 7, 2012 at 12:40

    Hi tobie,

    I have a clear signal with my device. Whatever "clear" means to the microphone of my Logitech H270 webcam ;-)
    The device is connected directly to one of the USB ports.

    Just a wild guess: the reason for your problem could be the samplerate.

    Try to find out which samplerate your device supports and then set ALSA accordingly.
    I had similar problems on a Seagate Dockstar with C-Media Audio USB Adapter. I fixed it by adding the following settings to /etc/asound.conf:


    pcm.rate_convert {
    type plug
    slave {
    pcm "hw:1,0"
    rate 48000
    }
    }

    See opensrc docs: http://alsa.opensrc.org/.asoundrc#Converting_Sample_Rates_On_Input
    and also the official alsa docs: http://www.alsa-project.org/main/index.php/Asoundrc
  3. Ben wrote on September 19, 2012 at 08:29

    Hi,

    How much delay is there in the recording (provided the pi and the listening device are on the same network)?
    I tried both RTP and HTTP Streaming successfully but with ~15s delay (no buffering used) and 30% CPU.


  4. Steffen wrote on September 19, 2012 at 14:59

    Hi Ben,

    mainly you have two buffers which need to get filled:

    1) Darkice buffer, configured with "bufferSecs" (5 seconds in my example cfg)
    2) Icecast2 buffer aka "queue-size" and eventually "burst-size>", which need some time to get filled.

    Not sure about how much delay is caused by resampling, but mpeg is not designed for low latency transport/transition. Maybe aac or ogg perform better here. I would be glad if you'd try and report back here.

    If you have both Darkice and icecast2 on one host, you can reduce the Darkice buffer. not sure if 0 is a good choice, but you could also try and frankly report here.
    However, if you want to provide a stable stream for clients on the network, you should not turn off icecast2 buffers completely.

  5. Ben wrote on September 19, 2012 at 21:40

    Thanks for documenting this!

    What was the latency you experienced when listening on the same network? By latency, i mean the time between the moment a sound is recorded and the moment it is received on the remote device.

    Fyi, the best I have managed is ~15s. Not really real time...

  6. Steffen wrote on September 20, 2012 at 11:45

    I have experienced approx. the same 15 seconds.

    If you like to nail down the root of your latency, you could sniff the network traffic e.g. with wireshark. Then you should roughly see how much time goes by until darkice starts streaming to icecast.

    Latency is nothing unusual for consumer (aka "mp3") audio streams in the internet.

  7. Seva wrote on October 3, 2012 at 00:52

    Have you done any load testing with actual users connected? I wonder how many listeners the RPi could handle..

  8. Steffen wrote on October 3, 2012 at 01:22

    Though I haven't tested this, I guess the network would be the bottleneck.

    RPi has only a network capacity of 100MBit/s, which theoretically means approx. 800 concurrent listeners with a 128k stream. This does not consider any overhead caused by network protocols and the ones.

    If you like to test this, have a look at this article, including a basic test script: http://www.icecast.org/loadtest1.php

  9. J@y wrote on October 8, 2012 at 02:25

    I love this tutorial it was exactly what i needed. But I'm just getting static noise when its recording from mic and nothing else.

  10. J@y wrote on October 8, 2012 at 02:30

    by the way this is what my asound.conf looks like - not sure what most of it means tho:

    pcm.mmap0 {
    type mmap_emul;
    slave {
    pcm "hw:0,0";
    }
    }

    pcm.!default {
    type plug;
    slave {
    pcm mmap0;
    }
    }

  11. Guilherme Rambo wrote on October 9, 2012 at 03:22

    My sound is sort of chunky, here's a sample: http://cl.ly/0y0n3y2q1g04 (the static noise is on purpose, notice it clips a few times every second).

    I've tried sample rates 44100, 48000 and 22050. 48000 seems to yield the best result, but still has that clipping.

    Also tried that asound.conf stuff. Tried different bufferSecs like 5, 10, 15... but no luck...

    I'm using a Behringer UCA200.

    Any thoughts?

  12. Steffen wrote on October 9, 2012 at 10:51

    J@y and Guilherme Rambo,

    please have a look at the ALSA docs, I referred to at http://www.t3node.com/blog/live-streaming-mp3-audio-with-darkice-and-icecast2-on-raspberry-pi/#comment-2

    You could also get in touch with the ALSA community via Mailinglists, Newsgroups etc. I am not really experienced with ALSA and can't help you out.


Leave a comment:

This page uses static caches. Make sure you reload the page in your browser after posting a comment.

(will not be published)

CAPTCHA image for SPAM prevention Click here for audio version of the word to enter.

If you can't read the captcha word, please click to load a new image.
(You need Javascript turned on. Otherwise press the submit button and wait until the page has reloaded.)