One Way to stream lossless icecast2 from MIXXX in Linux

General Mixxx discussion.... discuss

Moderator: garth

One Way to stream lossless icecast2 from MIXXX in Linux

Postby zog » Mon Apr 06, 2020 1:11 pm

I've been trying different ways to stream DJ sets from MIXXX and found this method that works providing a lossless FLAC ogg stream to icecast2, with an update of what track is playing.

I'm using Xubuntu 16.04 for this.

It took me a while to get this combination of software working, so I thought I'd post the recipe as a set of rough scripts to show the approach

As the built in MIXXX broadcasting options don't support this, I set up the "booth" output to go to an ALSA loopback audio device.

I then use arecord piped into aviconv to stream the audio as an Icecast flac stream to the ICECAST2 server. I'm piping from arecord as I couldn't figure out how to record from the Loopback device direct with aviconv.
I'm using arecord "raw" as arecord defaults to recording WAV which has a max size of 2GB, even when piped.

As this loses the metadata, I use an sqlite3 command to extract the "now playing" info and display it on a web page.
The below two shell fragments can be made into scripts and left running in a screen session on the PC running mixxx.

Broadcast script:
Code: Select all
# very simple loop, needs
# sudo modprobe snd-aloop
# run to have the loopback audio set (or set it up in /etc/ ..)
#
# then set hw:Loopback,0 as the BOOTH output in MIXXX
# you may need to increase the latency to reduce glitching with the additional output.
#
# set s16 to s32 for 24 bit flac, but thats overkill...
#
cd /tmp
while true
do
  date
  arecord -D hw:Loopback,1,0 -f FLOAT_LE -c 2 -r 44100 -t raw | \
   avconv -report \
    -f f32le -sample_rate 44100 -ac 2 -sample_fmt f32le \
    -i pipe: \
    -ar 44100 -ac 2 -b:a 420000 -sample_fmt s16 \
    -bufsize 20480k \
    -c:a flac -compression_level 10 -f ogg \
    -ice_name 'MY RADIO LOSSLESS FLAC STREAM' \
    -ice_description 'Describe my stream'  \
    -ice_url 'https://www.website.net.au/' \
    -ice_public 1 \
    -content_type application/ogg \
    icecast://source:[email protected]:8000/source
  sleep 1


As it has lost the metadata during this process, update a now playing text file on the web site by grabbing that info from the MIXXX database...

Code: Select all
touch /tmp/nowplaying.txt-prev /tmp/nowplaying.txt
while true
do
    sqlite3 /home/dj/.mixxx/mixxxdb.sqlite -column -header "select library.artist, library.title, library.album, library.year from library where library.id = (select PlaylistTracks.track_id from PlaylistTracks where id = (select max(id) from PlaylistTracks));" > /tmp/nowplaying.txt
   if ! diff /tmp/nowplaying.txt /tmp/nowplaying.txt-prev > /dev/null
   then
      echo track has changed
      cat /tmp/nowplaying.txt
      date >> /tmp/radio.log
      cat /tmp/nowplaying.txt >> /tmp/radio.log
      scp -q /tmp/nowplaying.txt [email protected]:site/nowplaying.txt
      cp /tmp/nowplaying.txt /tmp/nowplaying.txt-prev
   fi
   sleep 10
done


Web page that will display an inline player for the above code:

Code: Select all
<!DOCTYPE html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
  <script type="text/javascript">
    function refresh() {
      var req = new XMLHttpRequest();
      console.log("Grabbing Value");
      req.onreadystatechange = function () {
        if (req.readyState == 4 && req.status == 200) {
          document.getElementById('NowPlayingElement').innerText = req.responseText;
        }
      }
      req.open("GET", 'https://static.website.net.au/nowplaying.txt', true);
      req.send(null);
    }

    function init() {
      refresh()
      var int = self.setInterval(function () {
        refresh()
      }, 2000);
    }
  </script>
</head>

<body onload="init()">
  <div id="main">
    <div id="updateMe">
      <b>MY RADIO Track Now Playing is:</b>
      <pre><p id="NowPlayingElement"></pre>
    </div>
<p><audio controls="controls" preload="none"><source src="https://icecast.website.net.au:8443/source" type="audio/ogg" />Your browser does not support the audio element.</audio> <!-- END OF THE RADIO HTML5 PLAYER EMBEDDING --></p>
  </div>
</body>
</html>


Running example (if the entry level cloud ICECAST2 server doesn't fall over :-) is here: https://www.zog.net.au/experimental-zog ... ation.html
zog
 
Posts: 30
Joined: Tue Sep 15, 2015 9:20 am

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 4 guests