A Python package to convert drum audio to sheet music.
Project description
DrumScript
DrumScript is an open-source Python library and CLI tool for drum audio analysis and transcription. Give it a recording — a full mix or an isolated drum stem — and it will generate PDF sheet music, MIDI files, and MusicXML output.
Python >=3.9
Workflow Status
Demo Notebooks
Features
- Automatic Drum Transcription: Detects kicks, snares, hi-hats, toms, and cymbals using a deterministic, rule-based classification engine — no machine learning required.
- Tempo Detection: Automatically estimates BPM using a voting-system algorithm tuned for percussive audio.
- Onset Detection: Onset detection method tuned to the physics of percussion audio rather than polyphonic instruments (piano, guitar, etc.).
- Stem Separation: Uses the state-of-the-art Demucs source separation model to isolate drums, bass, vocals, and other instruments from a full mix.
- Backing Track Generator: Automatically remove the drums from any
.mp3or.wavto create a drumless play-along track. Bass-only and vocal-only extraction also supported. - Multiple Output Formats: Export transcriptions to PDF sheet music, MIDI (
.mid), and MusicXML (.xml) for import into DAWs and notation software (Logic Pro, Cubase, Ableton, MuseScore, Sibelius, etc.). - Deterministic Classification: DrumScript's core classification engine uses physics-based rules derived from acoustic analysis of real drum samples, not probabilistic AI/ML models.
Note: Some dependencies used by DrumScript (e.g. Demucs, librosa) may internally use probabilistic methods. DrumScript's own classification engine is fully deterministic.
Project Structure
See repository_structure.md for the full project layout.
DrumScript/
├── drumscript/ # Main source package
│ ├── __init__.py # Public API (transcribe, load_audio, etc.)
│ ├── main.py # CLI entry point
│ ├── audio_processor/ # Audio loading, DSP, stem splitting
│ ├── drum_classifier/ # Rule-based classification engine
│ ├── notation_generator/ # Score building, PDF/MIDI/XML export
│ └── utils/ # Helpers (ffmpeg installer, research scripts)
├── docs/ # Sphinx documentation
├── tests/ # pytest test suite
├── .github/workflows/ # CI/CD (tests, build, publish, docs)
├── pyproject.toml # Package metadata and dependencies
└── uv.lock # Pinned dependency versions
Installation
For users:
pip install drumscript
For developers:
git clone https://github.com/DrumScript/DrumScript.git
cd DrumScript
uv sync # this will create a .venv
source .venv/bin/activate && uv sync --extra dev
pytest -m "not slow"
DrumScript manages all dependencies via pyproject.toml using uv. There is no requirements.txt.
System dependencies
-
ffmpeg is required for MP3 input/output. WAV-only workflows do not need it.
- macOS:
brew install ffmpeg - Ubuntu/Debian:
sudo apt-get install ffmpeg libsndfile1 - Windows: Download from ffmpeg.org and add to PATH.
- Or use the built-in helper:
import drumscript as ds; ds.install_ffmpeg()
- macOS:
-
PortAudio is required by
sounddevicefor audio playback.- macOS:
brew install portaudio - Ubuntu/Debian:
sudo apt-get install libportaudio2 - Windows: Usually bundled with the
sounddevicewheel.
- macOS:
Quick Start
End-to-end transcription
import drumscript as ds
# Transcribe an isolated drum stem → PDF
pdf_path = ds.transcribe("drum_audio.wav")
# Transcribe a full song (separates drums automatically)
pdf_path = ds.transcribe("full_song.mp3", full_song=True)
# Get all intermediate results
result = ds.transcribe("drum_audio.wav", full=True)
print(f"Tempo: {result['tempo']:.1f} BPM")
print(f"Events: {len(result['events'])}")
Load and explore audio
import drumscript as ds
# Load at native sample rate (for notebooks / exploration)
audio_file = ds.load_audio("drum_audio.wav")
print(f"Sample rate: {sr} Hz, Duration: {len(audio)/sr:.1f}s")
# Detect tempo
bpm = ds.detect_tempo("drum_audio.wav")
print(f"Tempo: {bpm:.1f} BPM")
Extract stems
import drumscript as ds
# Extract just the drum stem
drum_path = ds.extract_stems("full_song.mp3")
# Create a drumless backing track in MP3
results = ds.extract_stems(
"full_song.mp3",
drumless=True,
output_format="mp3",
full=True,
)
print(f"Backing track: {results['mix']}")
CLI Usage
DrumScript also provides a command-line interface.
Basic transcription (isolated drum stem)
drumscript drum_audio.wav
Full song transcription (auto-separates drums)
drumscript full_song.mp3 --full
Extract a drumless backing track
drumscript full_song.mp3 --drumless
All options
drumscript <audio_file> [OPTIONS]
Options:
--full Transcribe a full song (isolates drums first via Demucs)
--drumless Extract a drumless backing track
--mute STEM Mute a specific stem (e.g. --mute bass). Repeatable.
--all-stems Export all individual stems (drums, bass, vocals, other)
--format FORMAT Output format for stems: wav (default) or mp3 (requires ffmpeg to be installed)
--rudiment Optimise classification for isolated single beats
--ts SIG Time signature (default: 4/4)
Examples
# Transcribe with 6/8 time signature
drumscript drum_audio.wav --ts 6/8
# Extract all stems as MP3
drumscript full_song.mp3 --all-stems --format mp3
# Classify rudiments
drumscript snare_hit.wav --rudiment
Contributing
We welcome contributions! DrumScript is intended to be a community-owned project.
- Open an Issue for bugs or feature requests.
- Submit a Pull Request for code changes.
- See CONTRIBUTING.md for the full contributor guide.
All bug reports and feature requests must be filed as GitHub Issues. All code changes must be submitted as Pull Requests. Keeping discussion public helps everyone.
FAQs
Why doesn't DrumScript include ffmpeg as a dependency?
ffmpeg is a system-level program, not a Python library, so it cannot be declared in pyproject.toml. It must be installed on the operating system. DrumScript provides an install_ffmpeg() helper to make this easier.
What normalisation is applied to loaded audio?
load_audio() applies peak normalisation after loading. It converts the audio to mono and scales it so the loudest sample is at 1.0. This is a linear operation — no audio detail is lost.
What is hop_length?
When analysing audio, librosa slides a small analysis window across the signal. The hop_length is how many samples the window advances per step. DrumScript uses HOP_LENGTH = 128, which at 44100 Hz gives a time resolution of ~2.9 milliseconds — fast enough to capture individual drum hits.
Does DrumScript use AI/machine learning?
DrumScript's own classification engine is fully deterministic — it uses physics-based rules, not neural networks. However, the optional stem separation feature uses Demucs, which is a deep learning model by Meta/Facebook.
Acknowledgements
- Demucs — The stem splitting functionality is built upon the work of @adefossez.
- librosa — For foundational audio processing tools.
License
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file drumscript-0.1.3.tar.gz.
File metadata
- Download URL: drumscript-0.1.3.tar.gz
- Upload date:
- Size: 63.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8af7fd17738e2e9eb1dec6f4e36d121d7c57ef080c6dff45e52b5aceb0155b4a
|
|
| MD5 |
e89b9be2c11cba0513929a3a9192de32
|
|
| BLAKE2b-256 |
073177feaf6a3777dea9b0a2a6e872ae3cebe1639030133ab0294d706602837c
|
Provenance
The following attestation bundles were made for drumscript-0.1.3.tar.gz:
Publisher:
publish.yml on DrumScript/DrumScript
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
drumscript-0.1.3.tar.gz -
Subject digest:
8af7fd17738e2e9eb1dec6f4e36d121d7c57ef080c6dff45e52b5aceb0155b4a - Sigstore transparency entry: 1583882964
- Sigstore integration time:
-
Permalink:
DrumScript/DrumScript@4bd08bee6c20dd7ba1bc33be31f3048b8e1f16c7 -
Branch / Tag:
refs/tags/drumscript__v0.1.4 - Owner: https://github.com/DrumScript
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4bd08bee6c20dd7ba1bc33be31f3048b8e1f16c7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file drumscript-0.1.3-py3-none-any.whl.
File metadata
- Download URL: drumscript-0.1.3-py3-none-any.whl
- Upload date:
- Size: 68.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6aa8e60b76f315708237ec0de05c815f5bdb225a688cd1501e714ce0716f85a4
|
|
| MD5 |
79033e3374a9e45bb93752c81e1bcc5b
|
|
| BLAKE2b-256 |
8009c1283688767d4b05b84df0269ab0206b55394743288681c92467f1a50373
|
Provenance
The following attestation bundles were made for drumscript-0.1.3-py3-none-any.whl:
Publisher:
publish.yml on DrumScript/DrumScript
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
drumscript-0.1.3-py3-none-any.whl -
Subject digest:
6aa8e60b76f315708237ec0de05c815f5bdb225a688cd1501e714ce0716f85a4 - Sigstore transparency entry: 1583883147
- Sigstore integration time:
-
Permalink:
DrumScript/DrumScript@4bd08bee6c20dd7ba1bc33be31f3048b8e1f16c7 -
Branch / Tag:
refs/tags/drumscript__v0.1.4 - Owner: https://github.com/DrumScript
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4bd08bee6c20dd7ba1bc33be31f3048b8e1f16c7 -
Trigger Event:
release
-
Statement type: