[PIPEWIRE] Unable to set filter chain via configuration.nix

Still can set manually using ~/.config/pipewire/filter-chain.conf.d/

could be related to upgrade from pipewire 0.3.54 to 0.3.55 breaks rnnoise filter.

using config.nix :

[E][00454.453782] pw.core      | [          core.c:  382 core_new()] 0x55d9e22e90f0: can't find protocol 'PipeWire:Protocol:Native': Operation not supported
[E][00454.453850] mod.filter-chain | [module-filter-ch: 2235 pipewire__module_init()] can't connect: Operation not supported
[E][00454.454058] pw.conf      | [          conf.c:  560 load_module()] 0x55d9e2283720: could not load mandatory module "libpipewire-module-filter-chain": Operation not supported
[E][00454.454133] default      | [      pipewire.c:  125 main()] failed to create context: Operation not supported

pipewire_conf.nix

{ config, pkgs, ... }:

{


services.pipewire.config.pipewire = {

  "context.properties"= {
    "link.max-buffers"= 16;
    "core.daemon"= true;
    "core.name"= "pipewire-0";
    "settings.check-quantum"= true;
    "settings.check-rate"= true;
#    "log.level"= 0;
    "vm.overrides"= {
      "default.clock.min-quantum"= 1024;
    };
  };
  "context.spa-libs"= {
    "audio.convert.*"= "audioconvert/libspa-audioconvert";
    "api.alsa.*"= "alsa/libspa-alsa";
    "support.*"= "support/libspa-support";
    "api.v4l2.*" = "v4l2/libspa-v4l2";
    "api.libcamera.*" = "libcamera/libspa-libcamera";
    "api.bluez5.*" = "bluez5/libspa-bluez5";
    "api.vulkan.*" = "vulkan/libspa-vulkan";
    "api.jack.*" = "jack/libspa-jack";
  };
  "context.modules"= [

###MICFILTER
    { "name" = "libpipewire-module-filter-chain";
        "args" = {
            "node.description" = "Noise Canceling source";
            "media.name"       = "Noise Canceling source";
            "filter.graph" = {
                "nodes" = [
                    {
                        "type"   = "ladspa";
                        "name"   = "rnnoise";
                        "plugin" = "${pkgs.rnnoise-plugin}/lib/ladspa/librnnoise_ladspa.so";
                        "label"  = "noise_suppressor_stereo";
                        "control" = {
                            "VAD Threshold (%)" = 50.0;
                        };
                    }
                ];
            };
            "audio.position" = [ "FL" "FR" ];
            "capture.props" = {
                "node.name" = "effect_input.rnnoise";
                "node.passive" = true;
            };
            "playback.props" = {
                "node.name" = "effect_output.rnnoise";
                "media.class" = "Audio/Source";
            };
        };
    }
###     


{
      "name"= "libpipewire-module-rt";
      "args"= {
        "nice.level"= -11;
      };
      "flags"= [
        "ifexists"
        "nofail"
      ];
    }
    {
      "name"= "libpipewire-module-protocol-native";
    }
    {
      "name"= "libpipewire-module-profiler";
    }
    {
      "name"= "libpipewire-module-metadata";
    }
    {
      "name"= "libpipewire-module-spa-node-factory";
    }
    {
      "name"= "libpipewire-module-client-node";
    }
    {
      "name"= "libpipewire-module-access";
      "args"= {};
    }
    {
      "name"= "libpipewire-module-adapter";
    }
    {
      "name"= "libpipewire-module-link-factory";
    }
  ];
  "context.objects"= [

    {
      "factory"= "spa-node-factory";
      "args"= {
        "factory.name"= "support.node.driver";
        "node.name"= "Dummy-Driver";
        "node.group"= "pipewire.dummy";
        "priority.driver"= 20000;
      };
    }
    {
      "factory"= "spa-node-factory";
      "args"= {
        "factory.name"= "support.node.driver";
        "node.name"= "Freewheel-Driver";
        "priority.driver"= 19000;
        "node.group"= "pipewire.freewheel";
        "node.freewheel"= true;
      };
    }
   
  ];
  "context.exec"= [];
};


}


1 Like

Solved

{ config, pkgs, ... }:

let
  json = pkgs.formats.json {};
  pw_rnnoise_config = {
  "context.modules"= [
    { "name" = "libpipewire-module-filter-chain";
        "args" = {
            "node.description" = "Noise Canceling source";
            "media.name"       = "Noise Canceling source";
            "filter.graph" = {
                "nodes" = [
                    {
                        "type"   = "ladspa";
                        "name"   = "rnnoise";
                        "plugin" = "${pkgs.rnnoise-plugin}/lib/ladspa/librnnoise_ladspa.so";
                        "label"  = "noise_suppressor_stereo";
                        "control" = {
                            "VAD Threshold (%)" = 50.0;
                        };
                    }
                ];
            };
            "audio.position" = [ "FL" "FR" ];
            "capture.props" = {
                "node.name" = "effect_input.rnnoise";
                "node.passive" = true;
            };
            "playback.props" = {
                "node.name" = "effect_output.rnnoise";
                "media.class" = "Audio/Source";
            };
        };
    }
];
};
in
{
  environment.etc."pipewire/pipewire.conf.d/99-input-denoising.conf" = {
      source = json.generate "99-input-denoising.conf" pw_rnnoise_config;
		};
}

1 Like

I’m having the same kind of issues to configure upmixing. Would you mind explaining what makes your solution work? Is it the conversion to (or from?) JSON?

Not my solution, I got it from here

It generates a valid pipewire split configuration file(json) based on the nix formatted input.

[lucio@inferno:/etc/pipewire/pipewire.conf.d]$ cat 99-input-denoising.conf 
{
  "context.modules": [
    {
      "args": {
        "audio.position": [
          "FL",
          "FR"
        ],
        "capture.props": {
          "node.name": "effect_input.rnnoise",
          "node.passive": true
        },
        "filter.graph": {
          "nodes": [
            {
              "control": {
                "VAD Threshold (%)": 50
              },
              "label": "noise_suppressor_stereo",
              "name": "rnnoise",
              "plugin": "/nix/store/4gm0d54brzdfl746qjkxv6hcfrq1mrl3-rnnoise-plugin-0.91/lib/ladspa/librnnoise_ladspa.so",
              "type": "ladspa"
            }
          ]
        },
        "media.name": "Noise Canceling source",
        "node.description": "Noise Canceling source",
        "playback.props": {
          "media.class": "Audio/Source",
          "node.name": "effect_output.rnnoise"
        }
      },
      "name": "libpipewire-module-filter-chain"
    }
  ]
}


1 Like

Thanks for the answer. I realize that in fact, my issue seems unrelated. Pipewire just does not take into account my changes in /etc/pipewire/client.conf or /etc/pipewire/pipewire-pulse.conf.

1 Like

You could try adding a new file with only the override changings inside /etc/pipewire/client.conf.d/ and /etc/pipewire/pipewire-pulse.conf.d/ directories , not sure if they’re all valid paths actually.

My client.conf and pipewire-pulse.conf ended up being applied, but I don’t know what made it work; from my point of view it randomly started working as I expected.

Could be some update fixing it, i’m running unstable.