# auditok: numpy-only audio event detection with optional WebRTC VAD and automatic thresholds

> auditok is a Python library that splits audio into events by thresholding signal energy, with a numpy-only core, automatic threshold estimation, and an optional WebRTC VAD backend for speech-specific work. It handles files, raw bytes and microphone input, and the same detection engine also runs in the browser through a JavaScript port.

**amsehili/auditok** — An voice activity detection and audio segmentation tool

- Repository: https://github.com/amsehili/auditok
- Stars: 861 · Forks: 102
- Language: Python
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/amsehili-auditok

## Energy thresholding is the whole engine

auditok is described as a lightweight audio activity detection library for Python with a numpy-only core. The mechanism is stated plainly: it splits audio streams into events by thresholding signal energy, and the threshold can be set manually or estimated automatically from the audio itself. An optional second path uses the WebRTC voice activity detector to target speech specifically rather than any sound.

That is the entire design, and it is worth being clear about what it implies. The library is not doing classification, transcription or speaker tracking. It answers one question: where in this stream is there enough signal energy to count as activity. Everything else in the API is arranged around refining the answer, merging events that are separated by short gaps, dropping events that are too short, and presenting the result.

The dependency list in pyproject.toml confirms the minimalism. The core requires Python 3.8 or higher and lists a single dependency, numpy, with the optional features split into extras. The package metadata classifies the project as Development Status 5, Production/Stable, and the classifiers run from Python 3.8 through 3.15.

The stated use cases match the mechanism: voice activity detection, silence removal, audio segmentation, or any task where you need to find where the sound is in an audio stream. It works with files, microphone input and streams, supports mono and multi-channel audio, and can be driven from a few lines of Python or from the command line.

## Installing the core, then the extras you actually need

The core install is a single command:

```bash
pip install auditok
```

Optional capabilities are installed as extras rather than being pulled in by default, and the four extras map cleanly onto the four things you might need:

```bash
pip install auditok[plot]       # plotting (matplotlib)
pip install auditok[device-io]  # microphone input and playback
                                    # (sounddevice, tqdm)
pip install auditok[webrtcvad]  # WebRTC VAD as frame decider
                                    # (webrtcvad-wheels)
pip install auditok[all]        # all of the above
```

The pyproject.toml gives the same mapping in machine readable form: device-io pulls sounddevice and tqdm, plot pulls matplotlib, webrtcvad pulls webrtcvad-wheels, and there is a separate test extra with pytest and pytest-cov alongside matplotlib and the WebRTC wheels.

One operational note deserves attention because it is easy to miss. Processing non-WAV formats, which the documentation lists as MP3, OGG, FLAC and video files among others, requires ffmpeg to be installed on the system. The library is not decoding those formats itself, it delegates to an external tool, so a deployment that only handles WAV works without any system packages and a deployment that handles compressed audio needs ffmpeg present in the image.

The microphone and playback paths are behind the device-io extra for the same reason: sounddevice needs native audio libraries, so keeping it optional means a server-side job that only reads files never has to satisfy that dependency.

## split, trim, fix_pauses and load form the small API

The API is documented as a table of functions with their key parameters, and it is small enough to read in one pass. split() detects and yields audio events as a generator, taking min_dur, max_dur, max_silence, energy_threshold and validator. trim() removes leading and trailing silence, with min_dur, max_silence and energy_threshold. fix_pauses() normalises pauses between events to a fixed duration, taking silence_duration alongside the usual parameters. split_and_plot() splits and visualises the result, using either matplotlib or an interactive Jupyter widget, with an interactive flag and save_as. load() reads audio from a file, bytes or the microphone into an AudioRegion, taking sr, sw and ch.

The flexibility is in the input handling. All of the functions accept file paths, raw bytes, AudioRegion objects, or None, and None means read from the microphone. The same four operations are also available as methods on AudioRegion, so you can chain a split and then trim the result rather than going back through load.

The distinction between split and trim is the one to hold on to. split finds events wherever they are, including in the middle of a long recording, while trim only removes silence at the two ends. If you are trimming a podcast intro and an outro, trim is the right call and split would give you the same result with more work. If you want every utterance in a meeting recording, split is what you want and trim does nothing for you.

fix_pauses is the third mode and it is the one people reach for when concatenating events. It rewrites the gaps between detected events to a constant duration, which is what you need before feeding a sequence to something that expects evenly spaced input.

## The quick start shows exactly which knobs matter

The quick start example is short enough to read as the specification of the important parameters:

```python
import auditok

# split returns a generator of AudioRegion objects
audio_events = auditok.split(
    "audio.wav",
    min_dur=0.2,     # minimum duration of a valid audio event in seconds
    max_dur=4,       # maximum duration of an event
    max_silence=0.3, # maximum tolerated silence within an event
    energy_threshold=55 # detection threshold
)

for i, r in enumerate(audio_events):
    # AudioRegions returned by split have start and end attributes
    print(f"Event {i}: {r.start:.3f}s -- {r.end:.3f}s")

    # play the audio event
    r.play(progress_bar=True)

    # save the event with start and end times in the filename
    filename = r.save("event_{start:.3f}-{end:.3f}.wav")
    print(f"Event saved as: {filename}")
```

The four tuning parameters are all durations in seconds or an energy threshold, and each does something different. min_dur drops events shorter than the given length, which is how you remove clicks and pops. max_dur caps how long a single event can be, which prevents a continuous hum from becoming one giant region. max_silence is the tolerance for a gap inside an event, so a speaker who pauses briefly does not get split into two events. energy_threshold is the level in decibels above which audio counts as active.

The AudioRegion object carries the timing and the audio together, and the example shows the three things you can do with one: read its start and end, play it back with a progress bar, and save it with the timestamps baked into the filename. The example output shows the shape of the result, with an event printed as a start and end pair and the saved file named after the same pair.

## Automatic thresholds are two different heuristics

Rather than tuning energy_threshold by hand, you can let auditok estimate it from the audio, and the library offers two named strategies with different assumptions:

```python
import auditok

# estimate the threshold from the input's energy distribution
# "otsu": balanced, suited to audio with clear pauses
audio_events = auditok.split("audio.wav", validator="otsu")

# "percentile": noise floor + margin, suited to dense/far-field speech
audio_events = auditok.split("audio.wav", validator="percentile")
```

The otsu validator is described as balanced and suited to audio with clear pauses, which is the classic case: a recording with obvious silence between utterances, where a threshold that separates the two populations cleanly is what you want. That is a well known method of finding a split between two distributions, and its weakness is exactly what the documentation hints at, which is that it needs the two populations to be separable.

The percentile validator is described as noise floor plus margin, suited to dense or far-field speech. It reads the noise floor at the 10th percentile of window energies, and you can read it elsewhere with a pXX form, so p20 reads a higher and more selective threshold. The mechanism is intuitive: find the quietest part of the recording, treat that as the noise, and set the bar a margin above it. That works when there is no clean silence, such as a recording made across a room, because the distribution of energies is continuous rather than bimodal.

Choosing between them is a judgement about the recording rather than about the library. A noisy far-field recording that produces no events under otsu is not a broken threshold, it is the wrong estimator for that recording, and switching to percentile is the documented answer.

## Where auditok is the wrong tool

The clearest limit is what the library does not attempt. It finds where sound is, not what is being said. There is no transcription, no speaker diarisation, no classification of audio types and no source separation. A project that needs to know who spoke, or needs the words, needs a different library and would use the timestamps auditok produces as a preprocessing step rather than an end to end solution.

The energy threshold approach also has a blind spot that follows from the mechanism rather than from an implementation defect. Anything loud enough crosses the threshold, whether it is speech, a door closing, a keyboard, or music. That is why the WebRTC VAD option exists, since a voice activity detector is trained on speech rather than on signal energy, and it is the right choice when the audio is speech with noise. The cost is an extra dependency and a different set of tuning parameters.

The ffmpeg requirement is the other practical constraint. If your pipeline is fed MP3 or OGG files, the library will not read them without an external binary present, which matters in a containerised deployment where the image is built from a slim base.

There is also a browser path that is worth knowing about if your use case allows it. The project maintains a JavaScript port, and a browser playground runs the same detection engine, with the same parameters and the same dB scale, entirely client side on your own files or microphone. For a use case where the audio should never leave the user's machine, that playground may be a better answer than installing a Python package at all. The trade is that you inherit a port rather than the library itself, and the two could drift apart over time.

## Conclusion

auditok fits a Python developer who needs to find where sound occurs in a recording, trim silence, or normalise pauses, and who wants to keep the dependency footprint down to numpy. It does not fit a pipeline that needs diarisation, speaker identification, or transcription, since the library detects activity rather than content. Before adopting it, confirm your audio is WAV or arrange for ffmpeg to be installed, because MP3, OGG, FLAC and video inputs are not handled without it, and pick a threshold strategy deliberately, because the automatic otsu and percentile validators suit different recordings and a wrong choice looks like a detection failure rather than a tuning mistake.

## FAQ

### How do I install auditok and what are the optional dependencies?

The core install is `pip install auditok`, and it needs Python 3.8 or higher with only numpy as a dependency. Extras add capabilities: the plot extra pulls matplotlib, the device-io extra pulls sounddevice and tqdm for microphone input and playback, the webrtcvad extra pulls webrtcvad-wheels, and the all extra installs every one of them.

### Does auditok handle MP3 and other compressed audio formats?

Not on its own. The documentation states that processing non-WAV formats such as MP3, OGG, FLAC and video files requires ffmpeg to be installed on your system, since the library delegates decoding to it rather than doing the work itself.

### How do I get auditok to pick a detection threshold automatically?

Pass a validator to split. The otsu validator is described as balanced and suited to audio with clear pauses, while percentile reads the noise floor at the 10th percentile of window energies and suits dense or far-field speech. You can move the percentile with a pXX form such as p20 for a higher, more selective threshold.

### What is the difference between split and trim in auditok?

split detects and yields audio events throughout a stream as a generator of AudioRegion objects, while trim removes only leading and trailing silence. fix_pauses is the third mode, normalising the gaps between events to a fixed duration.

### Can auditok use the WebRTC voice activity detector instead of energy thresholds?

Yes, if you install the webrtcvad extra, which pulls webrtcvad-wheels. The documentation describes the WebRTC VAD as usable as a frame decider so detection can target speech specifically rather than any sound above the energy threshold.

## Sources

- [amsehili/auditok on GitHub](https://github.com/amsehili/auditok)
- [Issues](https://github.com/amsehili/auditok/issues)
- [License: MIT](https://github.com/amsehili/auditok/blob/main/LICENSE)
- [README](https://github.com/amsehili/auditok/blob/main/README.md)
- [Releases](https://github.com/amsehili/auditok/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/amsehili-auditok
