How to stream my GNU/Linux audio output to Android devices over WI-FI?

Solution 1:

There is a very simple solution because PulseAudio already has all the necessary tools.

  1. Get your source device name with command pactl list | grep Name
  2. Create the following script named pashare:

    #!/bin/sh
    case "$1" in
      start)
        $0 stop 
        pactl load-module module-simple-protocol-tcp rate=48000 format=s16le channels=2 source=<source_name_here> record=true port=8000
        ;;
      stop)
        pactl unload-module `pactl list | grep tcp -B1 | grep M | sed 's/[^0-9]//g'`
        ;;
      *)
        echo "Usage: $0 start|stop" >&2
        ;;
    esac
    
  3. Make some checks and preparations (to allow script execution and check if the port successfully opened):

    chmod 755 pashare
    ./pashare start
    netstat -nlt | grep 8000 
    telnet 127.0.0.1 8000
    
  4. Download and install PulseDroid.apk

  5. Launch app on your phone; set the IP address to your computer and the port to 8000.

P.S. You can also check this Wiki page for general information on Pulseaudio network streaming, and this Wiki page about RTP streaming. Don't expect too much from streaming raw audio over WiFi; it takes enormous gobs of bandwidth. Even with a high-end wireless router/AP with a powerful signal I haven't been able to get more than stuttering audio out of it. Your best bet is probably to setup a proper media server (like Rygel, which works well with Pulseaudio) to transcode the raw audio to something like MP3 and stream that instead.

Solution 2:

You can use VLC to serve a MP3 stream of pulseaudio's output via HTTP.
The main advantage is that you don't need to install any special software on your remote device, a web browser (or music player) is all you need to play the stream. The downside is that it's audio only, a few seconds lag make it useless for videos

  1. Find pulseaudio's output name with:

    pactl list | grep "Monitor Source" 
    
  2. Start the VLC http server, replacing XXXX by your output name:

    cvlc -vvv pulse://XXXX --sout '#transcode{acodec=mp3,ab=128,channels=2}:standard{access=http,dst=0.0.0.0:8888/pc.mp3}'
    
  3. If needed, find your local IP address with ifconfig

  4. On your remote device, point the browser (or audio streaming app) to:

    http://your.local.ip.address:8888/pc.mp3
    

Note: The stream isn't affected by the volume set on the server, unless you totally mute it. If needed, you can keep the level just a tiny bit above 0 to only hear the remote device.


The first two steps combined into one by polynomial_donut:

cvlc -vvv pulse://$(pactl list | grep "Monitor Source" | awk '{print $3}') --sout '#transcode{acodec=mp3,ab=128,channels=2}:standard{access=http,dst=0.0.0.0:8888/pc.mp3}'