CrisperWhisper

repository·main·Indexed 21 days ago

https://github.com/nyrahealth/crisperwhisper

A high-accuracy speech recognition system providing controllable transcription modes (Verbatim vs. Intended) and precise word-level timings. It supports multilingual longform transcription and high-performance inference via CTranslate2, including speculative decoding for NVIDIA GPUs. The library offers various model sizes (turbo, medium, small, large) and specialized Pro versions with hotword boosting.

Tokens
26.3K
Snippets
80
Records
100
Agent score
72%

What's inside crisperwhisper

  1. Transcription Modes: Verbatim vs Intended

    main

    CrisperWhisper 2 supports two transcription styles that differ only by the decoder prompt prefix. The encoder output is identical for both, making them highly efficient to run.

    • Verbatim (default): Preserves disfluencies, stutters, filler words (e.g., [UH], [UM]), repetitions, and false starts.
    • Intended: Produces a clean, fluent, and readable transcript.

    Use mode="verbatim" for raw data preservation or mode="intended" for clean text.

    # Verbatim: preserves disfluencies, stutters, filler words
    result = model.transcribe("audio.wav", mode="verbatim")
    
    # Intended: clean, fluent transcript
    result = model.transcribe("audio.wav", mode="intended")
  2. How model conversion works on the CT2 backend

    main

    When using the ct2 backend, HuggingFace models are automatically converted to the CTranslate2 format upon the first load.

    • Caching: Converted models are stored in ~/.cache/crisperwhisper/. You can change this location by setting the CRISPERWHISPER_CACHE environment variable.
    • Direct Loading: You can bypass conversion by passing a path to a pre-converted CTranslate2 model directory directly to CrisperWhisperModel(..., backend="ct2").
  3. How Hallucination Mitigation works

    main

    Repetition-loop detection and repair is enabled by default (hallucination_mitigation=True) on both backends.

    Mechanism: After a greedy pass, the output is scanned for consecutive n-gram repetitions. If a loop is found, the output is rewound, one "escape" token is forced (the loop-starting token is banned for that step), and decoding resumes.

    Customizing Thresholds: Default thresholds for triggering repair:

    • 1-gram (unigrams): 8 repeats
    • 2-gram (bigrams): 8 repeats
    • 3-gram (trigrams): 4 repeats
    • 4-gram: 3 repeats
    • 5-gram: 3 repeats

    You can disable this per call with hallucination_mitigation=False or use the lower-level generate_with_repair API to provide custom detect_reps thresholds.

    # Disable mitigation per call
    result = model.transcribe("audio.wav", hallucination_mitigation=False)
    
    # Advanced: Custom thresholds via low-level API
    from crisperwhisper.hallucination import generate_with_repair
    
    gen_ids, n_repairs = generate_with_repair(
        engine, features, prompt_tokens,
        detect_reps={1: 10, 2: 6, 3: 3, 4: 2, 5: 2},  # custom thresholds
        keep_reps=1,
        max_repairs=3,
    )
  4. How backends and models work together

    main

    CrisperWhisper 2.0 is designed around two interchangeable backends that run the same high-level algorithms (longform, hallucination repair, and word timing) but differ in execution speed and capabilities:

    1. CTranslate2 (ct2): A high-performance backend optimized for speed. It supports advanced features like speculative decoding and dual-mode transcription (processing verbatim and intended text in a single batched pass). It is the recommended backend for production use on NVIDIA GPUs.
    2. Transformers: A portable backend using pure PyTorch. It is slower but highly compatible across different hardware (macOS, Windows, CPU). Note that for word-level timestamps, it uses attn_implementation="eager" to access cross-attention weights.

    When using backend="auto", the library will attempt to use ct2 if the [ct2] extra is installed, otherwise it defaults to transformers.

  5. Quickstart: Transcribe audio with CrisperWhisper

    main

    To use CrisperWhisper, import CrisperWhisperModel. You can use the default large model or specify a size like turbo, medium, or small.

    Verbatim Transcription (Default)

    Transcribes exactly what was said, including fillers, repetitions, stutters, and vocal events.

    Intended Transcription

    Produces a clean, readable version of the speech, formatting numbers, dates, and emails.

    Word-level Timestamps

    Enables precise start and end times for every word.

    Verbatimize

    Upgrades an existing clean transcript by inserting the actual disfluencies present in the audio.

    from crisperwhisper import CrisperWhisperModel
    
    # Initialize the model (defaults to nyralabs/CrisperWhisper2.0_large)
    model = CrisperWhisperModel() 
    # or pick a size: CrisperWhisperModel("turbo")
    
    # 1. Verbatim transcription (default)
    result = model.transcribe("meeting.wav", language="en")
    print(result.text)
    
    # 2. Intended: the clean, readable version
    clean = model.transcribe("meeting.wav", language="en", mode="intended")
    
    # 3. Word-level timestamps
    result = model.transcribe("meeting.wav", language="en", word_timestamps=True)
    for w in result.words:
        print(f"{w.start:6.2f}-{w.end:6.2f}  {w.word}")
    
    # 4. Verbatimize: upgrade an existing clean transcript
    result = model.verbatimize("clip.wav", "I think we should ship it Friday.")
    from crisperwhisper import CrisperWhisperModel
    
    model = CrisperWhisperModel()          # nyralabs/CrisperWhisper2.0_large
    # or pick a size: CrisperWhisperModel("turbo")  # turbo / medium / small
    
    # Verbatim transcription (default): every filler, repetition, stutter,
    # false start, and vocal event
    result = model.transcribe("meeting.wav", language="en")
    print(result.text)
    
    # Intended: the clean, readable version
    clean = model.transcribe("meeting.wav", language="en", mode="intended")
    
    # Word-level timestamps
    result = model.transcribe("meeting.wav", language="en", word_timestamps=True)
    for w in result.words:
        print(f"{w.start:6.2f}-{w.end:6.2f}  {w.word}")
    
    # Verbatimize: upgrade an existing clean transcript with the
    # disfluencies that are actually in the audio
    result = model.verbatimize("clip.wav", "I think we should ship it Friday.")
  6. Install CrisperWhisper

    main

    You can install CrisperWhisper using different backends depending on your hardware requirements:

    • NVIDIA GPU (Linux): This is the fastest option and includes speculative decoding. It requires an NVIDIA driver; CUDA libraries are installed via pip.
    • Pure PyTorch: This runs anywhere PyTorch is supported, including macOS, Windows, and CPU-only environments.
    # For NVIDIA GPU (Linux) with CTranslate2 support
    pip install "crisperwhisper[ct2]"
    
    # For Pure PyTorch (macOS, Windows, CPU)
    pip install "crisperwhisper[transformers]"
    # NVIDIA GPU (Linux): fastest, includes speculative decoding.
    pip install "crisperwhisper[ct2]"
    
    # Pure PyTorch: runs anywhere torch does (macOS, Windows, CPU)
    pip install "crisperwhisper[transformers]"
  7. Install CrisperWhisper with specific backends

    main

    The core crisperwhisper package does not include an inference backend by default. You must install one or both using extras via pip:

    • CTranslate2 ([ct2]): Fastest backend, supports speculative decoding. Requires an NVIDIA driver (CUDA libraries are provided via pip). Works on Linux x86_64.
    • Transformers ([transformers]): Portable PyTorch backend. Works anywhere torch runs (macOS, Windows, CPU). Requires torch>=2.4.
    • Both ([all]): Installs both backends.

    Important Notes:

    • Do not install faster-whisper or upstream ctranslate2 alongside [ct2], as they will overwrite the specialized fork.
    • For Intel Macs where torch>=2.4 is unavailable, you can install a compatible pair manually: pip install crisperwhisper "transformers==4.49.*" "torch==2.2.*"
    pip install crisperwhisper[ct2]            # CTranslate2 (fast, speculative decoding)
    pip install crisperwhisper[transformers]   # pure torch + HuggingFace Transformers
    pip install crisperwhisper[all]            # both backends
  8. Configure Quantization (compute_type)

    main

    You can control the precision of the model using the compute_type parameter during model initialization to balance speed and memory usage.

    • "float16" (default): Fastest on modern GPUs.
    • "int8_float16": Smaller model size with similar speed.
    # FP16 (default, fastest on modern GPUs)
    model = CrisperWhisperModel("nyrahealth/CrisperWhisper2", compute_type="float16")
    
    # INT8+FP16 (smaller model size, similar speed)
    model = CrisperWhisperModel("nyrahealth/CrisperWhisper2", compute_type="int8_float16")
  9. Implement a custom transcription engine using EngineProtocol

    main

    If you are building a new inference backend for CrisperWhisper, you must implement the EngineProtocol. This is a typing.Protocol used for structural typing, meaning engines are checked against this interface without requiring explicit inheritance or runtime registration.

    All shared CrisperWhisper algorithms (such as prompt building, longform strategies, word timing, and hallucination repair) are written against this protocol. The protocol covers four main functional areas: tokenizer/special-id state, feature extraction, decoding, and cross-attention (for word timing).

    Optional Capabilities

    Some engines implement additional capabilities that are detected via hasattr rather than being part of the formal protocol:

    • generate_with_attention: Used by SpeculativeDecoder to route word-timing through speculative capture.
    • generate_dual_greedy: Used by CT2Engine to power transcribe_dual functionality.
  10. How TransformersEngine and CT2Engine relate

    main

    The TransformersEngine is designed to be a drop-in peer to the CT2Engine. It implements the same high-level engine surface, including:

    • Feature extraction
    • Prompt-prefixed greedy generation
    • Hallucination repair (rewind/escape)
    • Cross-attention capture for word timing

    Key Differences:

    • Performance: TransformersEngine is slower as it lacks the fused kernels and int8 support of CTranslate2.
    • Speculative Decoding: Not supported in the Transformers backend.
    • Attention Capture: In the Transformers backend, attention is captured inline during the single generation pass, whereas CT2 uses a different mechanism. This requires attn_implementation="eager" to be used.
  11. Speculative Decoding Acceptance Modes: strict vs semantic

    main

    The speculative decoder supports two modes for determining if draft tokens should be accepted by the main model:

    1. strict (default): Requires an exact match between the draft model's proposed tokens and the main model's predicted tokens. If any token differs, the sequence is truncated and corrected.
    2. semantic: Allows for a higher acceptance rate by relaxing requirements for punctuation and casing. It uses a _semantic_accept_count logic to allow tokens that are semantically similar even if they aren't exact matches, which can significantly speed up decoding at the cost of slight precision variance in formatting.
  12. How hallucination mitigation works in speculative decoding

    main

    When hallucination_mitigation is enabled, the decoder protects against repetition loops (e.g., repeating the same word or phrase indefinitely).

    The Repair Process:

    1. Detection: The system searches the generated sequence for $n$-gram loops (using find_token_loop).
    2. Rewind: If a loop is found, the decoder rewinds the sequence to the point just before the loop started.
    3. Re-decode: The tail is re-decoded using the main model (not the draft model) with the token that triggered the loop explicitly banned (ban_first_tokens).
    4. Attention Alignment: To ensure the attention matrix remains valid for word-timing, the attention rows from the rejected/looped tokens are dropped, and the new attention rows from the main model's re-decoding are appended. This maintains a 1:1 mapping between gen_ids and the attention matrix.