Generate line-level LRC files from audio and canonical lyrics.
Project description
wispr
wispr is a Python library and CLI for generating synchronized, standard line-level
.lrc files from full-song audio plus a canonical line-by-line lyrics file.
The lyrics file is the source of truth. Transcription and alignment backends exist to recover timing, not to rewrite lyrics.
Demo contract
wispr song.wav lyrics.txt
By default this uses the WhisperX backend and writes song.lrc next to the audio file.
Existing outputs are not overwritten unless --force is passed.
wispr song.wav lyrics.txt -o output.lrc --debug --force
Initial flags:
-o, --output: choose an output path--force: overwrite an existing output file--debug: writetranscript.json,alignment.json, andsegments.json--backend mock|whisperx: choose the real WhisperX backend or mocked development timing--demucs: run optional Demucs vocal separation before WhisperX--model: WhisperX model name, defaulting tobase--device: runtime device, defaulting toauto--compute-type: WhisperX compute type, defaulting toauto--batch-size: WhisperX transcription batch size, defaulting by device--language: WhisperX language code, defaulting toen
Install
The PyPI distribution is wispr-lrc, and it installs the wispr command.
For real audio alignment, install the optional ML extra:
uv tool install "wispr-lrc[ml]"
WhisperX also requires ffmpeg to be available on your system path.
wispr song.wav lyrics.txt --model base --device auto --compute-type auto
Vocal separation is off by default. To run WhisperX on Demucs-isolated vocals, install
the optional separation extra and pass --demucs:
uv tool install "wispr-lrc[ml,separation]"
wispr song.wav lyrics.txt --demucs --model base --device auto
The mock backend is still available for fast development, CI, and framework smoke tests:
wispr song.wav lyrics.txt --backend mock
Current milestone
--device auto prefers CUDA when Torch reports that CUDA is available. With
--compute-type auto, wispr uses float16 on CUDA and int8 on CPU. If CUDA
is requested explicitly and unavailable, the run fails with a clear message.
Batch processing uses a CSV manifest with required audio and lyrics columns
and optional output, language, title, artist, and album columns.
Relative paths are resolved beside the manifest.
audio,lyrics,output,language
song-a.flac,song-a.txt,out/song-a.lrc,en
song-b.flac,song-b.txt,out/song-b.lrc,en
wispr batch manifest.csv --backend whisperx --device auto --compute-type auto --debug --force
Batch runs are sequential in one process so WhisperX models can be reused
without oversubscribing the GPU. Each run writes a *.summary.json file beside
the manifest with per-row status and stage timings.
Benchmark commands wrap the same pipeline and write a JSON report with runtime configuration, alignment quality, warnings, stage timings, and total wall time.
wispr benchmark song.wav lyrics.txt --backend whisperx --device auto --compute-type auto --debug --force
wispr benchmark batch manifest.csv --backend whisperx --device auto --compute-type auto --debug --force
Single-song benchmark reports default to <output-stem>.benchmark.json. Batch
benchmark reports default to <manifest-stem>.benchmark.json.
The emitted .lrc still uses the supplied lyrics file as canonical text. WhisperX only
provides timing evidence.
For a local real-audio smoke run, place ignored files under inputs/ and write outputs
back under that ignored tree:
For example:
uv run wispr inputs/03-giveon-twenties.flac inputs/lyrics.txt \
--backend whisperx \
--demucs \
--model base \
--device auto \
--compute-type auto \
--debug \
--force \
-o inputs/out/twenties.lrc
For local performance comparisons:
uv run wispr benchmark inputs/03-giveon-twenties.flac inputs/lyrics.txt --backend whisperx --device auto --compute-type auto --debug --force -o inputs/out/twenties.lrc
uv run wispr benchmark inputs/03-giveon-twenties.flac inputs/lyrics.txt --backend whisperx --demucs --device auto --compute-type auto --debug --force -o inputs/out/twenties-demucs.lrc
uv run wispr benchmark batch inputs/manifest.csv --backend whisperx --device auto --compute-type auto --debug --force
The WhisperX backend checks for both the optional Python dependency and ffmpeg before
running. Debug output includes raw backend payloads, normalized dataclass state, and an
alignment summary so failed or weak runs can be inspected without changing the .lrc
contract.
The code is organized around:
- typed dataclasses at stage boundaries
- deterministic LRC formatting
- a thin Typer CLI over reusable library code
- debug artifacts that mirror internal pipeline state
- structured warnings for weak alignment
- batch summaries and stage timings for runtime profiling
- benchmark reports for repeatable performance comparisons
Development
uv sync --dev
uv run pytest
uv run ruff check .
uv build
Slow ML tests should be marked with pytest.mark.ml and run explicitly:
uv run pytest -m ml
The local ML smoke test is skipped during the default test suite and only runs when the
inputs/ smoke files are present.
GitHub Actions runs linting, tests, a package build, and a mock benchmark smoke test on
Python 3.11 and 3.12. The committed Jingle Bells fixture under tests/fixtures/ is
public-domain material used to exercise real file handling without requiring WhisperX,
Demucs, Torch, ffmpeg, or model downloads in normal CI.
Real WhisperX benchmarking is available through the manual Manual ML Benchmark
workflow. It installs ffmpeg and the ml extra, runs against the same fixture, and
uploads the .lrc, debug files, and benchmark report as workflow artifacts.
Project details
Release history Release notifications | RSS feed
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 wispr_lrc-0.1.2.tar.gz.
File metadata
- Download URL: wispr_lrc-0.1.2.tar.gz
- Upload date:
- Size: 6.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
923d8377b59ca98056af8dbbdce5b964c8dc2ca483376c4d8a9abd1bb8f38949
|
|
| MD5 |
87d38b2fc7a220493c6e71c7e6844675
|
|
| BLAKE2b-256 |
9bea6b3129e08efaad0cbe6c3ec4aefeee80ee3c5b3b6140a6b1145783011380
|
File details
Details for the file wispr_lrc-0.1.2-py3-none-any.whl.
File metadata
- Download URL: wispr_lrc-0.1.2-py3-none-any.whl
- Upload date:
- Size: 25.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
249dc96433ca0ad0702de5486c155d578e1b72f8381e7421a640a775a7e45793
|
|
| MD5 |
5254ff9c5c63a117607e345068d578e1
|
|
| BLAKE2b-256 |
d95b2665255fa007cb11f1e3b5145cd5ff7c6cf6263b32a06116be3393665cce
|