Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Register
  • Sign in
  • pipewire pipewire
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 608
    • Issues 608
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 25
    • Merge requests 25
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar

Due to an influx of spam, we have had to impose restrictions on new accounts. Please see this wiki page for instructions on how to get full permissions. Sorry for the inconvenience.

  • PipeWirePipeWire
  • pipewirepipewire
  • Issues
  • #2939
Closed
Open
Issue created Jan 07, 2023 by Jost-Philip@Jost-Philip

libpipewire-module-echo-cancel ignores capture.props and playback.props in configuration file

  • PipeWire version (pipewire --version): 0.3.63
  • Distribution and distribution version (PRETTY_NAME from /etc/os-release): Arch Linux
  • Desktop Environment: Gnome
  • Kernel version (uname -r): 6.1.3-arch1-1

Description of Problem:

libpipewire-module-echo-cancel can be loaded from various configuration files in a similar fashion as other modules creating virtual devices (filter-chain, loopback, etc.). When loaded, it creates a virtual sink and a virtual source that can be used for echo cancellation when using speakerphone applications.

While libpipewire-module-echo-cancel does understand the module-specific properties source.props = {} and sink.props = {} to influence the appearance of the (application-facing) virtual source and sink it creates, it completely ignores the otherwise common (hardware-facing) capture.props = {} and playback.props = {} sections, even if they are present in the configuration file loading the module.

This means that the streams connecting to the physical (real) microphone and speaker will always be automatically connected to the first ports of the default playback and capture devices at the time of module load, and there is no documented way to influence that automatic behavior.

I understand why and can accept that using these ports is the default behavior since it makes initial setup easy for "standard" layouts, but in non-trivial environments with multiple and multichannel I/Os this default usually does not produce the desired audio graph.

Modifying the links after the module is loaded (using for example pw-link) does function as a workaround, but gets cumbersome when the underlying devices disappear and re-appear mid-flight. It also poses challenges in timing, because the workaround has to be executed after every module (re-)load, but before anything starts using the echo-cancel-device.

How Reproducible:

Always. This is the implemented and documented behavior. It's not "broken", it's just "bad".

Steps to Reproduce:

  1. Create a working pipewire setup which has multiple input and output devices (preferably with multiple channels, too)
  2. include libpipewire-module-echo-cancel into one of the configuration files, for example client.conf, using the snipped below (taken from the official documentation), and extend it to also include capture.props = {} and playback.props = {} sections like below:
  {   name = libpipewire-module-echo-cancel
      args = {
          library.name  = aec/libspa-aec-webrtc
          aec.args = {
              webrtc.gain_control = true
          }
          source.props = {
             # This is the virtual input device available to applications.
             # It will route the processed microphone signal to the application recording it.
             node.name = "Echo Cancellation MySource"
             node.description = "Echo Cancellation MySource"
          }
#           module-echo-cancel seems to completely ignore this argument and just use the first two channels of the default device
          capture.props = {
             # This is where the raw local microphone signal is really coming from
             # It should be connected to real local hardware microphones
             node.name = "Echo Cancellation MyCapture"
             node.description = "Echo Cancellation MyCapture"
             audio.channels = 2
             audio.position = [ AUX7 AUX6 ]
             target.object = "alsa_input.usb-Focusrite_Scarlett_18i20_USB_03020534-00.multichannel-input"
#           }
          sink.props = {
             # This is the virtual output device available to applications.
             # It is what the communication application should use to play sound locally.
             node.name = "Echo Cancellation MySink"
             node.description "Echo Cancellation MySink"
          }
#           module-echo-cancel seems to completely ignore this argument and just use the first two channels of the default device (01/2023)
          playback.props = {
              # This is the local speaker we are really sending the audio to that is coming from the application.
              # Note that ideally this should be a real hardware audio output, that is on the same clock as the real hardware microphones!
              node.name = "Echo Cancellation MyPlayback"
              node.description "Echo Cancellation MyPlayback"
              node.passive = true
              audio.channels = 2
           audio.position = [ AUX3 AUX2 ]
           target.object = "alsa_output.usb-Focusrite_Scarlett_18i20_USB_03020534-00.multichannel-output"
         }
  }
  1. update audio.position and target.object in the playback.props and the capture.props section according to your local setup, choose something other than your default playback/capture devices
  2. load the configuration

Actual Results:

module-echo-cancel is loaded and connects to the first ports of the default capture and playback devices, regardless of configured target in playback.props and capture.props.

Expected Results:

module-echo-cancel should honor the configuration in playback.props and capture.props and connect to the ports specified there, similar to how other modules behave, so non-trivial setups can be properly automated.

Edited Jan 07, 2023 by Jost-Philip
Assignee
Assign to
Time tracking