Skip to content

perf(rime): stream sentence batches and reuse WebSocket connections - #2426

Open
chasef07 wants to merge 1 commit into
livekit:mainfrom
chasef07:codex/rime-streaming-reuse
Open

perf(rime): stream sentence batches and reuse WebSocket connections#2426
chasef07 wants to merge 1 commit into
livekit:mainfrom
chasef07:codex/rime-streaming-reuse

Conversation

@chasef07

@chasef07 chasef07 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Description

With Rime WebSocket segment: 'never', the current plugin sends its provider flush only after all input text has arrived and closes the socket after each speech stream. This delays synthesis even when tokenized sentences are already available and repeats connection setup on later replies.

Add opt-in flushSentences and reuseWebsocket options. The first synthesizes available tokenizer sentences sequentially; the second reuses a fully drained connection. Existing HTTP and WebSocket behavior remains unchanged unless enabled.

Changes Made

  • Serialize each sentence's text/flush/done batch, preserving PCM, rebasing synthesis-local timestamps, and recording actual provider context IDs. Tokenizer buffering remains under the caller's control.
  • Honor explicit SDK stream.flush() boundaries with separate final frames and metrics, including already-queued segments and whitespace-only input. Retain at most one real PCM sample for the final frame so short audio is delivered promptly.
  • Exclusively lease sockets to streams, keep at most one completed idle connection for 30 seconds, discard interrupted/failed connections, invalidate reuse after connection-option changes, and release resources through TTS.close().
  • Add deterministic WebSocket regressions, document the options, regenerate the API report, and run Rime tests in CI. The regenerated report also removes a stale Arcana union member already absent from the current model source; this PR does not change model selection.

Pre-Review Checklist

  • Build passes: Build, lint, typecheck, formatting, throws checks, and the affected/core tests pass locally.
  • AI-generated code reviewed: Independent standards and behavior reviews completed; identified segment metrics and provider trace-correlation issues fixed.
  • Changes explained: Public options and lifecycle behavior documented.
  • Scope appropriate: Rime plugin implementation, tests, documentation/API report, and its CI coverage.
  • Video demo: Not applicable to this transport change; automated audio-stream assertions and direct provider validation are described below.

Testing

  • Automated tests added/updated: 19 WebSocket tests cover early PCM through the real default ttsNode, baseline behavior, serialized batches, exact PCM conservation, timestamps, explicit and queued SDK segments, metrics, context tracing, reuse/concurrency, cancellation, option changes, timeout, idle expiry, and shutdown.
  • All tests pass: pnpm test agents plugins/rime --maxWorkers 2 --silent — 153 files passed; 2,497 tests passed and 6 skipped.
  • restaurant_agent.ts / realtime_agent.ts: Not run; this change is isolated to the Rime plugin and its opt-in WebSocket path.

Local checks used Node 24 and the repository-pinned pnpm 11.13.1: full monorepo pnpm build, pnpm lint, pnpm typecheck, pnpm format:check, pnpm throws:check, and Rime api:check.

An earlier run alongside concurrent build/lint work had two timing failures in unchanged core tests. Both affected files passed on targeted rerun, and the complete final run above passed with two test workers.

The regression fixture was also run against unchanged upstream source: early audio, socket reuse, and default ttsNode early delivery failed before the change; the compatibility test passed. The explicit/queued SDK segment metrics failures were reproduced before their fixes.

Additional Notes

The underlying transport change was exercised against the real Rime Coda /ws3 endpoint in ten synthetic-text scenarios, including English/Spanish, cancellation/recovery, connection reuse, and shutdown. No credentials, patient data, or private application code are included in this PR.

With a sentence-ready tokenizer and a deliberately paced two-second text-input schedule, English first PCM arrived at 2.27–2.36 seconds on the original path versus 0.31–0.65 seconds on the optimized path. The second optimized reply opened no new connection. These controlled measurements demonstrate removal of client buffering; they are not a production latency distribution or a claim about the default tokenizer's latency.

Rime can coalesce overlapping flushes, so this implementation waits for each matching done before submitting the next batch. See the segmentation contract and Coda JSON protocol.

Live word timestamps sometimes exceeded returned PCM duration on both original and optimized paths. This PR preserves/rebases provider timing; it does not attempt to correct provider alignment accuracy. Sentence prosody and full SIP-call behavior still require listening/call validation.


Note to reviewers: Please ensure the pre-review checklist is completed before starting your review.

@chasef07
chasef07 requested a review from a team as a code owner September 5, 2026 13:02
@changeset-bot

changeset-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 6c6c78c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-05T13:05:34.740698Z 6c6c78c PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Devin Review

Comment thread plugins/rime/src/tts.ts
Comment on lines +680 to +684
if (data.type === 'error') {
// Provider error text can echo input or credentials. Keep it out of logs.
fail('Rime WebSocket synthesis failed');
} else if (activeContext && data.contextId === activeContext) {
void messages.write(data).catch(() => {});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Stale errors abort later speech

When a reused socket delivers an old request's error, onMessage fails the current speech before checking its context. Late errors can therefore discard unrelated speech on the same connection.

Suggested change
if (data.type === 'error') {
// Provider error text can echo input or credentials. Keep it out of logs.
fail('Rime WebSocket synthesis failed');
} else if (activeContext && data.contextId === activeContext) {
void messages.write(data).catch(() => {});
if (data.type === 'error') {
// Provider error text can echo input or credentials. Keep it out of logs.
if (activeContext && (!data.contextId || data.contextId === activeContext)) {
fail('Rime WebSocket synthesis failed');
}
} else if (activeContext && data.contextId === activeContext) {
void messages.write(data).catch(() => {});
}
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@chasef07

chasef07 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

@naszzz can you look and test this aap and if you want it to be default?

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.

1 participant