Skip to main content

granite-speech

A Whisper-like Python library for IBM's Granite Speech models.

The goal is to make speech-to-text with Granite as simple as Whisper:

pip install granite-speech
python - <<'PY'
import granite_speech

model = granite_speech.load_model()        # defaults to granite-speech-4.1-2b
result = model.transcribe("audio.wav")     # arbitrary-length audio
print(result["text"])
PY

…and from the command line:

granite-speech audio.wav --model granite-speech-4.1-2b --output_format srt

Install

Granite Speech requires Python 3.10 or later. Install the published package from PyPI:

pip install granite-speech

In a uv-managed project, add it as a dependency:

uv add granite-speech

For one-off CLI use without adding it to a project:

uvx granite-speech audio.wav --output_format txt

Granite Speech depends on PyTorch. If you need a specific CUDA build, install matching torch and torchaudio wheels first, then install Granite Speech:

pip install --index-url https://download.pytorch.org/whl/cu124 torch torchaudio
pip install granite-speech

Python API

import granite_speech

model = granite_speech.load_model(
    "granite-speech-4.1-2b",
    device=None,          # optional llama.cpp device override; use "cpu" for CPU-only
    llama_cpp_quant="Q4_K_M",
)

result = model.transcribe(
    "audio.wav",
    task="transcribe",
    language=None,        # source-language hint only, never detected
    keyword_biases=["Granite Speech", "watsonx.ai"],
    max_new_tokens=None,  # auto-size per window; pass an int to force a cap
    chunk_length=30.0,
    chunk_overlap=0.0,
    segmentation="fixed",  # use "vad" to skip silence and cut on speech activity
    clip_timestamps=None,  # e.g. "10,20" or "10,20,30,45" for selected ranges
)

print(result["text"])

result has stable keys:

{
    "text": str,
    "segments": [
        {
            "id": int,
            "start": float,
            "end": float,
            "text": str,
            "temperature": float,
            # "tokens": list[int],  # only present when the backend provides token IDs
        }
    ],
    "language": str | None,
    "target_language": str | None,
    "warnings": list[dict],
}

The segment id and temperature fields are included as Whisper-familiar compatibility metadata. Granite Speech does not fabricate Whisper confidence fields such as avg_logprob, compression_ratio, or no_speech_prob.

This shape is available as an importable TypedDict for type-checking your own code: from granite_speech import TranscriptionResult (also Segment, Word, Speaker, Warning). It is documentation only — results are plain dicts at runtime.

For translation, pass an explicit source language. If target_language is omitted, it defaults to English:

result = model.transcribe("fr.wav", task="translate", language="fr")

Use the plus model for the richer transcription prompt modes from its model card:

plus = granite_speech.load_model("granite-speech-4.1-2b-plus")

speakers = plus.transcribe("meeting.wav", prompt_mode="speaker_attributed")
timestamps = plus.transcribe(
    "meeting.wav",
    prompt_mode="word_timestamps",
    max_new_tokens=10000,
)

prompt_mode="speaker_attributed" renders the model-card speaker tag prompt, and prompt_mode="word_timestamps" renders the word timestamp prompt. The returned text strips the model-card tags, parsed segments include raw_text, and structured fields are attached as segments[].speakers or segments[].words plus top-level speakers or words. Pass prefix_text= with the plus model to use the incremental decoding hook shown in the model card.

The module-level convenience API is also available:

result = granite_speech.transcribe("audio.wav")

Migrating existing Whisper code? See the porting guide for the supported aliases and intentional differences.

Release validation commands, including the opt-in real-weights llama.cpp smoke, are documented in docs/release-checks.md.

CLI

granite-speech audio.wav --model granite-speech-4.1-2b --output_format txt
granite-speech audio.wav --llama_cpp_quant Q4_K_M
granite-speech audio.wav --task translate --language fr --output_format json
granite-speech audio.wav --keyword "Granite Speech" --keyword watsonx.ai
granite-speech meeting.wav --model granite-speech-4.1-2b-plus --prompt_mode speaker_attributed
granite-speech meeting.wav --model granite-speech-4.1-2b-plus --prompt_mode word_timestamps --max_new_tokens 10000
granite-speech audio.wav --segmentation vad --chunk_length 30
granite-speech audio.wav --clip_timestamps 10,20
granite-speech audio.wav --output_format srt --max_line_width 42 --max_line_count 2
granite-speech audio.wav --output_format all --output_dir transcripts/

Supported output formats are txt, srt, vtt, tsv, json, and all. By default, the CLI writes txt output to the current directory using the input filename stem, so granite-speech audio.wav writes ./audio.txt; pass --output_dir to choose another directory. For subtitle output, --max_line_width and --max_line_count wrap SRT/VTT cue text without changing TXT, TSV, or JSON output.

Pass keyword_biases=[...] in Python or repeat --keyword in the CLI to use Granite Speech's keyword list biasing. The library renders the model-card prompt form, for example transcribe the speech to text. Keywords: Granite Speech, watsonx.ai.

Long audio is processed as fixed-size windows. By default, max_new_tokens=None auto-sizes the generation budget from the window length: 30-second windows use 200 tokens, and longer windows scale proportionally. Pass an explicit integer to force the same token cap on every window.

For long recordings with substantial silence, pass segmentation="vad" in Python or --segmentation vad in the CLI. VAD mode uses built-in energy-based voice activity detection to skip silent regions, pad detected speech, merge speech separated by short silences, and split any speech span longer than chunk_length. Tune it with vad_threshold, vad_min_speech_duration, vad_min_silence_duration, and vad_speech_pad.

To transcribe selected regions, pass clip_timestamps= in Python or --clip_timestamps in the CLI as comma-separated seconds. Pairs select explicit ranges such as 10,20; an odd final timestamp selects through the end of the file, such as 30 or 10,20,30. Segment timestamps stay relative to the original audio file.

Exit codes:

  • 0: output produced with no per-window failures
  • 1: output produced, but one or more windows failed and are listed in warnings
  • 2: unrecoverable argument, model, audio, or download failure

Pre-download model weights for offline or container builds:

granite-speech download granite-speech-4.1-2b --download_root /models/granite-speech
granite-speech download granite-speech-4.1-2b --llama_cpp_quant Q4_K_M
granite-speech download granite-speech-4.1-2b-plus --llama_cpp_quant Q4_K_M

llama.cpp

Granite Speech uses the llama.cpp GGUF backend. The loader expects llama-cli to be installed and the selected model to have an official GGUF variant.

The backend shells out to llama-cli because Granite Speech audio is exposed through llama.cpp's multimodal CLI. Install llama.cpp separately, for example with Homebrew:

brew install llama.cpp

The default GGUF quant is Q4_K_M. Override it with llama_cpp_quant="Q8_0" in Python or --llama_cpp_quant Q8_0 in the CLI. Local GGUF paths are also supported when the matching mmproj-model-f16.gguf file is in the same directory, or by passing llama_cpp_mmproj=. The official base and Plus GGUF repos, ibm-granite/granite-speech-4.1-2b-GGUF and ibm-granite/granite-speech-4.1-2b-plus-GGUF, are accepted as model aliases.

Audio Inputs

Path inputs infer sample rate from the file. Raw numpy arrays or torch tensors must pass sample_rate=.

The loader normalizes audio to mono, 16 kHz, float32. WAV and FLAC are the primary supported file paths through soundfile; MP3/M4A/AAC are best effort through the installed audio libraries. For guaranteed container support, transcode to WAV or FLAC before calling the library.

GRANITE_SPEECH_MAX_AUDIO_SECONDS caps decoded duration as a decompression-bomb guard. The default is 4 hours; set it to 0 to disable the cap.

Cache and Offline Use

Cache resolution order:

  1. download_root=
  2. GRANITE_SPEECH_CACHE
  3. HF_HUB_CACHE
  4. HF_HOME/hub
  5. ~/.cache/granite-speech

Use local_files_only=True with load_model() for offline runs after weights are cached.

Current Limitations

This is an early v1 implementation of the original spec contract. Fixed-window mode uses window-granular timestamps and hard-cut boundaries may split speech. VAD mode can cut on speech activity, but it is energy-based rather than a learned speech detector. The granite-speech-4.1-2b-plus parser supports the model-card [Speaker N]: and [T:N] tag forms; word starts are inferred from the previous word end, and speaker turns do not include intra-window timing. Streaming is not implemented yet.

Metadata

Release files for granite-speech 0.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for granite-speech 0.0.3
File Size Uploaded Provenance Actions
granite_speech-0.0.3.tar.gz 62.8 kB Without provenance Details for granite_speech-0.0.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for granite-speech 0.0.3
File Interpreter ABI Platform Actions
granite_speech-0.0.3-py3-none-any.whl Python 3 none any Details for granite_speech-0.0.3-py3-none-any.whl

Total release size: 111.0 kB

Release files / granite_speech-0.0.3.tar.gz

Download URL granite_speech-0.0.3.tar.gz
Size 62.8 kB
Tags Source
SHA-256 checksum
How to use checksums
6cc4c5a182cf65497076ec7995ea3ed271f32307c97b4d299fe48a4fdd41dc51
BLAKE2b-256 checksum
How to use checksums
fbf124f9141744e28111e2cc18ff5767960b830f9d840e5f8b8fbd89ad72dc2d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / granite_speech-0.0.3-py3-none-any.whl

Download URL granite_speech-0.0.3-py3-none-any.whl
Size 48.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
de4a2de2349847971a0de85b0011d1efc8cfd3d29f78719fee2e10e559edf653
BLAKE2b-256 checksum
How to use checksums
ee8c36a906fb81e38405fda8d750bf4bd6c134518a7762af332ee740545ef90b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Security for granite-speech 0.0.3

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.0.3 This release

2 release files No provenance

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