Skip to content

Allow no-timestamp Whisper decoding to use full context#2075

Open
Emre-Akgul wants to merge 1 commit into
OpenNMT:masterfrom
Emre-Akgul:agent/whisper-no-timestamps-full-context
Open

Allow no-timestamp Whisper decoding to use full context#2075
Emre-Akgul wants to merge 1 commit into
OpenNMT:masterfrom
Emre-Akgul:agent/whisper-no-timestamps-full-context

Conversation

@Emre-Akgul

@Emre-Akgul Emre-Akgul commented Jul 11, 2026

Copy link
Copy Markdown

Summary

When Whisper timestamps are disabled, allow decoding to use the remaining text context instead of unconditionally limiting generation to half of max_length.

Timestamped decoding retains the existing limit.

This improves transcription completeness for languages that rely heavily on Whisper's byte-level fallback tokenizer, where relatively short text can consume a large number of decoder tokens.

Fixes #2074, #1856.

Reproduction

Using faster-whisper with large-v3:

segments, info = model.transcribe(
    audio_path,
    beam_size=1,
    vad_filter=False,
    without_timestamps=True,
    condition_on_previous_text=False,
)

Before the fix, both test files stop at exactly 224 re-tokenized text tokens.

Armenian

Reference:

2008 թվականի նոյեմբերի 26-ին մումբայի հարձակվողները քաղաք ժամանեցին նավակով իրենց հետ բերելով նռնակներ ինքնաձիգ զենքեր և հարվածեցին բազմաթիվ թիրախների որոնց թվում էին մարդաշատ չհաթրափաթի շիվաջի տերմինուս երկաթգծի կայարանը և հայտնի թաջ մահալ հյուրանոցը

Output before the fix:

Մումբայի հարցակվողները կաղակ ժամանեցին նավակով, իրենց հետ բերելով նրնակներ, ինքնածիկ սենքեր և հարվածեցին բազմաթիվ թիրախների, որոնց թվում էին մարդաշատ չյատրատ պատի շիվաջի տեր մինուս երկատգծի կայարան�

The replacement character at the end indicates that decoding stopped in the middle of a byte sequence.

Georgian

Reference:

იგი წინასწარ პატიმრობაშია. საბრალდებო დასკვნისა და სასამართლო პროცესის მოლოდინში, თუმცა მისი პიროვნების გასაჯაროების შემდეგ მოწმეების ნებისმიერი ჩვენება შეიძლება არაკეთილსინდისიერ მტკიცებულებად აღიარონ.

Output before the fix:

იგიც ინასდარ პატი მრობაშია საბრალდებუ დასყვნისა და სასამართლო პროცესის მოლოდინში, თუმცა მის

Armenian and Georgian rely heavily on Whisper's byte-level fallback tokenizer. As a result, even relatively short audio samples can exhaust the existing 224-token generation limit.

The Armenian reference requires 285 text tokens, which exceeds the previous 224-token limit but fits within the available no-timestamp decoder context.

The Georgian reference requires 516 text tokens, which exceeds Whisper's complete decoder context. The full reference therefore cannot fit in a single decoding window, even after removing the artificial half-context limit.

Root Cause

Whisper generation currently sets:

decoding_options.max_length = std::min(
    total_max_length / 2,
    total_max_length - start_step
);

This applies the half-context limit even when the prompt explicitly contains <|notimestamps|>.

The half-context restriction is needed for timestamped decoding because timestamp tokens refer to positions in the audio window. It is unnecessarily restrictive when timestamps are disabled and the remaining decoder context can be used entirely for text generation.

Change

For prompts containing <|notimestamps|>, use the entire remaining decoder context:

total_max_length - start_step

Timestamped decoding retains the existing half-context behavior.

With the standard no-timestamp prompt, the patched decoder can use up to 445 returned positions. Timestamped decoding remains limited to 224 positions.

Results After the Fix

Armenian

Output after the fix:

Մումբայի հարցակվողները կաղակ ժամանեցին նավակով, իրենց հետ բերելով նրնակներ, ինքնածիկ սենքեր և հարվածեցին բազմաթիվ թիրախների, որոնց թվում էին մարդաշատ չյատրատ պատի շիվաջի տել մինուս երկատգծի կայարանը և հայտնի թաճ մահալ հյուրանոցը։

The old output stopped at 224 tokens with:

կայարան�

The patched output completes normally after 261 decoder tokens, before reaching the maximum decoder-context allowance. It no longer ends in the middle of a byte sequence.

Georgian

Output after the fix:

იგიცე, ენასდარ პატიმრობაშია, საბრალდებო დასყვნისა 16-ს პროცესის მოლოდინში თუმცა მისი პირონების გასაჯაროების შემდექ მოცმეების შეიძლება არა კეთელს ინდისიერ, მთქითე ბულე ბად აყიარონ. გი�

The old output stopped at 224 tokens:

იგიც ინასდარ პატი მრობაშია საბრალდებუ დასყვნისა და სასამართლო პროცესის მოლოდინში, თუმცა მის

The patched decoder continues until the full 445-position allowance is exhausted, returning substantially more of the transcription.

The result still ends in the middle of a byte sequence because this sample requires more tokens than Whisper's complete 448-position decoder context can accommodate. This is separate from the previous artificial 224-token limit.

Interpretation

The Armenian sample demonstrates the intended behavior clearly: the transcription requires more than 224 tokens but fits within the remaining decoder context, so it can now complete normally.

The Georgian sample exceeds the model's complete decoder context even after the fix. It therefore remains truncated, but the decoder returns substantially more of the transcription than before.

Languages that rely heavily on byte-level fallback tokens should still be used with caution because they can exhaust Whisper's decoder context with comparatively short outputs. However, removing the unnecessary half-context restriction improves both transcription completeness and practical availability for these languages.

Validation

  • The C++ library builds successfully.
  • The Python bindings build successfully.
  • The existing Whisper integration test passes all three parameter sets.
  • Patched large-v3 decoding was validated using the Armenian and Georgian samples above.
  • No-timestamp decoding can use the remaining decoder context.
  • Timestamped decoding retains the existing 224-position limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow no-timestamp Whisper decoding beyond 224 tokens

1 participant