MPD Stream lossless flac or wav

Modern networks are so fast and disk space so abundant and cheap that compressing a music collection to mp3, vorbis or similar now seems mostly pointless even for streaming, especially at home. Even away from home and streaming via ssh tunnels there is often no need for compression. I spent ages looking for a way to stream lossless audio and finally realised it was right under my nose and already running in the form of my mpd server. Lesson learned: Read The Fine Manual but don’t believe everything it says or assume it complete!

The mpd man page and typical example mpd.conf are out of date. For example mpd.conf states that streamed output must be vorbis or mp3. This is no longer the case. Run mpd –version to see a list of supported encoders. My mpd server (Debian Wheezy) shows:

Encoder plugins:
null vorbis lame wave flac

(If you compile mpd yourself you can include extra lossy encoders such as twolame, opus and shine).

so I set up my mpd server to stream lossless audio. If your audio collection is flac derived from CD (44100Hz 16-bit PCM with 2 channels) then you can use an output like this one:

audio_output {
type "httpd"
name "FLAC Stream"
encoder "flac"
port "8000"
format "44100:16:2"
}

(format must be defined for flac streams)

If you have a variety of formats and don’t want changes in bit depth or sample rate then you can choose to output to raw pcm wav like this:

audio_output {
type "httpd"
name "pcm wav Stream"
encoder "wave"
port "8000"
}

As this is raw (headerless) pcm some players won’t play it, or will require a format to be defined (sox’s play command is like this). Fortunately mplayer or mplayer2 will play back a raw pcm stream without issue. This means it integrates easily into your local alsa/pulse/jack setup, so you can direct the audio to any predefined software devices such as equalisers, crossfeeds, mixers, or direct to hardware devices such as USB DAC or onboard spdif and so on. Of course you can also use mplayer’s built in audio filters and/or numerous applications which have mplayer as a backend.

To play without stuttering or dropping out on track changes you can use something like:

mplayer -idle -cache 2048 your-mpd-host:8000

VLC will also play back these kinds of headerless streams.

On Android devices MPDroid supports streaming, and if you have an Android device with good multimedia support it might support both flac and raw pcm. My old (2010 vintage) Archos 43 and 28 Internet Tablets handle this really well and MPDroid passes the audio off to the devices’ DSP so it is relatively undemanding on the battery.

Advertisements

15 Responses to “MPD Stream lossless flac or wav”

  1. timss Says:

    This really helped me understand how I could do lossless mpd http stream, thanks a ton!

    I opted for the pcm/wave solution as I’ve got a healthy mix of proper flac rips, varying and fixed bitrate mp3 and sadly also some really horrible YouTube-> mp3 rips.

    The only downside is quite the amount of bandwidth usage (176.4 KB/s at all times), but this is mainly for use at a home LAN.

    • takla Says:

      Glad it was useful for you.

      Even the most humbly equipped home LAN should never have trouble streaming wav audio. My mpd server is a very lowly seven year old Core Duo laptop which connects to my router via a dual band wireless USB interface (Tenda W522U). In practice the bandwidth is about the same as wired 10/100 ethernet. The same machine also hosts all my video, runs ssh, dictionary, torrent and ftp servers and is perfectly capable of supporting 720p video with multichannel audio on my LAN, so plain audio is really only a modest demand.

      My very cheap home ADSL has a maximum upload speed of only about 1 megabit. When I’m away from home I use a Galaxy Note with 3G (variable connection quality here, HSDPA+ at best, can drop to Edge). If I have a strong signal and bandwidth I can stream wav to my phone (Galaxy Note GT-N7000 which supports flac for local files but doesn’t stream flac so I have to use wav if I want to stream lossless). Often my 3G connection is not ideal and then I might opt to use a vorbis or twolame lossy stream:

      audio_output {
      type “httpd”
      name “Ogg Vorbis Q7 Stream”
      encoder “vorbis”
      port “8000”
      quality “7.0”
      }

      audio_output {
      type “httpd”
      name “MP2”
      encoder “twolame”
      port “8000”
      bitrate “224”
      format “44100:16:2”
      }

      This can be done over SSH tunnel on a really good connection, or more reliably and with less bandwidth overhead and much less impact on the phone’s battery life by using an IPsec VPN such as strongswan. You need a good router for this, either an expensive commercial product or a home router than can run OpenWRT or similar.

      • timss Says:

        Oh, I didn’t intend to imply that the bandwidth usage could lead to problems for the streaming itself. More to the point of “wasting” bandwidth if that would ever be a problem and you’re not on a LAN.

        I’m currently using wireless aswell, but it’s pretty quick. Netgear WNDR3800, which can run OpenWRT. Mobile networks around where I live is usually at 5-20mbit on HSDPA+, but the data usage could be a problem when streaming lossless.

        Thanks for the tip about solutions when using mobile. Might use it in the future, but for now it will only be for my desktop, htpc and laptop.

        By the way, even when using –idle, -cache and -cache-min as arguments to mplayer I get errors with cache after a while. Have you been experiencing anything similar?

        “Cache not filling, consider increasing -cache and/or -cache-min!”

        It’s also kind of annoying to use high values for mplayer cache as it will take longer for it to respond to pauses done in ncmpcpp (or more correctly, by ncmpcpp).

        nvlc (or vlc -I ncurses) is an alternative which still gives you some more information that just cvlc, but it stops after longer pauses.

      • takla Says:

        I think I did sometimes run into cache errors with mplayer. These days I’m using mpv (see mpv.io) which is “..a fork of mplayer2 and MPlayer. It shares some features with the former projects while introducing many more.”

        A command for playing streaming flac audio from my mpd server (the mpd server is 192.168.1.3):

        mpv –idle –cache 512 http://192.168.1.3:8000

        This seems to work fine. mpv is very decent but if you have lots of aliases or scripts based on mplayer then it is quite a task to update them with mpv’s syntax, which is just (pointlessly imo) different enough to make me want to strangle its developers (I visualise this as being a more effective and satisfying means of expression than the traditional bug report). Stuff it is notably better at: gapless audio, colour fidelity in video.

        It might also be worth looking at pulse audio for its ability to act as a network sound server. I still use plain alsa as last time I tried pulse audio I ran into latency problems with game audio and also found that my rather low end Asus EeePC works beautifully with alsa but crackles and pops with pulse. That was quite a while ago and it’s worth revisiting these things to check for improvements but at the moment, for me, everything works as I like so my position is “if it ain’t broke….”.

      • timss Says:

        Right, I read about mpv a long time ago, but at that stage it didn’t look too serious/no real benefit over mplayer2+smplayer2.

        Tried it a little bit now (v0.5.1 from Debian Testing repos) and there was immediately a few things I noticed that I didn’t like.

        $ mpv –idle -cache 512 http://192.168.1.3:8000
        Playing: http://192.168.1.3:8000
        [libav/demuxer] wav: max_analyze_duration 5000000 reached
        File is not seekable, but there’s a cache: enabling seeking.
        [stream] Audio (+) –aid=1 (pcm_s16le)
        File tags:
        icy-notice1: This stream requires an audio player!
        icy-notice2: MPD – The music player daemon
        icy-name:
        icy-genre:
        icy-url: Set website in config
        icy-pub: 1
        icy-title: What I
        Video: no video
        AO: [pulse] 44100Hz stereo 2ch s16
        A: 00:01:09 / 00:25:21 (4%) Cache: 48.44%

        The title (icy-title) isn’t reported correctly, it is cut off because it includes a ‘ – the full album title is “What I’ve Always Waited for”. When it doesn’t include a ‘ it shows which is ok. Seems like there was previously an issue to show the title at all:

        https://github.com/mpv-player/mpv/issues/36

        I created a new issue for this apostrophe bug:

        https://github.com/mpv-player/mpv/issues/1071

        Moreover it spams a lot of silly metadata for each song played. Not a big problem as it will only run in the background, but I find it a little odd.

        https://github.com/mpv-player/mpv/issues/813

        On the plus side I haven’t had any cache issues so far. Probably going to be playing music all day long, so I’ll report back if I experience some issues.

      • takla Says:

        I just checked and I also noticed the apostrophe bug with icy-metadata. Great to see you opened a bug report and that it is fixed. I just built from git master and can confirm it now works as expected, for example:

        mpv --af-clr --idle --cache 512 http://192.168.1.3:8000 -ao alsa:device=fiio
        Playing: http://192.168.1.3:8000
        File is not seekable, but there's a cache: enabling seeking.
        [stream] Audio (+) --aid=1 (flac)
        File tags:
        icy-notice1:
        This stream requires an audio player!
        icy-notice2: MPD - The music player daemon
        icy-name: FLAC Stream
        icy-genre: Set genre in config
        icy-url: Set website in config
        icy-pub: 1
        icy-title: Boulevard de l'Independance - Toumani Diabaté's Symmetric Orchestra - Mali Sadio

      • timss Says:

        Cool. If you have an account on Github maybe you should notify the developer that the fix worked. If you don’t want to I could do it for you if you’d like.

        That being said, it doesn’t seem like my all of my problems are completely resolved yet. Now I’m struggling with the stream only having a duration of 00:25:21 (25m21s), and both mpv and vlc stops playing after this duration. I can’t find anything about it in the configuration files of mpd nor through Google. Any idea?

        $ mpv –idle -cache 512 http://host:8000
        #
        A: 00:22:41 / 00:25:21 (89%) Cache: 48.44%
        File tags:
        icy-notice1: This stream requires an audio player!
        icy-notice2: MPD – The music player daemon
        icy-name:
        icy-genre:
        icy-url:
        icy-pub: 1
        icy-title:
        A: 00:25:21 / 00:25:21 (99%) Cache: 48.44%
        [libav/audio] pcm_s16le: invalid PCM packet
        Error decoding audio.
        A: 00:25:21 / 00:25:21 (99%) Cache: 0.00%

        Keep in mind that the duration is exactly the same for not only mpv, but also VLC among others. It’s really annoying to have to restart my client ever 25 minutes. The amount of `-cache` does not matter, nor does `–idle ` help as you can see.

      • timss Says:

        Right as I posted I got a tip on #mpd@freenode to try a different encoder. Gave flac a shot and now it doesn’t seem to specify a duration/limit (00:00:00) and plays just fine.

        No specific reason I originally opted for PCM, just felt like a good choice as I have a lot of different music files, but since I set `format` I guess it didn’t matter either way…

        Time will tell if this is a final fix.

  2. Adrian Baugh Says:

    Hi, I have 2 machines running volumio (a frontend to mpd). I’ve tried your tip to make mpd output a pcm stream and it works from vlc. But when I go to another machine running mpd and tell mpd to play the stream coming fron the first one I get no sound out. Is there a way to persuade mpd to play back wav streams produced on another mpd instance?

    • takla Says:

      An mpd stream to a different machine needs a player on that remote machine. It’s the player, not the server, which renders the stream via the audio hardware. You just need a player which understands http streams – vlc is fine. The player will output the audio to the physical audio device.

      My understanding of what you wrote:

      the original audio stream is being output on volumio1. Let’s assume volumio1 is at 192.168.1.2 for the sake of an example, and assume it outputs its pcm wav stream on its local port 8000.

      Now assume volumio2 is on the same LAN but has an address 192.168.1.3. If you want to pass that audio stream from volumio1 to the physical audio output of volumio2 then what you need is not another instance of mpd but an audio player on volumio2 that can pass that stream to volumio2’s audio hardware. For example you could use, on volumio2, `mplayer -idle -cache 1024 http://192.168.1.2:8000` or `vlc http://192.168.1.2:8000`

      As for controlling mpd on 192.168.1.2 you can use any client that can access 192.168.1.2. That might be volumio2 or volumio1 (if they are attached to a display, keyboard etc.), it might be your phone, or a PC.

  3. sc Says:

    Thanks for the information, really helped out a lot! However, I am seeming my mplayer2 stream die when any of the following occurs:

    1. The next song has a different format than the first, for example 44.1khz 16-bit > 96khz 32-bit. However, if I restart mplayer2, it works fine.

    2. When I clear the playlist and add new tracks (may be related to the first?).

    3. When I manually play a new song (may be related to the second?)

    Any ideas why mplayer2 doesn’t like the switching of formats, or is it just my configuration?

    Thanks again,
    very helpful post!

    • takla Says:

      I think there are three possibilities:

      If your stream is being rendered by your audio device without a mixer such as dmix then, unless you have a pro soundcard capable of simultaneously using different sample rates and bit depths, any change of format within a single stream will cause a failure.

      If your stream is flac you define the sample rate and bit depth and number of channels:
      format "44100:16:2"
      or
      format "96000:24:2" (or whatever you need)

      so this issue doesn’t arise.

      If streaming wav you don’t have that facility with mpd’s httpd wav output, so you would have to make sure your audio passes through alsa’s dmix (or equivalent sound mixer) before the audio hardware renders it.

      Third possibility: mplayer/mplayer2/mpv might hang if there is an interruption or problem with buffering. You can use the mplayer option -idle (or –idle in mpv):

      from mpv man page:

      --idle Makes mpv wait idly instead of quitting when there is no file to play. Mostly useful in slave mode, where mpv can be controlled through input commands (see also --slave-broken).

      edit: also try using -idle with -cache, for example `mpv –idle –cache 1024` I find this works very well.

      mpv works noticably better than mplayer/mplayer2 in this respect (and others) and is worth switching to, or at least trying.

      • sc Says:

        Thanks, I decided on using the pulse output over LAN to connect to my laptop, which is connected via USB to my DAC. This has essentially 0 latency, and supports all formats.

        While this supports all formats I have encoded, I have opted to resample to CD specs, which is most of my stuff anyway… It doesn’t put a large burden on my ancient laptop. I will boost this up (if it even matters, my ears can’t tell a difference) to higher sample/rates…

    • Anonymous Says:

      always_on “yes”
      might help (for some of the cases).
      See http://www.musicpd.org/doc/user/config_audio_outputs.html

      • takla Says:

        I think the “always on” option addresses a slightly different situation and probably will not help in this case, however all useful and relevant info is gratefully received and passed on! Thanks for your helpful comments btw.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: