Jamulus Server – Audio Stream

Installation

Raspberry PI 4 comes with a playback device only (headphones), however to stream audio from Jamulus client a playback device is sufficient.

x11

  • We want graphical support for e.g. jackd, jamulus
  • sudo apt install x11-apps
  • After installation login with -Y option (e.g. ssh -Y user@host); requires e.g. Xquartz (Mac), Xming (Windows)

Alsa

Advanced Linux Sound Architecture (ALSA) is a software framework and part of the Linux kernel that provides an application programming interface (API) for sound card device drivers.

sudo apt-get install alsa-base alsa-utils

arecord -l
**** List of CAPTURE Hardware Devices ****

cat /proc/asound/cards
0 [Headphones     ]: bcm2835_headphonbcm2835 Headphones - bcm2835 Headphones

aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Headphones [bcm2835 Headphones], device 0: bcm2835 Headphones [bcm2835 Headphones]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7

JACK

JACK (JACK Audio Connection Kit) refers to an API and two implementations of this API, jack1 and jack2. It provides a basic infrastructure for audio applications to communicate with each other and with audio hardware. Through JACK, users are enabled to build powerful systems for signal processing and music production.

sudo apt install jackd

The following NEW packages will be installed: jackd jackd2 libflac8 libpython2-stdlib libpython2.7-minimal libpython2.7-stdlib libqt5x11extras5 libsndfile1 libvorbisenc2 python-dbus python-gi python2
 python2-minimal python2.7 python2.7-minimal qjackctl

Darkice

DarkIce is a live audio streamer. It records audio from an audio interface (e.g. jack), encodes it and sends it to a streaming server.

sudo apt-get install dh-autoreconf libtool libtool-bin libasound2-dev libfftw3-dev 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 libshout3-dev libmp3lame-dev libopus-dev libfaad-dev libflac-dev libtwolame-dev libaudio-dev lame libjack-jackd2-dev
wget https://github.com/rafael2k/darkice/releases/download/v1.4/darkice-1.4.tar.gz
cd /home/ubuntu/darkice-1.4

./configure --with-lame --with-lame-prefix=/usr/lib/aarch64-linux-gnu/ --without-faac
make
sudo make install
-rwxr-xr-x 1 root root 603856 Oct 29 11:46 /usr/local/bin/darkice*
  • sudo vim /etc/darkice.cfg 
[general]
duration        = 0         # duration of encoding, in seconds. 0 means forever
bufferSecs      = 2         # size of internal slip buffer, in seconds
reconnect       = yes       # reconnect to the server(s) if disconnected
realtime        = yes       # run the encoder with POSIX realtime priority
rtprio          = 3         # scheduling priority for the realtime threads

# this section describes the audio input that will be streamed
[input]
device          = jack      # OSS DSP soundcard device for the audio input
jackClientName  = darkice   # name as represented in jack
sampleRate      = 48000     # sample rate in Hz. try 11025, 22050 or 44100
bitsPerSample   = 16        # bits per sample. try 16
channel         = 2         # 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     = abr        # average bit rate
format          = mp3        # format of the stream: ogg vorbis
bitrate         = 128        # bitrate of the stream sent to the server
server          = localhost
port            = 8000
password        = hackme
mountPoint      = timton.live # mount point of this stream on the IceCast2 server
name            = timton.live # name of the stream
#description     = TIMTON PI audio stream # description of the stream
url             = http:/jamulus.hensler.net # URL related to the stream
genre           = Genre Jazz # genre of the stream
public          = yes       # advertise this stream?
#localDumpFile  = dump.ogg  # local dump file

Jamulus client

cd /home/ubuntu
sudo apt-get install build-essential qt5-qmake qtdeclarative5-dev libjack-jackd2-dev qt5-default
git clone https://github.com/corrados/jamulus.git jamulus_client
cd jamulus_client
qmake Jamulus.pro
make clean
make

Configuration

Use either qjackctl or command line to configure JACK connections. qjackctl must be run each time after a restart:

qjackctl

  • Start Darkice: /usr/local/bin/darkice -v 4 -c /etc/darkice.cfg
  • Start Jamulus client: /home/ubuntu/jamulus_client/Jamulus -c jamulus.hensler.net
  • Start qjackctl: /usr/bin/qjackctl 
Create your Patchbay configuration
in Setup “configure parameters”
in Options activate “Patchbay Persistence” and “Reset all connections”
check your session window

command line

  • vim start_audio_stream.sh
#!/bin/bash
CURRENTDATE=`date +"%Y-%m-%d %T"`

echo
echo START NEW AUDIO STREAM $CURRENTDATE
echo

export JACK_NO_AUDIO_RESERVATION=1

killall jackd

sleep 2s
/usr/bin/jackd -ddummy &

sleep 5s
/root/jamulus_client/Jamulus -n -c jamulus.hensler.net &

sleep 5s
/usr/local/bin/darkice -c /etc/darkice.cfg &

sleep 2s
jack_disconnect "Jamulus:output left" "system:playback_1"
jack_disconnect "Jamulus:output right" "system:playback_2"
jack_disconnect "Jamulus:output left" "darkice:left"
jack_disconnect "Jamulus:output right" "darkice:right"
jack_disconnect "system:capture_1" "Jamulus:input left"
jack_disconnect "system:capture_2" "Jamulus:input right"

sleep 2s
jack_connect "Jamulus:output left" "darkice:left"
jack_connect "Jamulus:output right" "darkice:right"
  • crontab -e
@reboot /root/start_audio_stream.sh > /root/timton.live.out

Icecast

Icecast is a streaming media server which currently supports Ogg Vorbis and MP3 audio streams. It can be used to create an Internet radio station or a privately running jukebox and many things in between. It is very versatile in that new formats can be added relatively easily and supports open standards for commuincation and interaction.

sudo apt-get install icecast2
The following NEW packages will be installed: icecast2 libspeex1 libtheora0 libwolfssl24

sudo vim /etc/icecast2/icecast.xml
    <hostname>jamulus.hensler.net</hostname>
    <authentication>
        <!-- Sources log in with username 'source' -->
        <source-password>password</source-password>
        <!-- Relays log in with username 'relay' -->
        <relay-password>password</relay-password>

        <!-- Admin logs in with the username given below -->
        <admin-user>admin</admin-user>
        <admin-password>password</admin-password>
    </authentication>

sudo systemctl status icecast2

nginx

  • sudo apt-get install nginx
The following NEW packages will be installed: 
libgd3 libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream libxpm4 libxslt1.1 nginx nginx-common nginx-core
  • sudo vim /etc/nginx/sites-available/default
server {
listen 80;
listen [::]:80;
server_name jamulus.hensler.net;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;
location / {
proxy_pass http://localhost:8000;
}
}

certbot

Certbot is usually meant to be used to switch an existing HTTP site to work in HTTPS (and, afterward, to continue renewing the site’s HTTPS certificates whenever necessary).

  • sudo snap install core; sudo snap refresh core
  • sudo snap install –classic certbot
  • sudo ln -s /snap/bin/certbot /usr/bin/certbot
  • sudo certbot certonly –manual  –email bhensler@gmail.com -d ‘*.hensler.net’
  • nslookup -type=TXT _acme-challenge.hensler.net
  • sudo systemctl restart nginx
  • sudo vim /etc/nginx/sites-available/default
server {

server_name bernhard.hensler.net www.hensler.net;
#return 301 https://bernhard.hensler.net$request_uri;

root /var/www/html/bernhard.hensler.net;
index  index.php index.html index.htm;

client_max_body_size 100M;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;



location / {
        try_files $uri $uri/ /index.php?$args;
    }
    location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass             unix:/var/run/php/php7.4-fpm.sock;
    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

location /timton.live {
    proxy_pass http://localhost:8000;
    }


    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/bernhard.hensler.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/bernhard.hensler.net/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = bernhard.hensler.net) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


listen 80;
listen [::]:80;
server_name bernhard.hensler.net;
    return 404; # managed by Certbot

  • sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Miscellaneous

system data

Embed audio stream (e.g. WordPress Blog)

liquidsoap

An alternative to Darkice is liquidsoap.

sudo apt install liquidsoap

The following NEW packages will be installed:
  gstreamer1.0-plugins-base libaacs0 libao-common libao4 libaom0 libass9 libasyncns0 libavc1394-0 libavcodec58 libavdevice58 libavfilter7 libavformat58
  libavutil56 libbdplus0 libbluray2 libbs2b0 libcaca0 libcamomile-ocaml-data libcdio-cdda2 libcdio-paranoia2 libcdio18 libcdparanoia0 libchromaprint1
  libcodec2-0.9 libdc1394-22 libexif12 libfaad2 libfftw3-double3 libflite1 libgavl1 libgif7 libgme0 libgsm1 libgstreamer-plugins-base1.0-0 libiec61883-0
  liblilv-0-0 liblo7 libmad0 libmp3lame0 libmpg123-0 libmysofa1 libnorm1 libopenal-data libopenal1 libopencore-amrnb0 libopencore-amrwb0 libopenjp2-7
  libopenmpt0 libopus0 liborc-0.4-0 libpgm-5.2-0 libportaudio2 libpostproc55 libpulse0 libraw1394-11 librubberband2 libsdl-image1.2 libsdl-ttf2.0-0
  libsdl1.2debian libsdl2-2.0-0 libserd-0-0 libshine3 libsnappy1v5 libsndio7.0 libsord-0-0 libsoundtouch1 libsox-fmt-alsa libsox-fmt-base libsox3 libsoxr0
  libsratom-0-0 libssh-gcrypt-4 libswresample3 libswscale5 libtag1v5 libtag1v5-vanilla libtwolame0 libva-drm2 libva-x11-2 libva2 libvdpau1 libvidstab1.1
  libvisual-0.4-0 libvpx6 libwavpack1 libwebpmux3 libx264-155 libx265-179 libxss1 libxv1 libxvidcore4 libzmq5 libzvbi-common libzvbi0 liquidsoap
  mesa-va-drivers mesa-vdpau-drivers ocaml-base-nox ocl-icd-libopencl1 sox va-driver-all vdpau-driver-all vorbis-tools vorbisgain
liquidsoap 'liquidsoap.in = input.jack() output.icecast(%vorbis, host = "localhost", port = 8000, password = "hackme", mount = "timton.live", name = "Jamulus Audio Stream", url = "http://jamulus.hensler.net", liquidsoap.in)'

One thought on “Jamulus Server – Audio Stream

  1. Hey, thanks for the write-down! One thing I stumbled upone is that there is an outer tag missing in the icecast.xml. Maybe that’s helpful for others.

Leave a Reply

Your email address will not be published. Required fields are marked *