Skip to content

Add ENABLE_ECHO_CANCEL env var for Docker AEC setup#260

Open
interkelstar wants to merge 7 commits into
OHF-Voice:mainfrom
interkelstar:feat/docker-aec-env-var
Open

Add ENABLE_ECHO_CANCEL env var for Docker AEC setup#260
interkelstar wants to merge 7 commits into
OHF-Voice:mainfrom
interkelstar:feat/docker-aec-env-var

Conversation

@interkelstar
Copy link
Copy Markdown
Contributor

The AEC setup documented in docs/enabling_aec.md (#254) requires Docker users to manually SSH into the host, run pactl commands, and configure AUDIO_INPUT_DEVICE by hand — steps that don't persist across PulseAudio restarts and are easy to miss.

This PR adds a single ENABLE_ECHO_CANCEL=1 env var that automates exactly the setup the documentation already describes, with no new concepts introduced.

When enabled, the Docker entrypoint:

  1. Loads module-echo-cancel with source_name=aec_mic aec_method=webrtc — the same command as in the docs
  2. Sets AUDIO_INPUT_DEVICE=aec_mic automatically
  3. Falls back gracefully if the module fails to load (logs a warning, continues with default devices)

docs/enabling_aec.md is updated with a Docker section pointing to this variable, and .env.example documents it alongside the other audio options.

No code changes — entrypoint and docs only.

Docker users currently have to manually SSH into the host, run pactl
commands, and set AUDIO_INPUT_DEVICE by hand — steps that don't persist
across PulseAudio restarts. This adds a single env var that automates
exactly the setup already described in docs/enabling_aec.md.

When ENABLE_ECHO_CANCEL=1 is set, the entrypoint loads
module-echo-cancel with source_name=aec_mic and sets AUDIO_INPUT_DEVICE
to aec_mic automatically. If the module fails to load a warning is
logged and the application starts normally with the default devices.

Updates docs/enabling_aec.md with a Docker section and .env.example
with documentation for the new variable.
@florian-asche
Copy link
Copy Markdown
Collaborator

We already have a plan for that. We will provide all confiuration up front, the user simply just need to change the input device. The configuration will be provided for the host setup. There will be no configuration on the container side.

@florian-asche florian-asche self-assigned this Mar 24, 2026
@florian-asche florian-asche added documentation Improvements or additions to documentation enhancement New feature or request labels Mar 24, 2026
@aryanhasgithub
Copy link
Copy Markdown
Contributor

It will be easier to debug if the user sets up AEC outside the container and passes it into the container via a argument or the env file.

@interkelstar
Copy link
Copy Markdown
Contributor Author

interkelstar commented Mar 27, 2026

Thanks both for the input - I understand the preference for keeping the container clean and having the user configure AEC on the host.

That said, I'd like to make the case for why this matters in practice:

Managed and locked-host platforms are a real use case. A significant portion of Docker-based Home Assistant deployments run on managed OS platforms - Umbrel, CasaOS, ZimaOS, Synology DSM - where direct host access is limited or actively discouraged. On these systems there is no practical way to run pactl load-module on the host, persist it across reboots, or modify PulseAudio's default.pa. The container entrypoint is the only interface available to the user.

This container already operates on the host's PulseAudio. The entrypoint mounts /run/user/1000, connects to the host's PulseAudio socket, and already runs pactl info to verify connectivity. Loading a module via that same open connection isn't a new category of host interaction - it's one more call on a channel that's already in use.

The debuggability argument may actually go the other way. With host-side setup, a misconfigured or missing AEC source fails silently - the app just starts with the wrong input device and the user has no idea why AEC isn't working. With ENABLE_ECHO_CANCEL=1 in the entrypoint, the outcome is explicit either way: "✅ Echo cancellation enabled" or "⚠️ Failed to load echo cancellation module (continuing without it)". The user always knows the state from container logs alone.

The common case is simple. Most Docker users have a single mic/speaker device and just want AEC to work. The proposed plan of documenting host-side pactl commands and then passing AUDIO_INPUT_DEVICE is two separate configuration steps across two separate systems - exactly the kind of friction that a Docker-first tool should eliminate.

I'd also love to get input from @synesthesiam here given their experience with voice assistant deployments - curious whether managed-OS platforms are a realistic target audience and whether container-side AEC setup would be appropriate in that context.

@Solarunit
Copy link
Copy Markdown

Most Docker users have a single mic/speaker device and just want AEC to work.

I have several speakers..

The proposed plan of documenting host-side pactl commands and then passing AUDIO_INPUT_DEVICE is two separate configuration steps across two separate systems - exactly the kind of friction that a Docker-first tool should eliminate.

Yea, I agree it's a bit more complex setup to manually add virtual mic on the host. But on the other hand you already have to do some configuration on the host like enable linger for the pipewire user.


offtopic: WebRTC Auto Gain & Noise Suppression and AEC are two different things, right? What are pros an cons to enable all together?

@aryanhasgithub
Copy link
Copy Markdown
Contributor

offtopic: WebRTC Auto Gain & Noise Suppression and AEC are two different things, right? What are pros an cons to enable all together?

Yes AGC and NS are used to add gain and to suppress extra noise while AEC is used to cancel out the noise from the speaker of the device on which you have enabled AEC to prevent feedback. AGC could amplify extra background noise, NS might remove useful portions of audio and AEC might make your audio sound worse, but these are uncommon though I won't call them edge cases, depends on your setup and conditions.

@interkelstar
Copy link
Copy Markdown
Contributor Author

Following up one more time.

I'd like to reframe the question: what's the downside of giving users a simpler path?

Today, a Docker user who wants AEC needs to:

  1. Get shell access to the host (not always possible on managed platforms)
  2. Run pactl load-module module-echo-cancel ...
  3. Edit /etc/pulse/default.pa to persist across reboots
  4. Then set AUDIO_INPUT_DEVICE=aec_mic in .env

With ENABLE_ECHO_CANCEL=1, it's one line in .env. The existing manual path in the docs stays untouched — users who prefer host-side setup aren't affected either way.

I'm not trying to impose architecture here — genuinely trying to remove friction for the common case. If there's a specific technical objection (security, stability, edge case I'm missing), I'd like to understand it. If the direction is simply "we don't want container-side audio configuration as a matter of principle," I'll accept that and close the PR.

@synesthesiam @florian-asche — would appreciate a clear answer either way so I know whether to iterate or close.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants