Skip to main content

Remove background music from videos - for accessibility and personal use

Project description

ELUATE

As a muslim, I've experienced this friction many times: the documentary I want to watch or some informative long-form video I want to learn from, almost always comes with a score running underneath. Normally my next step would be to just not watch it. However, on one of those days, I just thought maybe I could build a simple tool that would take a video in and hand me back the same video with the music gone.

ELUATE is that simple thing. It is a CLI that you give it a video file, it removes the music, keeps the dialogue and sound effects, and outputs the video. The video stream is copied through untouched so it is bit-for-bit unchanged.

In terminal you do

eluate documentary.mp4
# → ~/Documents/ELUATE/documentary_eluted.mp4

I also wanted this to have a small API with the same engine behind, so I can wire ELUATE into other tools (a content pipeline, a batch job, my other project, etc.)

import eluate

eluate.elute("documentary.mp4")

I wanted to share this here for muslims who run into the same friction trying to learn, research, experiment. However as I was developing this and doing research about it, I found that the benefit can be much broader. For instance people with hearing loss where the score fights the narration, or someone with focus or auditory-processing conditions where the score becomes another competing thing you have to filter out.

If that's you too, I hope this tool helps you.

It's a one-maintainer project + AI. Feel free to fork and develop, I am sure there are much more talented and knowledgeable muslims than me that could make this much much better.

Install

pip install eluate

ELUATE needs FFmpeg on your PATH. It's preinstalled on Colab; on Linux install it with sudo apt-get install -y ffmpeg, on macOS with brew install ffmpeg.

The first run downloads a ~450 MB model checkpoint from Zenodo into ~/.eluate/. It only happens once.

eluate info   # verify device, FFmpeg, and model are ready

A ready-to-run Colab notebook is at notebooks/eluate_colab_template.ipynb: set the runtime to a GPU (Runtime -> Change runtime type -> GPU), then run the cells top to bottom.

Usage

eluate                                # interactive mode (prompts for file)
eluate video.mp4                      # single file → ~/Documents/ELUATE/
eluate video.mp4 -o custom.mp4        # custom output path
eluate --checkpoint eng video.mp4     # use the English-optimised model
eluate setup                          # download the default model for API use
eluate --batch files.txt              # process paths from a list file
eluate --folder /path/to/videos       # process every video in a folder
eluate --folder ./videos --batch-size 10   # folder in batches of 10
eluate info                           # system / model status
eluate video.mp4 --device cpu         # force CPU, skip MPS
eluate video.mp4 --force              # skip duration / disk-space checks

Supported input containers: mp4, mkv, avi, mov, webm, flv, wmv, m4v.

Model

ELUATE ships a single model: Bandit v2, CC-BY-SA 4.0, 48 kHz. CC-BY-SA permits commercial use under share-alike terms; see Licensing for the caveats before shipping anything commercial.

Bandit v2 ships per-language checkpoints (multi, eng, deu, fra, spa, cmn, fao). The default is multi. Swap with --checkpoint eng etc.

Python API

For batch loops or wiring ELUATE into your own code, instantiate a Session so the model loads once and is reused:

import eluate

with eluate.Session() as session:
    for path in ["a.mp4", "b.mp4", "c.mp4"]:
        session.elute(path)

eluate.elute(), eluate.Session, eluate.Result, and the typed exception hierarchy under eluate.EluateError form the entire v1.x public surface; semver applies to those names only. Full reference, including progress callbacks and stem-only outputs, in docs/api.md.

How it works

With (Bandit v2) ELUATE splits the audio into speech, music, and sfx, discards the music stem, mixes the other two back together, and then into a copy of the video.

 input.mp4 ─┬─▶ ffmpeg audio extract ─▶ 48 kHz WAV
            │
            │                            Bandit v2 (streaming demix)
            │                                  │
            │                    ┌─────────────┼─────────────┐
            │                    ▼             ▼             ▼
            │                  speech        music          sfx
            │                    │           drop            │
            │                    └────────── mix ────────────┘
            │                                │
            └─▶ ffmpeg mux  ◀─────  new audio track (speech + sfx)
                   │
                   ▼
           output_eluted.mp4   (video stream copied as-is)

The separator uses a streaming demix path: a fixed-size ring buffer and virtual padded-chunk construction so the full audio track is never held in memory. See Testing for the memory benchmark.

Testing

Even though over time I started to optimize the code towards CUDA for people to maybe run this on Colab, I've developed it on a Mac mini, so testing was largely done with that.

On an 84-minute documentary on my M4 with 24 GB, it had 19 GB of peak memory usage with ELUATE latest state compared to 41 GB for the original (non-optimized) upstream reference, which finished with macOS swapping about 20 GB to disk, meaning ELUATE used 2.15× less in practice. To do that ELUATE uses a fixed-size ring buffer instead, processing the audio in a moving window without ever holding the full track in memory. Check docs/bench/ for the plain-language summary, full methodology in memory-benchmark.md, and a windowing bug this benchmarking uncovered and fixed.

It isn't faster than Demucs. I optimised the memory path for long files, not raw throughput, and you'll feel that on short inputs where Demucs finishes first. However in terms of use case, as far as I know, Demucs is more of a music stem separation model.

The CLI doesn't give you the stems. ELUATE's terminal workflow is video in, video out; the Python API can export speech and sfx WAVs for downstream tools, but it still never exposes the music stem.

Configuration and data

ELUATE writes data to two places, both under your home directory:

Path What lives there
~/.eluate/models/ Downloaded model checkpoints (~450 MB each), configs
~/.eluate/venv/ Python virtual env (created by install.sh)
~/.eluate/telemetry.jsonl Local debug log (only if you enable it)
~/Documents/ELUATE/ Processed output videos

Nothing is sent over the network after the initial model download.

Local debug log (off by default)

ELUATE can write a local JSONL log of processing stages to help debug performance issues. The log never leaves your machine. It's a plain file you can read, delete, or ignore.

Telemetry is off by default. Enable it when you want a paper trail:

ELUATE_TELEMETRY=1 eluate video.mp4

The log contains nothing that identifies you or your files. Delete it any time.

Licensing

  • ELUATE's own code: MIT (see LICENSE).
  • Bandit v2 model weights: CC-BY-SA 4.0, from Zenodo 12701995. CC-BY-SA permits commercial use under share-alike terms: any derivative work you distribute under these weights must itself be licensed CC-BY-SA. That clause is operationally hostile to a lot of commercial software (it arguably extends to downstream derivative works). Consult a lawyer before shipping a commercial product built on ELUATE. The README can't and doesn't give legal advice.
  • Vendored separator framework at vendor/mss-training/: ZFTurbo's Music-Source-Separation-Training, MIT-licensed.

Contributing

Open an issue or PR at https://github.com/anaxoniclabs/ELUATE/issues.

For bug reports, running with the debug log enabled would help a lot:

ELUATE_TELEMETRY=1 eluate your-video.mp4
# then attach ~/.eluate/telemetry.jsonl (it never leaves your machine until you share it)

Acknowledgements

Project details


Download files

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

Source Distribution

eluate-0.0.2.tar.gz (109.5 kB view details)

Uploaded Source

Built Distribution

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

eluate-0.0.2-py3-none-any.whl (85.1 kB view details)

Uploaded Python 3

File details

Details for the file eluate-0.0.2.tar.gz.

File metadata

  • Download URL: eluate-0.0.2.tar.gz
  • Upload date:
  • Size: 109.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for eluate-0.0.2.tar.gz
Algorithm Hash digest
SHA256 5b763f01fde6c495a39e75037fb4e3de26f8b80dbc89117b640f4f774791df67
MD5 11a070252f642785d236929467141ec1
BLAKE2b-256 9a91513f0da9b72dfb35bafd188c748c761986ffad2fc2bf0a296ece050905b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for eluate-0.0.2.tar.gz:

Publisher: publish.yml on anaxoniclabs/ELUATE

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

File details

Details for the file eluate-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: eluate-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 85.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for eluate-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b7e68b8d52cce019d0cac9f5a2db4ea78f1ecfc364c668925f16c171c03cbc96
MD5 48bbc698881aaedc97d6689daababe41
BLAKE2b-256 f8eb4ec2f1c07ddecc68ac6b2ad7165315300506b4c6d9a7301214270adff7a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for eluate-0.0.2-py3-none-any.whl:

Publisher: publish.yml on anaxoniclabs/ELUATE

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

Supported by

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