Skip to content

fix: enable Opus voice output for Feishu and Lark platforms - #51819

Closed
leowangzi wants to merge 1 commit into
NousResearch:mainfrom
leowangzi:fix/feishu-lark-tts-opus-voice
Closed

fix: enable Opus voice output for Feishu and Lark platforms#51819
leowangzi wants to merge 1 commit into
NousResearch:mainfrom
leowangzi:fix/feishu-lark-tts-opus-voice

Conversation

@leowangzi

Copy link
Copy Markdown

Problem

TTS voice messages on Feishu/Lark are sent as file attachments instead of playable voice bubbles.

Root Cause

In tools/tts_tool.py, want_opus (which triggers ffmpeg conversion from MP3 to Opus and marks the output as voice_compatible) only checked for platform == "telegram". Feishu and Lark were excluded.

Meanwhile, the Feishu adapter only uploads .ogg/.opus files with the native "audio" message type (_FEISHU_OPUS_UPLOAD_EXTENSIONS = {".ogg", ".opus"}). MP3 files fall through to generic file attachment delivery.

Fix

One-line change: extend the want_opus condition to include feishu and lark:

- want_opus = (platform == "telegram")
+ want_opus = (platform in {"telegram", "feishu", "lark"})

This triggers:

  1. ffmpeg MP3→Opus conversion for Edge TTS on Feishu/Lark
  2. voice_compatible = True[[audio_as_voice]] marker prepended
  3. Opus file recognized by Feishu adapter → sent as native audio message

Testing

Tested on Feishu with Edge TTS: voice messages now arrive as playable audio bubbles instead of file attachments.

Edge TTS generates MP3, which requires ffmpeg conversion to Opus
to be sent as a native voice message on Feishu/Lark. Previously only
Telegram received this conversion; this change adds feishu and lark
so TTS audio is delivered as playable voice bubbles instead of file
attachments.
@alt-glitch alt-glitch added type/bug Something isn't working tool/tts Text-to-speech and transcription platform/feishu Feishu / Lark adapter P2 Medium — degraded but workaround exists labels Jun 24, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: competing fix cluster for #45557. The earliest want_opus PRs are now closed (#45555, #45637, #32258); still-open alternatives are #45712 (Feishu-only want_opus, same one-line approach) and #37804 (combined gateway-side approach with duration metadata). This PR is the broadest of the live options — it extends the guard to both feishu and lark. Flagging for a maintainer to pick one.

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

Thanks for narrowing the conversion gate to the Feishu/Lark delivery path. The current-main premise is valid: tools/tts_tool.py:2202 still restricts want_opus to Telegram, while the Feishu plugin routes .ogg/.opus as native audio at plugins/platforms/feishu/adapter.py:5025-5026.

Problems

  • Please add a regression test for HERMES_SESSION_PLATFORM="feishu". tests/tools/test_tts_opus_routing.py:47-70 currently exercises only Telegram, so this new routing branch is unprotected.
  • lark is not a current session-platform value: the Feishu/Lark adapter is constructed as Platform.FEISHU (plugins/platforms/feishu/adapter.py:1442) and the gateway exports that value (gateway/run.py:15000-15002). The feishu case covers Lark-domain deployments.
  • This remains conversion-dependent: _convert_to_opus() returns None when ffmpeg is absent or fails (tools/tts_tool.py:899-933), after which non-Opus Feishu audio falls back to file routing (plugins/platforms/feishu/adapter.py:5034-5037).

Suggested changes

  • Add the Feishu routing regression and limit the condition to the reachable platform identity.
  • State the ffmpeg-success condition, or separately validate a fallback before promising native bubbles without it.

Automated hermes-sweeper review.

Comment thread tools/tts_tool.py
@@ -2177,7 +2177,7 @@ def text_to_speech_tool(
# and needs ffmpeg for conversion.

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.

Please add a Feishu regression in tests/tools/test_tts_opus_routing.py. The current test covers only Telegram; exercise this new branch with HERMES_SESSION_PLATFORM="feishu" and assert .ogg conversion plus the voice directive.

Comment thread tools/tts_tool.py
@@ -2177,7 +2177,7 @@ def text_to_speech_tool(
# and needs ffmpeg for conversion.

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.

lark is not emitted by the current adapter: Feishu/Lark constructs Platform.FEISHU, and the gateway exports its value as feishu. The feishu case already covers Lark-domain deployments; retaining an unreachable alias makes the routing contract misleading.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
@teknium1

Copy link
Copy Markdown
Contributor

The root cause here (gateway auto-TTS choosing MP3 vs Ogg/Opus via the cleared HERMES_SESSION_PLATFORM contextvar, so opus platforms got audio attachments instead of native voice bubbles) was fixed class-wide in #73508: platform-awareness now comes from the caller via build_auto_tts_output_path(platform) keyed off OPUS_VOICE_PLATFORMS (based on @giladbau's #62040), with the central container repair guaranteeing real Ogg/Opus bytes.

(Landed via #73508, merge f440a44753.) Closing.

@teknium1 teknium1 closed this Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Medium — degraded but workaround exists platform/feishu Feishu / Lark adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages tool/tts Text-to-speech and transcription type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants