Trouble loading Pipewire ROC module

Hi everyone!

I’m having a hard time configuring the Pipewire ROC module. I have this is my configuration.nix:

    environment.systemPackages = with pkgs; [
       roc-toolkit
];

## Pipewire
  # rtkit is optional but recommended
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
  };

  # Configure ROC module.
  services.pipewire.extraConfig.pipewire = {
    roc-sink = {
      context.modules = [
        {
          name = "libpipewire-module-roc-sink";
          args = {
            fec.code = "rs8m";
            remote.ip = "192.168.1.27";
            remote.source.port = 4713;
            remote.repair.port = 4714;
            sink.name = "ev-nixos sound output";
            source.props = {
              node.name = "roc-sink";
            };
          };
        }
      ];
    };
  };

The machine running over at 192.168.1.27 is also running NixOS, with a similar configuration (albeit for a Pipewire source rather than a sink).

No matter what I do, the ROC module is not listed by pw-cli list-objects:

ev@ev-nixos /nix $ pw-cli list-objects Module 
	id 1, type PipeWire:Interface:Module/3
 		object.serial = "1"
 		module.name = "libpipewire-module-rt"
	id 2, type PipeWire:Interface:Module/3
 		object.serial = "2"
 		module.name = "libpipewire-module-protocol-native"
	id 4, type PipeWire:Interface:Module/3
 		object.serial = "4"
 		module.name = "libpipewire-module-profiler"
	id 6, type PipeWire:Interface:Module/3
 		object.serial = "6"
 		module.name = "libpipewire-module-metadata"
	id 8, type PipeWire:Interface:Module/3
 		object.serial = "8"
 		module.name = "libpipewire-module-spa-device-factory"
	id 10, type PipeWire:Interface:Module/3
 		object.serial = "10"
 		module.name = "libpipewire-module-spa-node-factory"
	id 12, type PipeWire:Interface:Module/3
 		object.serial = "12"
 		module.name = "libpipewire-module-client-node"
	id 14, type PipeWire:Interface:Module/3
 		object.serial = "14"
 		module.name = "libpipewire-module-client-device"
	id 16, type PipeWire:Interface:Module/3
 		object.serial = "16"
 		module.name = "libpipewire-module-portal"
	id 17, type PipeWire:Interface:Module/3
 		object.serial = "17"
 		module.name = "libpipewire-module-access"
	id 18, type PipeWire:Interface:Module/3
 		object.serial = "18"
 		module.name = "libpipewire-module-adapter"
	id 20, type PipeWire:Interface:Module/3
 		object.serial = "20"
 		module.name = "libpipewire-module-link-factory"
	id 22, type PipeWire:Interface:Module/3
 		object.serial = "22"
 		module.name = "libpipewire-module-session-manager"
	id 29, type PipeWire:Interface:Module/3
 		object.serial = "30"
 		module.name = "libpipewire-module-jackdbus-detect"

journalctl --user -u pipewire.service just returns:

Feb 14 16:26:48 ev-nixos systemd[1955]: Started PipeWire Multimedia Service.

Loading the module manually doesn’t seem to work either:

ev@ev-nixos ~ $ pw-cli load-module libpipewire-module-roc-sink
Error: "Could not load module"

My machine is running (a recently updated) NixOS unstable installation.
What am I doing wrong?

Thanks a lot!

EV

Probably the main issue is putting roc-toolkit in your systemPackages is not actually exposing the PW module for PW to use. So, remove that.

Interestingly, pw is built with roc support by default:

And I even see pw is actually building the corresponding modules:

[962/1114] Linking target src/modules/libpipewire-module-roc-source.so
[963/1114] Linking target src/modules/libpipewire-module-roc-sink.so

So I’m personally not sure how to debug that part further.

Thanks for your reply.

I forgot to mention that I didn’t originally include the roc-toolkit package, and I had the same issue.

I only added it because this article Roc Toolkit 0.4 + updated tutorial for live audio streaming mentions it.

Thanks again!

I’ve managed to solve this. The issue was seemingly caused by a wrong syntax.

Here is the working configuration, if it can be of any help:

  • On the server:
  services.pipewire = {
    enable = true;
    pulse.enable = true;
    systemWide = true;
  };
  services.pipewire.extraConfig.pipewire = {
    "10-roc-source" = {
      "context.modules" = [
        {
          "name" = "libpipewire-module-roc-source";
          "args" = {
            "fec.code" = "rs8m";
            "local.ip" = "192.168.1.27";
            "resampler.profile" = "medium";
            "local.source.port" = "4713";
            "local.repair.port" = "4714";
            "source.name" = "remote soundcard";
            "source.props.node.name" = "roc-source";
          };
        }
      ];
    };
  };
  networking.firewall = {
    allowedTCPPorts = [
      # pipewire-roc
      4713
      4714
    ];
    allowedUDPPorts = [
      # pipewire-roc
      4713
      4714
    ];
  };

  • On the client:
# configuration.nix
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
  };

# home-manager configuration
  xdg.configFile."pipewire/pipewire.conf.d/10-roc-sink.conf" = {
    text = ''
      context.modules = [
        {
          name = "libpipewire-module-roc-sink"
          args = {
            fec.code = "rs8m"
            remote.ip = "192.168.1.27"  # Server IP
            remote.source.port = "4713"  # Source port on the server
            remote.repair.port = "4714"  # Repair port on the server
            sink.name = "remote sound output"  # Sink name
            sink.props.node.name = "roc-sink"  # Node name for the sink
          }
        }
      ]
    '';
  };