Playing sound over the network with Pipewire and ROC on Arch Linux

Table of Contents

Originally posted on 18 July 2023.

My homeserver is connected to a DAC and good (enough) speakers. I use it to play music using Logitech Media Server (which I highly recommend!).

I have been willing to be able to play sound from my laptop (henceforth "the client") on my homeserver (henceforth "the server") over the LAN smoothly for years now, especially when I (very seldom) watch films on it, because I don't want to use a second set of speakers. While both my laptop and my homeserver are connected to the network via Ethernet, Pulseaudio's native TCP module was always very slow and the sound was often out of sync. Moreover, I was never able to understand what the differences between its various network modules (simple-protocol? tunnel? native-tcp?) were.

Some time ago, I switched from Pulseaudio to Pipewire. This got me very confused, because I couldn't understand what needed to be configured on which side. For once, the Arch wiki was not very helpful, as its instructions did not work for me.

I gave it another go today, using ROC. And, much to my satisfaction, it worked perfectly out of the box. And it uses native Pipewire modules.

Tutorial

Here's a quick summary of what you need to do in order to achieve this if you use Pipewire on Arch Linux:

  • Install pipewire-roc both on the client and the server:

    sudo pacman -S pipewire-roc
    
  • On the server, add this to /etc/pipewire/pipewire.conf.d/roc-source.conf:

    context.modules = [
      {   name = libpipewire-module-roc-source
          args = {
              local.ip = 192.168.1.x
              resampler.profile = medium
              fec.code = rs8m
              sess.latency.msec = 100
              local.source.port = 4713
              local.repair.port = 4714
              source.name = "My server's speakers"
              source.props = {
                 node.name = "roc-source"
              }
          }
      }
    ]
    

Replace 192.168.1.x with the server's local IP and both 4713 and 4714 with the port numbers of your liking, making sure you have opened them in your server's firewall first.

  • On the client, add this to /etc/pipewire/pipewire.conf.d/roc-sink.conf:

      context.modules = [
        {  name = libpipewire-module-roc-sink
           args = {
                fec.code = rs8m
                remote.ip = 192.168.1.x
                remote.source.port = 4713
                remote.repair.port = 4714
                sink.name = "My laptop's soundcard"
                sink.props = { node.name = "roc-sink" }
           }
       }
    ]
    

    Again, specify the IP and ports accordingly.

    • Restart Pipewire both on the server and client:

      systemctl --user restart pipewire
      

Now look at the list of sinks on your laptop, using pavucontrol for instance (I use Gnome Shell's sound menu for that). You'll see a new ROC sink. Select it and enjoy your new sound output!

Related links and acknowledgements

  • roc-droid is an Android app which allows a phone to become a roc sender or receiver (and it works!).
  • This article by the developer of roc inspired this one.

Index page
Last updated on 10 September 2023.
Created with Emacs and Org.
CSS: Carrara.
Page hosted on Sourcehut Pages.

Public inbox: ~e-v/edgar-vincent-public-inbox@lists.sr.ht