Skip to content

TDT beam search fails above ~40-90s of audio: "zero-duration expansion did not reduce score" (greedy on the same audio is fine) #61

Description

@aanchan

parakeet_capi_transcribe_pcm_nbest_json aborts on longer inputs with

tdt_beam_search: zero-duration expansion did not reduce score

while greedy decoding of the same audio with the same model succeeds. It reads like an internal invariant that long inputs violate, rather than a bad-input case.

Environment

  • parakeet.cpp v0.5.0, released lib-macos-metal-arm64 bundle (ABI 6)
  • macOS arm64, Metal backend
  • Model: mudler/parakeet-cpp-gguftdt-0.6b-v3-q4_k.gguf
  • Audio: 16 kHz mono float PCM, AMI meeting recordings (~100s each)

What fails

22 of 23 AMI clips (~100s each) fail. One succeeded, and only at beam 4.

It is not a beam-width interaction — beam 1 fails identically to beam 8:

beam_size=1  FAIL   beam_size=2  FAIL   beam_size=4  FAIL   beam_size=8  FAIL

What succeeds on the identical audio

  • parakeet_capi_transcribe_pcm (greedy) — 242 words, no error
  • parakeet_capi_transcribe_pcm_batch_json (greedy + timestamps) — 242 words, 242 word records
  • The same N-best call on the first 30s or 40s of that same file

So the encoder, the model and the audio are all fine; it is specific to the beam search path at length.

Threshold varies with content, not a fixed limit

Truncating each file to N seconds and decoding at beam 4:

file length 30s 40s 50s 60s 70s 80s 90s
ES2004a_FEE013 100.6s ok ok ok fail fail fail fail
EN2002c_MEE071 100.0s ok ok ok ok ok ok fail
ES2004b_MEO015 105.7s ok ok fail fail fail fail fail

All three pass at 30s and 40s and fail before 100s, at different points — consistent with something accumulating over frames rather than a hard cap.

Possibly model-specific

The same 100.6s clip decodes fine at beam 2, 4 and 8 with tdt_ctc-1.1b-q4_k.gguf. Only tdt-0.6b-v3 failed here, so it may be an interaction between that checkpoint's duration predictions and the expansion check.

Minimal reproduction

# ctypes against libparakeet.dylib from the v0.5.0 release
ptr = lib.parakeet_capi_transcribe_pcm_nbest_json(
    ctx, samples_p, len(samples), 16000, 4, 1, 1, None)
# ptr is NULL; parakeet_capi_last_error(ctx) reports the message above.
# Truncating `samples` to 40s makes the same call succeed.

Possibly related to #55 (error above 5 min), though the threshold here is far lower and the message differs.

Not blocking for us — we moved to transcribe_pcm_batch_json, which gives greedy output with per-word timestamps and no beam search. Reporting because the failure is silent-until-it-isn't for anyone relying on N-best over long audio.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions