Skip to main content

Echoff

Echo off. Clean microphone on.

echoff is a small Python library for real-time acoustic echo cancellation. It captures the audio rendered by the computer and the microphone on separate streams, aligns their timelines, and feeds matched 10 ms frame pairs to WebRTC's Audio Processing Module (APM).

The package deliberately does not contain voice activity detection, speech recognition, text-to-speech, or conversation policy. Applications receive clean microphone frames and decide what to do with them.

Current platform support

Platform Status Capture backend
Windows Supported WASAPI loopback and microphone through PyAudioWPatch, with WDM-KS microphone fallback
Linux Planned PipeWire sink monitor and microphone source

The WebRTC processor and timestamp aligner are platform-neutral. Only the device capture adapters are platform-specific.

Install

Echoff is published on PyPI and currently supports live device capture on Windows with Python 3.11 or newer:

python -m pip install echoff

The WebRTC processor and alignment components are platform-neutral; additional capture backends will be published as they receive physical hardware testing.

Install for development on Windows

git clone https://github.com/KoljaB/echoff D:\Projekte\echoff
cd D:\Projekte\echoff
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"

Five-minute hardware check

List devices:

echoff devices

Record system audio, the raw microphone, and the AEC-cleaned microphone:

python examples\record_aec_session.py --duration 20 --log-level INFO

While it runs, play any speech or music through the normal speakers. You may also speak into the microphone. The output directory contains:

computer_audio.wav
microphone_raw.wav
microphone_aec.wav
events.jsonl
config.json
summary.json
run.log

For a repeatable loudspeaker stimulus, provide a WAV file:

python examples\record_aec_session.py `
  --play-wav D:\audio\speech.wav `
  --repetitions 3 `
  --output D:\Temp\aec-probe

See Capture artifacts for the exact meaning of each file and Hardware probe for a repeatable test.

Library API

import time
from pathlib import Path

from echoff import AecCapture, AecConfig, AecFrame


def consume(frame: AecFrame) -> None:
    # 48 kHz mono floating-point samples in [-1.0, 1.0].
    send_to_your_audio_pipeline(frame.microphone_clean)


config = AecConfig(stream_delay_ms=50)
with AecCapture(
    config,
    on_frame=consume,
    output_dir=Path("capture-artifacts"),
) as capture:
    time.sleep(20)
    print(capture.status())

For applications that already own their audio devices, use only the processor:

from echoff import AecConfig, WebRtcAecProcessor

processor = WebRtcAecProcessor(AecConfig())
clean_microphone = processor.process_pair(reference_samples, microphone_samples)

process_pair() is intentionally atomic: the far-end reference is always submitted immediately before its matching microphone frame.

Deterministic replay pipelines with one shared clock may use StreamingWebRtcAecProcessor to submit continuous reference and microphone streams separately. Physical device capture should always use AecCapture so timestamp alignment remains active.

Design guarantees

  • One worker owns reference/microphone pairing and APM call order.
  • Capture blocks carry monotonic end timestamps.
  • Startup phase differences and later discontinuities are realigned instead of silently pairing stale frames.
  • Every realignment starts a fresh AEC epoch exactly once.
  • The echo-path readiness signal advances only on paired, active far-end audio.
  • Libraries never configure the process-wide root logger.
  • Raw and processed audio can be recorded for every run.

Read Architecture and Integration before adding a new backend.

Development

python -m unittest discover -s tests -v
ruff check .
mypy src
python -m build

Hardware tests are deliberately separate from unit tests. Unit tests must not open devices or play audio.

License

No distribution license has been selected yet. Until the repository owner adds one, the source is provided without a grant to copy, modify, or redistribute it.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

echoff-0.1.1.tar.gz (35.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

echoff-0.1.1-py3-none-any.whl (32.5 kB view details)

Uploaded Python 3

File details

Details for the file echoff-0.1.1.tar.gz.

File metadata

  • Download URL: echoff-0.1.1.tar.gz
  • Upload date:
  • Size: 35.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for echoff-0.1.1.tar.gz
Algorithm Hash digest
SHA256 9102ccc4ef269e22e8193481f1d31c61009201cbcfbb7c5c1810dc3178f6bbf2
MD5 981b4e6af1570be08d7b7dc43e8616c1
BLAKE2b-256 351d00d29e06da45b1a28a3654c1d4c35db128c84d0b28fc66772be45cc56037

See more details on using hashes here.

File details

Details for the file echoff-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: echoff-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 32.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for echoff-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f8fe03b3e4778968ad4afa7514aa6b5fb79c683c2b70f7c984e51e72e64c6ed2
MD5 dc908f7fb3c4744197d171ed54640f8e
BLAKE2b-256 230133183feeea0947911530b81899cf4459d917e2a7eff09407f7e95b3d81a2

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.0

2 files

0.2.0

2 files

0.1.4

2 files

0.1.3

2 files

This release

0.1.1 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page