# Extension points — openai/whisper

> Canonical page: https://codevetter.com/unpack/whisper/extension-points

# Extension points — openai/whisper

Scanned commit 86098128c0b4f24f0e2aa2994de830614b474227 (2026-08-31). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Extension is mostly class-substitution rather than plugin registration: the get_writer() dict is a mini-registry for output formats; TokenDecoder, LogitFilter, SequenceRanker, and Inference are abstract seams inside DecodingTask; new checkpoints plug in via _MODELS/_ALIGNMENT_HEADS or by path; DecodingOptions is the frozen config dataclass every knob flows through. There is no dynamic plugin discovery — all seams require editing source.
- Output formats: subclass ResultWriter (set `extension`, implement write_result) and add it to the `writers` dict in get_writer() — the CLI's --output_format choices list in transcribe.py must also be updated. — [whisper/utils.py#L85-106](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/utils.py#L85-L106) [whisper/utils.py#L306-329](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/utils.py#L306-L329) [whisper/transcribe.py#L534](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/transcribe.py#L534)
- Search strategies: implement TokenDecoder (reset/update/finalize) — GreedyDecoder and BeamSearchDecoder are the built-ins — and select it in DecodingTask.__init__ where `options.beam_size is not None` chooses between them. — [whisper/decoding.py#L216-270](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L216-L270) [whisper/decoding.py#L272-404](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L272-L404) [whisper/decoding.py#L546-551](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L546-L551)
- Logit-level policies: implement LogitFilter.apply(logits, tokens) and append to DecodingTask.logit_filters, currently populated with SuppressBlank, SuppressTokens, and ApplyTimestampRules. — [whisper/decoding.py#L407-420](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L407-L420) [whisper/decoding.py#L553-570](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L553-L570)
- Reranking: SequenceRanker.rank(tokens, sum_logprobs) → indices; MaximumLikelihoodRanker (length-normalized or Google-NMT penalty) is the only implementation, assigned in DecodingTask.__init__. — [whisper/decoding.py#L179-213](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L179-L213) [whisper/decoding.py#L543](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L543)
- Inference backend: Inference defines logits() / rearrange_kv_cache() / cleanup_caching(); PyTorchInference implements it via KV-cache forward hooks — an alternative (e.g. compiled or batched backend) would subclass Inference and be wired in DecodingTask.__init__. — [whisper/decoding.py#L130-177](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L130-L177) [whisper/decoding.py#L540](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L540)
- New official models: add a CDN URL to _MODELS and a base85 gzip'd (n_layers × n_heads) mask to _ALIGNMENT_HEADS in __init__.py; unofficial/fine-tuned checkpoints work without changes by passing a file path to load_model. — [whisper/__init__.py#L17-51](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/__init__.py#L17-L51) [whisper/__init__.py#L136-145](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/__init__.py#L136-L145) [whisper/model.py#L285-292](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/model.py#L285-L292)
- DecodingOptions is the single frozen config dataclass for a decode (task, language, temperature, beam/best_of, prompt/prefix, suppress_tokens, timestamps, fp16); transcribe() forwards **decode_options straight into DecodingOptions(**kwargs), so new CLI/API knobs route through it. — [whisper/decoding.py#L80-115](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/decoding.py#L80-L115) [whisper/transcribe.py#L200](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/transcribe.py#L200)
- Languages are table-driven via LANGUAGES and TO_LANGUAGE_CODE, but special tokens are baked into the .tiktoken vocab — new languages can't be added without retraining; only aliases are cheap to extend. — [whisper/tokenizer.py#L10-128](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/tokenizer.py#L10-L128) [whisper/tokenizer.py#L340-350](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/tokenizer.py#L340-L350)
- Accelerator backends: timing.py dispatches CUDA vs CPU implementations by trying the triton path inside try/except — the established pattern for adding a new kernel backend to median_filter and dtw. — [whisper/timing.py#L36-54](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/timing.py#L36-L54) [whisper/timing.py#L141-151](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/timing.py#L141-L151)
- Normalizers are composable: EnglishTextNormalizer wires an ignore_patterns regex, a replacers dict, EnglishNumberNormalizer, and EnglishSpellingNormalizer(json map) — a new locale would follow the same class shape and export through normalizers/__init__.py. — [whisper/normalizers/english.py#L467-552](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/normalizers/english.py#L467-L552) [whisper/normalizers/__init__.py](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/normalizers/__init__.py) [whisper/normalizers/basic.py#L60-80](https://github.com/openai/whisper/blob/86098128c0b4f24f0e2aa2994de830614b474227/whisper/normalizers/basic.py#L60-L80)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
