Skip to content

meta: add Muse Voice Transcribe STT plugin - #7096

Open
CHVSAnirudh wants to merge 4 commits into
livekit:mainfrom
CHVSAnirudh:feat/meta-muse-stt-plugin
Open

meta: add Muse Voice Transcribe STT plugin#7096
CHVSAnirudh wants to merge 4 commits into
livekit:mainfrom
CHVSAnirudh:feat/meta-muse-stt-plugin

Conversation

@CHVSAnirudh

Copy link
Copy Markdown

Adds livekit-plugins-meta, a streaming speech-to-text plugin for Meta's Muse Voice Transcribe (muse-voice-transcribe-1.0) over the realtime ASR WebSocket at wss://api.meta.ai/v1/asr/realtime.

The plugin authenticates in the first frame rather than a header (as the API requires), streams 80 ms chunks of mono s16le PCM as binary frames, and rotates the connection before Muse's 60-minute session limit. It supports ENDPOINTING mode for model-detected turn boundaries, DIARIZATION for speaker labels, keyword biasing (wired to framework-managed keyterms) and language biasing.

One ordering detail is worth calling out: Muse emits speechEnd before speechComplete, but AudioRecognition begins end-of-turn detection as soon as it sees END_OF_SPEECH, using the transcript accumulated so far. Forwarding the frames in wire order would judge each turn before its final text arrived, so the plugin holds the boundary and releases it after the FINAL_TRANSCRIPT.

Capabilities: streaming, interim results, keyterms, and diarization in DIARIZATION mode. Muse timestamps turns rather than words, so aligned_transcript is left False.

Adds livekit-plugins-meta, a streaming speech-to-text plugin for Meta's
Muse Voice Transcribe (muse-voice-transcribe-1.0) over the realtime ASR
WebSocket at wss://api.meta.ai/v1/asr/realtime.

The plugin authenticates in the first frame rather than a header (as the
API requires), streams 80 ms chunks of mono s16le PCM as binary frames,
and rotates the connection before Muse's 60-minute session limit. It
supports ENDPOINTING mode for model-detected turn boundaries, DIARIZATION
for speaker labels, keyword biasing (wired to framework-managed keyterms)
and language biasing.

One ordering detail is worth calling out: Muse emits `speechEnd` before
`speechComplete`, but AudioRecognition begins end-of-turn detection as
soon as it sees END_OF_SPEECH, using the transcript accumulated so far.
Forwarding the frames in wire order would judge each turn before its
final text arrived, so the plugin holds the boundary and releases it
after the FINAL_TRANSCRIPT.

Capabilities: streaming, interim results, keyterms, and diarization in
DIARIZATION mode. Muse timestamps turns rather than words, so
aligned_transcript is left False.
@CHVSAnirudh
CHVSAnirudh requested a review from a team as a code owner September 2, 2026 13:25
@CLAassistant

CLAassistant commented Sep 2, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 11 potential issues.

2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/stt.py
Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/stt.py Outdated
Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/stt.py
Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/stt.py
Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/stt.py
Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/stt.py
Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/stt.py
Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/models.py
Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/stt.py
Comment thread livekit-plugins/livekit-plugins-meta/livekit/plugins/meta/stt.py
Addresses review feedback on the initial plugin commit.

- STT.aclose() closed nothing: the inherited implementation is a no-op, so
  every stream's task and WebSocket outlived the recognizer. It now closes
  the streams it handed out, and one failing closure no longer strands the
  rest. The HTTP session is left alone, since it is either the caller's or
  the job-scoped one from http_context.

- update_options(language=...) never reached a running stream, because
  _apply_options preserved each stream's language unconditionally. Streams
  now record whether stream(language=...) gave them an explicit override;
  only those keep their own language, the rest follow the recognizer.

- Reopening the socket mid-utterance loses the turn, since its final never
  arrives. Reconnects requested during a turn are now held until
  END_OF_SPEECH releases them. The 55-minute rotation uses the same path
  with a hard deadline, because Muse drops the session at 60 minutes
  whether or not the turn has ended.

- update_options(mode=...) left capabilities.diarization at its constructor
  value, so adapters could trust speaker labels that were no longer coming
  (or reject ones that were).

- The audio-duration collector was never flushed when input ended, dropping
  up to one collection period of audio from STT usage metrics.
devin-ai-integration[bot]

This comment was marked as resolved.

Class, stream(), model and provider docstrings for pdoc3; the constructor
already carried the parameter documentation.
Every plugin here names its credential <PROVIDER>_API_KEY; MODEL_API_KEY
was Meta's SDK convention and reads as generic in a multi-provider agent.
The missing-key error now follows the assemblyai/baseten wording.
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.

2 participants