transcribe-cpp
Python bindings for transcribe.cpp, a C/C++ speech-to-text library built on ggml.
Status: in development. Until wheels are published, use a locally built
libtranscribethrough repo auto-discovery orTRANSCRIBE_LIBRARY.
Upgrading from 0.1? See the
0.2 migration guide,
including the replacement of gpu_device= with exact device objects.
import transcribe_cpp
with transcribe_cpp.Model("model.gguf") as model:
with model.session() as session:
result = session.run(pcm_float32_16k_mono)
print(result.text)
run() takes mono 16 kHz float32 PCM (buffer-protocol object or sequence). It
does not decode containers or resample; convert audio before calling it.
import numpy as np
pcm = np.asarray(audio, dtype=np.float32) # 1-D, 16 kHz mono
# Downmix stereo first; 2-D input is rejected:
# pcm = audio.mean(axis=1).astype(np.float32)
result = session.run(pcm)
Punctuation, capitalization, and text normalization
Generic run controls use "default" to preserve each model family's shipped
behavior. Models advertising model.supports("pnc") accept pnc="off" or
pnc="on"; models advertising model.supports("itn") accept the equivalent
itn values. The options are available on run(), run_batch(), stream(),
and the one-shot transcribe() helper.
result = session.run(pcm, pnc="off", itn="on")
Prompting
vocabulary (custom terms), prompt (context, or the instruction under
task="instruct") and prefix (text the model continues from) take effect
where model.supports() reports "vocabulary", "context_prompt",
"instruct" or "transcript_prefix".
result = session.run(pcm, vocabulary=["Kubernetes", "gRPC"])
Streaming models expose incremental transcription with committed/tentative
text views — see examples/stream_wav.py:
with model.session() as session, session.stream() as stream:
for chunk in pcm_chunks:
stream.feed(chunk)
text = stream.text() # .committed (stable) + .tentative
stream.finalize()
result = stream.snapshot() # language, segments, words, tokens, timings
Long transcriptions can be cancelled from another thread with
session.cancel() — the run raises Aborted with the partial transcript on
exc.partial_result (same for OutputTruncated).
Diarization
Models whose model.roles include Role.DIARIZE (Sortformer) answer "who
spoke when" through a diarize session. run() returns SpeakerSegment
rows (speaker_id in 1..model.diarize_info.max_speakers), grouped by
speaker. Locking, Busy, cancel() and close() work as on Session. A
model without the role raises UnsupportedRole, as model.session() and
model.capabilities do on a model without Role.ASR (Sortformer serves only
Role.DIARIZE).
with model.diarize_session() as diarizer:
turns = diarizer.run(pcm, family=transcribe_cpp.SortformerDiarizeOptions(
preset="very_high_latency"))
for turn in turns:
print(turn.speaker_id, turn.t0_ms, turn.t1_ms)
Language ID
Models whose model.roles include Role.LANGID (VoxLingua107 ECAPA-TDNN)
identify the spoken language through a langid session. run() returns a
LangIdResult with candidates ranked by p. Codes are the model's own labels
("iw", "jw"; model.langid_label_index("he") resolves aliases), so match
result.code against the ASR model's capabilities.languages yourself.
allowed=None scores every label; allowed_mass is the unrestricted
probability the allowed set captured. An empty allowed list raises
InvalidArgument; clips under model.langid_info.min_audio_ms raise
InputTooShort, and longer ones than max_audio_ms are scored on their first
max_audio_ms. Every allowed label comes back as a candidate. Locking,
Busy, cancel() and close() work as on Session.
with model.langid_session() as lid:
result = lid.run(pcm, allowed=["en", "de", "fr"])
print(result.code, result.candidates[0].p, result.allowed_mass)
Voice activity detection
Models whose model.roles include Role.VAD (Silero VAD, GGUF or the
whisper.cpp .bin) score speech probability per frame of
model.vad_info.frame_samples samples through a VAD session. run() scores one
clip and returns a VadResult with probs and speech segments
(start_sample/end_sample; options default to Silero's
get_speech_timestamps). stream_feed() streams audio of any chunk size and
returns the probabilities of the frames each call completed (first_frame is
the position of the first); stream_flush() scores the zero-padded remainder
and ends the stream, stream_reset() drops it. The VAD stream does not take
the model's ASR stream lease. Locking, Busy, cancel() and close() work as
on Session.
with model.vad_session() as vad:
for seg in vad.run(pcm, min_silence_ms=300).segments:
print(seg.start_sample, seg.end_sample)
frame = model.vad_info.frame_samples
probs = []
for chunk in chunks:
r = vad.stream_feed(chunk)
print(f"{len(r.probs)} frames from sample {r.first_frame * frame}")
probs.extend(r.probs)
probs.extend(vad.stream_flush().probs)
Backends
Model(backend=...) applies a backend policy ("auto" uses the best
available). transcribe_cpp.backends() returns process-local device objects;
pass one as Model(device=device) for exact selection with no fallback. Persist
a device's device_id, not its runtime handle or index. backend_available(kind)
checks whether a backend policy can currently be satisfied.
device = next(d for d in transcribe_cpp.backends() if d.device_type == "cpu")
with transcribe_cpp.Model("model.gguf", device=device) as model:
print(model.device)
| Variable | Effect |
|---|---|
TRANSCRIBE_BACKEND |
overrides the "auto" default; explicit backend= still wins |
TRANSCRIBE_NATIVE_PROVIDER |
forces an installed native provider package, for example cu12 |
TRANSCRIBE_LIBRARY |
loads exactly this shared library |
Planned wheels will bundle CPU plus platform accelerators;
transcribe-cpp[cu12] will add the CUDA 12 provider.
Running from a working tree
The binding loads the native library at import and verifies its ABI layout and
version before use. Build a shared library, then run from the repo or point
TRANSCRIBE_LIBRARY at it:
cmake -B build-shared -DTRANSCRIBE_BUILD_SHARED=ON
cmake --build build-shared --target transcribe
cd bindings/python
PYTHONPATH=src uv run --no-project python examples/transcribe_wav.py \
../../models/whisper-tiny.en/whisper-tiny.en-Q5_K_M.gguf ../../samples/jfk.wav
No-model tests always run; model tests skip unless smoke assets are present.
Override paths with TRANSCRIBE_SMOKE_MODEL, TRANSCRIBE_SMOKE_AUDIO, and
TRANSCRIBE_SMOKE_STREAMING_MODEL.
cd bindings/python
TRANSCRIBE_LIBRARY=../../build-shared/src/libtranscribe.dylib \
uv run --extra test pytest
Notes
- One compute call at a time per
Model: the binding serializes calls across all sessions of a model with a model-wide lock (load one model per worker for parallelism). While a stream is active, other runs and stream begins on that model raisetranscribe_cpp.Busy. See theModeldocstring. - Import package:
transcribe_cpp - Distribution:
transcribe-cpp - License: MIT
Metadata
Release files for transcribe-cpp 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| transcribe_cpp-0.4.0.tar.gz | 118.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| transcribe_cpp-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 165.2 kB
Release files / transcribe_cpp-0.4.0.tar.gz
| Download URL | transcribe_cpp-0.4.0.tar.gz |
|---|---|
| Size | 118.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
80255c52ec4109c9fc8e865f6585a19215456b75d71848ec16b03cb6ea980eb6
|
|
BLAKE2b-256 checksum How to use checksums |
391a31460b4a253d2080ac062d77de1796ddc8cd27d71f0ac588f04e5374b2fc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logRelease files / transcribe_cpp-0.4.0-py3-none-any.whl
| Download URL | transcribe_cpp-0.4.0-py3-none-any.whl |
|---|---|
| Size | 47.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9e1b8e522944bb3771829af91f5517a75fe1887a913329d8a25637f05adeed48
|
|
BLAKE2b-256 checksum How to use checksums |
9f6f526ea6b0e430eb7d526bf8508634aa671b9a7db1a0e5b24ccf2d03e15af5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency log