OpenBSD Journal

Transparent network audio with mpd & sndiod

Contributed by rueda on from the Radio Landry dept.

Landry Breuil (landry@ when wearing his developer hat) wrote in…

I've been a huge fan of MPD over the years to centralize my audio collection, and i've been using it with the http output to stream the music as a radio on the computer i'm currently using…

audio_output {
       type            "sndio"
       name            "Local speakers"
       mixer_type      "software"
}
audio_output {
       type            "httpd"
       name            "HTTP stream"
       mixer_type      "software"
       encoder         "vorbis"
       port            "8000"
       format          "44100:16:2"
}

this setup worked for years, allows me to stream my home radio to $work by tunnelling the port 8000 over ssh via LocalForward, but that still has some issues:

  • a distinct timing gap between the 'local output' (ie the speakers connected to the machine where MPD is running) and the 'http output' caused by the time it takes to reencode the stream, which is ugly when you walk through the house and have a 15s delay
  • sometimes mplayer as a client doesn't detect the pauses in the stream and needs to be restarted
  • i need to configure/start a client on each computer and point it at the sound server url (can do via gmpc shoutcast client plugin…)
  • it's not that elegant to reencode the stream, and it wastes cpu cycles

So the current scheme is:

mpd -> http output -> network -> mplayer -> sndiod on remote machine
|
-> sndio output -> sndiod on soundserver

Fiddling a little bit with mpd outputs and reading the sndio output driver, i remembered sndiod has native network support… and the mpd sndio output allows you to specify a device (it uses SIO_DEVANY by default).

So in the end, it's super easy to:

  • enable network support in sndio on the remote machine i want the audio to play by adding -L<local ip> to sndiod_flags (i have two audio devices, with an input coming from the webcam):
    sndiod_flags="-L10.246.200.10 -f rsnd/0 -f rsnd/1"
  • open pf on port 11025 from the sound server ip:
    pass in proto tcp from 10.246.200.1 to any port 11025
  • configure a new output in mpd:
    audio_output {
           type            "sndio"
           name            "sndio on renton"
           device          "snd@10.246.200.10/0"
           mixer_type      "software"
    }
  • and enable the new output in mpd:
    $mpc enable 2
    Output 1 (Local speakers) is disabled
    Output 2 (sndio on renton) is enabled
    Output 3 (HTTP stream) is disabled

Results in a big win: no gap anymore with the local speakers, no reencoding, no need to configure a client to play the stream, and i can still probably reproduce the same scheme over ssh from $work using a RemoteForward.

mpd -> sndio output 2 -> network -> sndiod on remote machine
|
-> sndio output 1 -> sndiod on soundserver
Thanks ratchov@ for sndiod :)

  1. By Mario St-Gelais (mariostg) mario.stg@videotron.ca on

    Looking forward to try this out for my mpd setup.

  2. By Jan Lambertz (JanLam) jan@lambertz.one on

    Hi,

    i already have the setup you described for 2 years by now. It works great. Sadly sndiod (I think) is not able to play two outputs in sync. So no multiroom audio yet.

Credits

Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original deadly.org with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]