ASR Language Configuration#
The language field in Docling's Whisper ASR option classes controls which language the model decodes audio as, using ISO 639-1 codes (e.g., "en", "zh", "fr"). All three inline ASR option classes currently default to "en", which forces English decoding regardless of actual audio content. This diverges from upstream openai-whisper's own default of language=None (auto-detect from the first 30 seconds). Using non-English audio without overriding this default causes mistranslation; see Known Issue for details.
Key files:
docling/datamodel/pipeline_options_asr_model.py— defines the option classes andlanguagefield defaultsdocling/datamodel/asr_model_specs.py— preset constants (e.g.,WHISPER_TINY,WHISPER_TURBO_NATIVE)docling/pipeline/asr_transcriber.py— forwardslanguageto the underlying transcription library
Language Field per Option Class#
All three subclasses of InlineAsrOptions define language independently (the base class does not). Each currently uses a non-optional str with a default of "en":
| Class | Language field | Default | Lines |
|---|---|---|---|
InlineAsrNativeWhisperOptions | language: str | "en" | |
InlineAsrMlxWhisperOptions | language: str | "en" | |
InlineAsrWhisperS2TOptions | language: str | "en" |
InlineAsrWhisperS2TOptions additionally validates this field via a model_validator: passing a non-English language code for English-only models (e.g., tiny.en, distil-large-v3) raises a ValueError at construction time. The set of English-only S2T repos is defined in _ENGLISH_ONLY_S2T_REPOS.
InlineAsrNativeWhisperOptions also exposes two additional decoding controls added by PR #3717: beam_size: Optional[int] = None and condition_on_previous_text: Optional[bool] = None. Both default to None, delegating to Whisper's own defaults.
How Language Is Forwarded to the Underlying Library#
The transcriber reads the language field from options in __init__ and passes it directly to the backend without transformation:
- Native Whisper:
self.language = asr_options.language→whisper.transcribe(..., language=self.language) - MLX Whisper: same pattern →
mlx_whisper.transcribe(..., language=self.language, ...) - WhisperS2T: passes as a list →
transcribe_with_vad([...], lang_codes=[self.language], ...)
Because the field type is currently str (not Optional[str]), there is no first-class None path for auto-detection, though passing None directly via a custom options instance propagates through to the underlying library.
Language in Preset Constants#
Preset constants in asr_model_specs.py follow two patterns:
- MLX auto-selecting and explicit MLX presets (e.g.,
WHISPER_TINYon Apple Silicon,WHISPER_TINY_MLX): explicitly setlanguage="en". - All native presets (e.g.,
WHISPER_TINY_NATIVE,WHISPER_TURBO_NATIVE, English-only variants likeWHISPER_TINY_EN_NATIVE, Distil-Whisper variants likeWHISPER_DISTIL_LARGE_V3_NATIVE): omit thelanguagefield entirely, inheriting the class default of"en". - WhisperS2T presets: all explicitly set
language="en".
Auto-selecting presets for the native path (e.g., WHISPER_TINY on non-Apple hardware) rely implicitly on the class default rather than an explicit language= argument .
Known Issue: Default Breaks Non-English Audio#
Issue #3892 (opened 2026-07-27, currently open) documents the impact: transcribing Chinese audio with default WHISPER_TINY options produces hallucinated English output instead of a faithful Chinese transcript.
Root cause: language="en" is forwarded to whisper.transcribe(), forcing the decoder into English mode. Upstream openai-whisper defaults to language=None (auto-detect from the first 30 seconds), which performs identically to an explicit language="zh" on Chinese audio.
History: PR #3717 (merged 2026-07-02) started forwarding language to whisper.transcribe() but intentionally preserved the "en" default. The issue author of the predecessor noted "the defaults are still the risk/defective ones." Issue #3892 now formally requests the change.
Proposed fix (not yet merged): change the field to Optional[str] with a None default in InlineAsrNativeWhisperOptions and InlineAsrMlxWhisperOptions:
language: Annotated[str | None, Field(...)] = None
InlineAsrWhisperS2TOptions requires separate treatment: its model_validator enforces that English-only model repos cannot be paired with non-English language codes, and will need updating to handle None.
How to Override Today#
Until the default is changed, explicitly set language when constructing options or pass None to enable auto-detection:
from docling.datamodel.pipeline_options_asr_model import InlineAsrNativeWhisperOptions
from docling.datamodel.pipeline_options import AsrPipelineOptions
# Explicit language
opts = InlineAsrNativeWhisperOptions(repo_id="tiny", language="zh")
# Auto-detect (passes None through to whisper.transcribe)
opts = InlineAsrNativeWhisperOptions(repo_id="tiny", language=None) # type: ignore
pipeline_options = AsrPipelineOptions(asr_options=opts)
For the MLX backend, set language on InlineAsrMlxWhisperOptions the same way. The task field ("transcribe" or "translate") on MLX and WhisperS2T options is a separate control: "translate" always produces English output regardless of source language .