59

Is there a way to stream the live output of the soundcard from our 12.04.1 LTS amd64 desktop to a DLNA-compliant external device in our network? Selecting media content in shared directories using Rygel, miniDLNA, and uShare is always fine - but so far we completely failed to get a live audio stream to a client via DLNA.

Pulseaudio claims to have a DLNA/UPnP media server that together with Rygel is supposed to do just this. But we were unable to get it running.

We followed the steps outlined in live.gnome.org, this answer here, and also in another similar guide.


In 12.04 LTS we can select the local audio device, or our GST-Launch stream in the DLNA client but Rygel displays the following message and the client states it reached the end of the playlist:

(rygel:7380): Rygel-WARNING **: rygel-http-request.vala:97: Invalid seek request

There was no way to listen to live audio streams on the client.


Only after a distribution upgrade to 14.04 LTS we were able to select a live stream on our DLNA renderers from settings nicely outlined in below answer. Still, we needed to select an established stream after we started rygel and were unable to push a new stream to our UPnP devices. Audio metadata were not transmitted.


Are there any other alternatives for sending the audio of our soundcard as live stream to a DLNA client?

4
  • Can you avoid DLNA streaming with your receiver device? My solution is to pass the pulseaudio stream over HTTP, see more here: sandalov.org/blog/1441 Oct 31, 2012 at 21:36
  • Sorry, no, I really do want DLNA to work because DLNA only is widely implemented on various clients (TVs, AV-receivers, Blueray players, etc.).
    – Takkat
    Oct 31, 2012 at 22:03
  • Takkat, the solution I am talking about solved the problem of streaming to my AVR. If you really want to launch a DLNA server, I had a positive experience with rygel+pulseaudio on 12.04 (after 'pacmd load-module module-http-protocol-tcp'), on 12.10 I received the same 'Invalid seek request' warnings. Nov 1, 2012 at 6:54
  • @DmitrySandalov: it would be really cool if you shared details on how you succeeded to set up Rygel to live stream the pulseaudio output.
    – Takkat
    Nov 1, 2012 at 9:40

7 Answers 7

69
+400

Pulseaudio-DLNA

I created a little server which discovers all upnp renderers in your network and adds them as sinks to pulseaudio. So you can control every application via pavucontrol to play on your upnp devices.

That's the kind of comfort I always wanted when dealing with upnp devices under linux.

The application can be installed from source or DEB package downloadable from git, or after we had added the project's official ppa:qos/pulseaudio-dlna to our sources with:

sudo apt-get update && sudo apt-get install pulseaudio-dlna

We then run pulseaudio-dlna from the command line with following options:

pulseaudio-dlna [--host <host>] [--port <port>] [--encoder <encoder>] [--renderer-urls <urls>] [--debug]
pulseaudio-dlna [-h | --help | --version]

See also the pulseaudio-dlna "About" for more.

When there was a DLNA renderer present we can then select it from the sound menu as an output sink:

enter image description here

5
  • 3
    Great application - thank you! Worked fine on my devices including a Samsung Smart TV (UE40ES6100). Just a note: we also needed python-requests as a dependency and we could select the renderer from default audio controls - no need to install pavucontrol.
    – Takkat
    Jan 5, 2015 at 16:55
  • Glad you like it. I just updated the README. Thanks for the hint!
    – Massimo
    Jan 5, 2015 at 18:59
  • 3
    Great solution. Thanks. But I have one question: There is a playback delay of several seconds (10 secs after pressing pause in VLC). Is this a DLNA "feature" or is there any way to reduce it? So DLNA does not make sense for video playback or gaming? :(
    – JPT
    Aug 10, 2015 at 8:35
  • 2
    The delay comes from filling the HTTP buffer. It keeps the stream playing in case your connection has issues (weak wifi, etc.). If you want to reduce the delay, use a codec which needs much bandwidth (wav) to fill that buffer faster. Cable connection always helps. Otherwise this is very specific to your manufacturers firmware implementation. E.g. i have a delay with Cocy about 1 second. Sonos Play 1 with wav: 1 second, with mp3: 5 seconds. All connected via cable. But you won't get rid of it completely. Main purpose is music and audio books. Everything what does not need to be in sync.
    – Massimo
    Aug 20, 2015 at 9:03
  • 1
    @JPT and everyone else looking for a way to fix the delay (10s for me): Using shairport-sync I'm running an AirPlay sink on my RaspberryPi in parallel to the DLNA sink and must say that the delays are much shorter (~2s to start up; stopping is immediate). That being said, thanks a lot to Massimo because, forgetting about the delay, pulseaudio-dlna works like a charm and really is trivial to install! (AirPlay was quite a bit harder to set up for me.)
    – balu
    Sep 7, 2018 at 1:58
8

Pavucontrol is the missing item in this jigsaw puzzle! I had also set up everything correctly and the external device(LG TV) was showing that the sound was being played but I did not hear any sound. Today I installed pavucontrol and when I opened it I found the option to channel sound through the DLNA server. The DLNA option is only shown when there is sound output from a player to pulseaudio. enter image description here

5
  • Thank you for sharing this. How did you set up the DLNA server? For me atm Rygel quits with rather unhelpful segfaults.
    – Takkat
    Dec 22, 2012 at 14:31
  • I have just normal settings. I followed the same link as you have mentioned in your post.[GstLaunch] enabled=true launch-items=audiotestsrc; audiotestsrc-title=Desktop Live Streaming! audiotestsrc-mime=audio/mpeg audiotestsrc-launch=pulsesrc device=upnp.monitor ! lamemp3enc target=quality quality=6
    – jumbli
    Dec 22, 2012 at 16:10
  • Weird. With Rhythmbox the segfaults have disappeared but I still only get Invalid seek request from Rygel. Media directories are there but my GST-stream is always EOF.
    – Takkat
    Dec 22, 2012 at 16:50
  • Great addition, it lets you set a sink for each app that can play audio! I can listen to music on my big stereo, and keep videos or game sounds on my computer. Thanks! Feb 27, 2018 at 15:02
  • This solved my issue when all was connectedn and playing but just sound was missing!
    – easwee
    Jul 4, 2019 at 12:43
4

I'm sorry I can't help you with Rygel at all, but there may be an alternative which may work for you.

The principle is get a program to record the stream to an audiofile, then launch miniDLNA with a custom config which points to the directory that stream is in.

Example: Say we're working in ~/stream/. Create ~/stream/minidlna.conf

network_interface=wlan0
media_dir=/home/<user>/stream/
friendly_name=Live Audio Stream
db_dir=/home/<user>/stream/
album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg
inotify=no
enable_tivo=no
strict_dlna=no
notify_interval=900
serial=12345678
model_number=1

Then save the stream to an audiofile in that directory. Googling for "FFmpeg record sound card audio" yielded this command

ffmpeg -f alsa -i default -acodec flac ~/stream/OutputStream.flac

but I didn't have much luck with it. Another option is vlc is you have a GUI available and this doesn't work.

Then boot up miniDLNA in another terminal window:

minidlna -d -f ~/stream/minidlna.conf -P ~/stream/minidlna.pid

It should locate OutputStream.flac and then be accessible from your network device.

Hopefully if you haven't already got it solved that's given you a few ideas.

4
  • 1
    Promising approach - thank you - but it needs further refinement. With a quick test with miniDLNA today I couldn't get the stream file recognized by my DLNA client. In addition the streams produced by ffmpeg seem to be rather poor (static noise). I'm at it and let you know.
    – Takkat
    Oct 16, 2012 at 21:02
  • So far we are able to generate a flac or mp3 audio file from the audio sink with ffmpeg or avconv. However this file will not be recognized by miniDLNA unless we quit recording. Thenafter we can open this file again on the DLNA client while recording another instance but the stream always starts from the beginnning of the recording and stops at the time it was when we started listening on the client. Any ideas how to overcome this?
    – Takkat
    Oct 27, 2012 at 15:32
  • So, do you mean once you've broken off the ffmpeg process to stop recording, only then is the file recognized by miniDLNA? Also, is the audio quality any better? I'll try it out on my machine and see if I can get it going again. (I had something similar working last year for transcoding movies on the fly)
    – Marcus
    Oct 27, 2012 at 16:34
  • Yeah in the first place. Second time I can acess it from the client but it starts from the beginning (i.e. whenever I started recording) and stops in the middle (ie. after exactly the time between start recording and start receiving on the client). Audio is fine now, had to disable duplex.
    – Takkat
    Oct 27, 2012 at 16:37
4

One idea I had to stream "what I hear" to a DLNA renderer (like WDTV) was to server the stream with VLC as http stream with pulse://alsa_output.xxx.monitor as input and transcode it to MP3 or FLAC. Then I wanted to use some DLNA control point to let the renderer play taht stream. VLC does serve the transcoded stream correctly, but it does not allow to set the mime type, so the renderer refuses to play it.

The next idea was to write a http server in python that serves the stream instead. It gets the audio stream from pulse with parec, encodes it with flac (or lame or whatever you want) and sets the mime type correctly.

It works with the following (very simple) script:

#!/usr/bin/python

import BaseHTTPServer
import SocketServer
import subprocess

PORT = 8080
# run "pactl list short |grep monitor" to see what monitors are available
# you may add a null sink for streaming, so that what is streamed is not played back locally
# add null sink with "pactl load-module module-null-sink"
MONITOR = 'null.monitor'
MIMETYPE = 'audio/flac'
ENCODER = 'flac - -c --channels 2 --bps 16 --sample-rate 44100 --endian little --sign signed'
BUFFER = 65536

class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_HEAD(s):
    print s.client_address, s.path, s.command
    s.send_response(200)
    s.send_header('content-type', MIMETYPE)
    s.end_headers()
def do_GET(s):
    s.do_HEAD()
    pa = subprocess.Popen('parec -d {} | {}'.format(MONITOR, ENCODER), shell = True, bufsize = BUFFER, stdout = subprocess.PIPE)
    while True:
        data = pa.stdout.read(1024)
        if len(data) == 0: break
        s.wfile.write(data)
    print 'stream closed'


httpd = SocketServer.TCPServer(("", PORT), Handler)

print "listening on port", PORT

try:
httpd.serve_forever()
except KeyboardInterrupt:
pass

httpd.server_close()

Adjust the parameters, run it, and point the DLNA renderer to your machine. It worked for me with a WDTV as renderer and an Android phone with BubbleUPnP as control point (You can type in the stream URL when adding a new item to the playlist manually). But it should work with any DLNA compliant devices.

4

NOTE: This solution works, but a newer and probably better solution has been proposed by Massimo.

Here's an answer for Ubuntu 14.04 (also tested and working on 15.04), for completeness:

  1. install any needed packages: sudo apt-get install rygel rygel-preferences rygel-gst-launch

  2. create the file ~/.config/rygel.conf that contains the following:

    [GstLaunch]
    enabled=true
    title=@REALNAME@'s stream
    launch-items=myaudioflac;myaudiompeg
    
    myaudioflac-title=FLAC audio on @HOSTNAME@
    myaudioflac-mime=audio/flac
    myaudioflac-launch=pulsesrc device=upnp.monitor ! flacenc quality=8
    
    myaudiompeg-title=MPEG audio on @HOSTNAME@
    myaudiompeg-mime=audio/mpeg
    myaudiompeg-launch=pulsesrc device=upnp.monitor ! lamemp3enc target=quality quality=6
    
    [Playbin]
    enabled=true
    title=Audio/Video playback on @REALNAME@'s computer
    
    [general]
    interface=
    upnp-enabled=true
    
    [MediaExport]
    uris=
    
  3. Execute the following commands from the commandline (these could be put into a script if desired):

    pactl load-module module-http-protocol-tcp
    pactl load-module module-rygel-media-server 
    rygel &
    
  4. Run the paprefs command, and ensure that both DLNA options are enabled (checked) on the "Network Server" tab.

  5. Play some audio on your computer. Run the pavucontrol program, and on the "Playback" tab, change the output device to "DLNA/UPnP Streaming".

At this point, you should be able to play the MPEG and FLAC streams from a DLNA client (renderer / control point).

NOTE: you may need to restart your computer (or restart pulse) in order for things to begin to work.

3

The python script from Adam is just what I needed. Brilliant. Rygel with gst-launch doesn't work with one of my renderers, but this script works with both. In my case I'm taking an audio stream input from squeezelite (for squeezebox) and sending to a renderer. The script also works in the original form to take input from a pulseaudio monitor if that's what is needed.

Knowing little about any of this I managed to make some additions to the script that:

i) allow it to be run from a shell script and be terminated with a SIGTERM/SIGKILL (the 'except' statement now includes 'systemexit')

ii) allows the script to be stopped and restarted and re-use the same port (as it was the restarted script tended to fail saying it could not open the port if the renderer still had it open) - (the allow_reuse_address = True statement)

iii) make a version that takes input from stdin and resamples it using sox to output in wav format (on port 8082)

So my version looks like:

#!/usr/bin/python

import BaseHTTPServer
import SocketServer
import subprocess

PORT = 8082

MIMETYPE = 'audio/x-wav'
BUFFER = 65536

class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
  def do_HEAD(s):
    print s.client_address, s.path, s.command
    s.send_response(200)
    s.send_header('content-type', MIMETYPE)
    s.end_headers()
  def do_GET(s):
    s.do_HEAD()
    pa = subprocess.Popen('sox -t raw -r 96000 -b 24 -L -e signed -c 2 - -t wav -r 44100 -b 16 -L -e signed -c 2 - ', shell = True, bufsize = BUFFER, stdout = subprocess.PIPE)
    while True:
        data = pa.stdout.read(1024)
        if len(data) == 0: break
        s.wfile.write(data)
    print 'stream closed'

SocketServer.TCPServer.allow_reuse_address = True
httpd = SocketServer.TCPServer(("", PORT), Handler)

print "listening on port", PORT

try:
 httpd.serve_forever()

except (KeyboardInterrupt, SystemExit):
 pass

httpd.server_close()
2
  • 1
    I have found a few minor issues with this script.
    – pastim
    Jun 9, 2014 at 21:22
  • @Adam - After several trials I found a few minor issues with this program. However, the biggest problem is that streaming stops with error 32 (Broken pipe) after a time that is in direct proportion to the amount of data sent. For a 24/96000 quality stream this is just over an hour. At 24/192000 it is a little over 30 minutes. For CD quality somewhat over 3 hours. By selecting the stream again on the renderer the stream starts again. I believe the solution may be 'chunked encoding'. I wondered if anyone has produced a chunked version.
    – pastim
    Jun 9, 2014 at 21:30
1

Not sure if this is will be useful for you now, but I written a post about getting this to work on Ubuntu 12.10:

http://dpc.ucore.info/blog/2012/11/07/dlna-streaming-in-ubuntu-12-dot-10/

5
  • Thank you for sharing this - its exactly what so far always failed with me. From this site's design we'd like to encourage you to outlined the steps you took (in addition to just posting the link to your blog) because links may disappear over time thus leaving your answer useless. I'll get back to you as soon as I was able to test this.
    – Takkat
    Nov 7, 2012 at 7:27
  • Here's my observations so far: Following your guide crashes Rygel with SEGFAULT when selecting the audio stream from the client in 12.04. In 12.10 we are unable to create a stream with GST-Launch. Anything missing?
    – Takkat
    Nov 8, 2012 at 11:41
  • The question was about 12.04 and this answer is for Ubuntu 12.10, otherwise I'd vote it up. :)
    – jdthood
    Nov 28, 2012 at 15:24
  • Person from the future here: that link has rotted. :P
    – datashaman
    Aug 14, 2015 at 20:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .