Skip to main content

AudioCLI

A scriptable, batch-capable, cross-platform audio power-tool that runs DAW-quality effects from the command line. Built on Spotify's pedalboard — pre-built wheels for Linux, macOS, and Windows mean no system ffmpeg/sox to wrangle.

Install

pip install audiocli-tools

Note on the name: the PyPI distribution is audiocli-tools. The bare audiocli on PyPI is an unrelated audio-measurement project — pip install audiocli will get you the wrong tool. Once installed, everything in your shell and your code stays audiocli / audiocli-gui / from audiocli import ....

Python ≥ 3.10. No torch, no librosa, no scipy. audiocli --help returns in under 150 ms.

The optional desktop GUI is being developed as a cross-platform PySide6 app:

pip install "audiocli-tools[gui]"
audiocli-gui

The GUI uses the same capability metadata as the CLI/library, with a compact workspace for browsing tools, building chains, and running batches.

One-shot mode

Every command takes one or more --target paths (files or directories), an optional --output, and --workers N for parallelism. Directory targets recurse by default; pass --no-recursive to flatten.

# Apply 6 dB of gain to every WAV in a folder, write to a new dir
audiocli gain --target ./stems --db 6 --output ./stems-louder

# Normalize a folder of stems to -1 dBFS peak in parallel
audiocli normalize --target ./stems --peak-db -1 --workers 8

# Convert WAVs to FLAC in place (writing alongside the source)
audiocli convert --target ./stems --format flac

# LUFS normalization for streaming targets
audiocli normalize --target ./mixes --lufs -14

# A 1000-file batch where 50 files are corrupt — 950 succeed, 50 are
# reported, exit code is non-zero, the job never hangs
audiocli compress --target ./big-folder --ratio 4 --threshold-db -20 --workers 16

Interactive REPL

audiocli shell

Chain commands with ;. set targets <paths>, set output <dir>, set workers N configure session state and persist to disk so they survive restarts. show prints the current session.

audiocli> set targets ./stems ; set output ./out ; resample 22050 ; mono -o

First-party ops

Command Description Example
gain Apply gain in decibels audiocli gain --target … --db 6
normalize Peak (dBFS) or LUFS normalization audiocli normalize --target … --peak-db -1
polarity Invert sample polarity audiocli polarity --target …
mono Mix down to 1 channel audiocli mono --target …
stereo Duplicate mono → 2-channel stereo audiocli stereo --target …
resample Change sample rate (libsamplerate) audiocli resample --target … --sr 22050
pitch Pitch-shift in semitones audiocli pitch --target … --semitones -2
trim Strip leading/trailing silence audiocli trim --target … --threshold-db -60
fade Fade in/out (linear, exp, cosine) audiocli fade --target … --fade-in-s 0.5 --shape cosine
convert Change output format (wav/flac/mp3/ogg) audiocli convert --target … --format flac
bitdepth Set output bit depth (8/16/24/32) audiocli bitdepth --target … --bits 24
compress Dynamic range compression audiocli compress --target … --ratio 4 --threshold-db -20
limit Peak limiting audiocli limit --target … --threshold-db -1
highpass High-pass filter audiocli highpass --target … --hz 80
lowpass Low-pass filter audiocli lowpass --target … --hz 8000
reverb Algorithmic reverb audiocli reverb --target … --room-size 0.6 --wet 0.3
delay Feedback delay audiocli delay --target … --time-s 0.4 --feedback 0.4
chorus Modulated chorus audiocli chorus --target … --rate-hz 1.0 --depth 0.25
phaser All-pass phaser audiocli phaser --target … --rate-hz 1.0
distortion Soft-clip distortion audiocli distortion --target … --drive-db 25
bitcrush Bit-depth reduction audiocli bitcrush --target … --bit-depth 8
vst Host any VST3 / AU plugin audiocli vst --target … --plugin-path ./MyComp.vst3 --param Threshold=-12
info Print sr, channels, duration, peak, RMS, LUFS audiocli info --target …
remove-silent Delete files below an RMS threshold audiocli remove-silent --target … --threshold-db -55
chunk Split files into N-second pieces audiocli chunk --target … --seconds 5.0
hook Run a one-off Python transform audiocli hook ./my_transform.py --target …
run-script Run a .acli batch file audiocli run-script ./pipeline.acli
shell Start the interactive REPL audiocli shell

Run audiocli <command> --help for the full flag set on any op.

--json event mode

Every op accepts --json. When set, the CLI emits one JSON object per line on stdout — newline-delimited so any other process can parse it.

audiocli normalize --target ./stems --peak-db -1 --json
{"type": "start", "total": 12, "workers": 8}
{"type": "file_done", "path": "./stems/a.wav", "ok": true, "error": null}
{"type": "progress", "done": 1, "total": 12, "current": "./stems/a.wav"}

{"type": "done", "ok": 12, "failed": 0, "duration_s": 3.42}

Exit code is 0 on full success, otherwise the failure count (capped at 255). Pipe straight into your CI script or progress UI.

Desktop GUI

audiocli-gui is the v2 desktop direction for macOS, Windows, and Linux. It is a thin workspace over the same pipeline and capability model: tool metadata drives the browser and parameter panel, saved chains can round-trip through native chain files or .acli scripts, and long runs use the library event/cancellation path.

For VST/AU work, the GUI discovers installed plugin bundles from conservative platform defaults without loading native code. Selecting a VST / AU Plugin node shows detected plugins, accepts an explicit plugin path, and can open the plugin's native editor in a helper process. Parameters reported by the editor are mirrored back into the node as repeatable key=value entries, with a paged, read-only parameter view in the GUI.

The current GUI polish favors dense desktop use: compact controls, icon buttons where practical, and code-font lists/empty states for scan- and capability-heavy surfaces.

Use as a library

from audiocli import run_per_file, list_ops, get_op

# Enumerate registered ops with full param metadata
for op in list_ops():
    print(op.name, [p.name for p in op.params])

# Drive a batch from Python with a progress callback
gain = get_op("gain")
report = run_per_file(
    ["song1.wav", "song2.wav"],
    gain,
    {"db": 6.0},
    output="./out",
    workers=4,
    on_event=lambda evt: print(evt),
)
print(report.ok_count, "ok,", report.failed_count, "failed")

The library API is intentionally GUI-friendly:

  • cancel_token: threading.Event — flip from any thread to abort a long batch. In-flight files complete; pending submissions skip.
  • on_event — same protocol as the --json CLI mode, so a desktop app can render progress without shelling out.
  • list_ops() returns frozen dataclasses (OpInfo / ParamInfo) describing every op's parameters — type, default, help, required — for dynamic UI generation.
  • No print() or sys.exit() in any library module. Errors are raised from the public hierarchy: AudioCLIErrorLoadError, SaveError, OpError, PluginError, ConfigError.

Plugin authors

A plugin is a regular pip-installable package that registers ops via Python entry-points. The minimum viable plugin:

# my_plugin/ops.py
from audiocli import op, AudioBuffer


@op(name="reverse", help="Reverse the audio along the time axis.")
def reverse(buf: AudioBuffer) -> AudioBuffer:
    return AudioBuffer(data=buf.data[:, ::-1], sr=buf.sr, subtype=buf.subtype)
# my_plugin/pyproject.toml
[project]
name = "audiocli-plugin-reverse"
version = "0.1.0"
dependencies = ["audiocli>=2"]

[project.entry-points."audiocli.ops"]
reverse = "my_plugin.ops:reverse"
pip install audiocli-plugin-reverse
audiocli reverse --target ./stems   # appears as a first-class command

The plugin contract is filter-shape only in v2.0: (buf: AudioBuffer, **params) -> AudioBuffer. First-party special-case ops (info, chunk, remove-silent, vst) bypass the contract because their shape is multi-output / analysis / side-effect; the plugin contract may broaden in v2.1+.

If a plugin's name collides with a first-party op, the first-party op wins and the conflict is logged at startup. Malformed plugin signatures raise PluginError at registration time, not at run time.

Power-user escape hatches

Don't want to publish a package for a one-off experiment? Drop a Python file and:

audiocli hook ./my_transform.py --target ./stems --custom-key value
# my_transform.py
from audiocli import AudioBuffer


def transform(buf: AudioBuffer, custom_key: str = "") -> AudioBuffer:
    return AudioBuffer(data=buf.data * 0.5, sr=buf.sr, subtype=buf.subtype)

Save a sequence of commands as a .acli script and re-run it:

# pipeline.acli
gain --target ./stems --db -6 --output ./out
trim --target ./out --threshold-db -55
fade --target ./out --fade-out-s 0.5
audiocli run-script ./pipeline.acli

Settings

Persisted at the platformdirs user-config location (XDG on Linux, ~/Library/Application Support/AudioCLI on macOS, %APPDATA%\AudioCLI on Windows). JSON with a "schema": 1 field for forward-compatibility. Stores: targets, output dir, workers, recursive flag, last-used overwrite preference. Override with AUDIOCLI_SETTINGS_FILE for testing.

Development

git clone https://github.com/diontimmer/AudioCLI
cd AudioCLI
pip install -e ".[dev]"
ruff check .
ruff format --check .
pytest --cov=audiocli

CI runs the suite on {ubuntu, macos, windows} × {3.10, 3.11, 3.12}.

License

MIT.

Download files

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

Source Distribution

audiocli_tools-2.1.0.tar.gz (214.1 kB view details)

Uploaded Source

Built Distribution

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

audiocli_tools-2.1.0-py3-none-any.whl (172.7 kB view details)

Uploaded Python 3

File details

Details for the file audiocli_tools-2.1.0.tar.gz.

File metadata

  • Download URL: audiocli_tools-2.1.0.tar.gz
  • Upload date:
  • Size: 214.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for audiocli_tools-2.1.0.tar.gz
Algorithm Hash digest
SHA256 db29dc91affb08d4f240354a8a45602a54a2952b85ea1afccbd3f3f4275a9c47
MD5 8aa169d3e40d252d23950402e2d62fd4
BLAKE2b-256 a6af87ddf3ca7248427475af8cc184659928f2e823f21907043ff9f9c2329e2d

See more details on using hashes here.

Provenance

The following attestation bundles were made for audiocli_tools-2.1.0.tar.gz:

Publisher: release.yml on diontimmer/AudioCLI

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file audiocli_tools-2.1.0-py3-none-any.whl.

File metadata

  • Download URL: audiocli_tools-2.1.0-py3-none-any.whl
  • Upload date:
  • Size: 172.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for audiocli_tools-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dd63d884a047ef4c23972f3598f0319ba1d8afe2187e22a90d5fc2ed4abfcbef
MD5 37b89d2d0ed4950b6af65f8a4784e26f
BLAKE2b-256 8a309f0e32cac27b5c5990c828861bdc0c32368a81561c48dc7d584b686e7256

See more details on using hashes here.

Provenance

The following attestation bundles were made for audiocli_tools-2.1.0-py3-none-any.whl:

Publisher: release.yml on diontimmer/AudioCLI

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

2.1.0 This release

2 files

2.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page