Skip to content

TranscriptionSynchronizer should flush text for zero-duration audio segments #2384

Description

@coderabbitai

Summary

TranscriptionSynchronizer should settle a zero-duration segment by sending its text through the normal transcription output without audio pacing.

Problem

In @livekit/agents 1.6.3, SegmentSynchronizerImpl waits for onPlaybackStarted before it releases the first text segment. This behavior blocks a segment when TTS returns non-empty text but pushes zero audio frames.

For this segment shape:

  • Text input ends.
  • Audio input ends.
  • Pushed audio duration is zero.
  • SyncedAudioOutput.captureFrame does not run.
  • onPlaybackStarted does not occur.
  • The segment does not receive the normal playback-finished or playout-drift settlement path.

As a result, the text is withheld from the transient lk.transcription stream. A later audible reply can recover the stream, but the zero-duration reply never receives live transcription.

Required behavior

When a segment has ended text input and audio input, and its pushed audio duration is zero, TranscriptionSynchronizer should settle that segment immediately and flush its text unsynchronized. It must not wait for a playback start that cannot occur.

This path should preserve normal paced delivery for segments that contain audio.

Rationale

A non-empty agent reply can remain available through application conversation-item events and chat context, but consumers of the lk.transcription stream still miss the live transcript for the affected reply. Local application-side re-emission is unsafe because it can duplicate text when timing races resolve normally. The synchronizer owns the segment state and can determine zero duration without a race.

Affected area

  • @livekit/agents
  • Voice transcription synchronization
  • SegmentSynchronizerImpl
  • TranscriptionSynchronizer / SyncedAudioOutput segment lifecycle

Reproduction

  1. Enable synchronized transcription.
  2. Generate a reply with non-empty text.
  3. Make TTS complete without producing audio frames.
  4. Observe that the segment has no playback start.
  5. Observe that its text does not arrive on lk.transcription.
  6. Generate a later reply with audio frames.
  7. Observe that the later reply can deliver transcription.

Acceptance criteria

  • A segment with completed text, completed audio, and zero pushed audio duration flushes its complete text unsynchronized.
  • The segment does not wait for onPlaybackStarted.
  • A zero-duration segment does not block transcription delivery for subsequent audible segments.
  • Segments with one or more audio frames retain existing paced transcription behavior.
  • Add regression coverage for non-empty text with zero TTS audio frames.

Local context

Quippy added synchronized transcription pacing in PR #79. Its integration test currently verifies that a zero-frame reply does not wedge the next audible reply. The application does not add a local raw-output fallback because the SDK has the authoritative segment state and a watchdog could double-deliver text.

Requested by @jonathanli12.

Backlinks:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions