← Back to PRs

#12700: fix(tts): deliver WhatsApp voice as opus bubble instead of MP3 (#12672)

by lailoo open 2026-02-09 14:13 View on GitHub →
size: XS trusted-contributor
## Summary Fixes #12672 ## Problem `resolveOutputFormat()` in `src/tts/tts.ts` only checked for `"telegram"` when deciding to use opus format, so WhatsApp received MP3 files instead of opus voice bubbles. Similarly, the `shouldVoice` flag only checked for `"telegram"`, so WhatsApp audio was never sent as a voice message — it appeared as a downloadable file attachment. ### Root cause Two conditions in `src/tts/tts.ts` were missing `"whatsapp"`: 1. **`resolveOutputFormat`** (line 477): only returned `TELEGRAM_OUTPUT` (opus) for `"telegram"` 2. **`shouldVoice`** (line 1546): only set `audioAsVoice=true` for `"telegram"` ## Fix Added `|| channelId === "whatsapp"` to both conditions so WhatsApp gets the same opus voice treatment as Telegram. ### Before ```typescript // resolveOutputFormat if (channelId === "telegram") { return TELEGRAM_OUTPUT; } // shouldVoice const shouldVoice = channelId === "telegram" && result.voiceCompatible === true; ``` ### After ```typescript // resolveOutputFormat if (channelId === "telegram" || channelId === "whatsapp") { return TELEGRAM_OUTPUT; } // shouldVoice const shouldVoice = (channelId === "telegram" || channelId === "whatsapp") && result.voiceCompatible === true; ``` ## Reproduction & Verification ### Before fix (main branch) — Bug reproduced: ``` === TTS WhatsApp opus format check === 1. Telegram output format: openai=opus, voiceCompatible=true ✅ PASS: Telegram gets opus + voiceCompatible 2. WhatsApp output format: openai=mp3, voiceCompatible=false ❌ FAIL — BUG CONFIRMED: WhatsApp should get opus + voiceCompatible but gets mp3 3. shouldVoice for telegram: true ✅ PASS: Telegram shouldVoice=true shouldVoice for whatsapp: false ❌ FAIL — BUG CONFIRMED: WhatsApp shouldVoice is false (should be true) === Summary === ❌ BUG CONFIRMED: WhatsApp TTS gets MP3 format and audioAsVoice=false. Users receive a downloadable MP3 file instead of an inline voice bubble. ``` ### After fix — All verified: ``` === TTS WhatsApp opus format verification === ✅ PASS: Telegram → opus ✅ PASS: Telegram → voiceCompatible ✅ PASS: Telegram → .opus extension ✅ PASS: WhatsApp → opus ✅ PASS: WhatsApp → voiceCompatible ✅ PASS: WhatsApp → .opus extension ✅ PASS: Discord → mp3 ✅ PASS: Discord → not voiceCompatible ✅ PASS: Slack → mp3 ✅ PASS: null → mp3 ✅ PASS: undefined → mp3 ✅ PASS: shouldVoice(telegram, true) = true ✅ PASS: shouldVoice(whatsapp, true) = true ✅ PASS: shouldVoice(discord, true) = false ✅ PASS: shouldVoice(whatsapp, false) = false === Summary: ✅ ALL PASSED === ``` ## Effect on User Experience **Before fix:** WhatsApp users receiving TTS audio get a downloadable MP3 file attachment that requires manual tap-to-download and playback. The audio does not appear as an inline voice bubble. **After fix:** WhatsApp users receive TTS audio as an inline opus voice bubble (same as Telegram), playable directly in the chat with a single tap. ## Testing - ✅ 34 tests pass (including new WhatsApp opus regression test) - ✅ Lint passes (oxlint: 0 warnings, 0 errors) <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This change updates the TTS channel handling so WhatsApp matches Telegram’s “voice note” behavior: `resolveOutputFormat()` now returns the Opus-oriented `TELEGRAM_OUTPUT` for `channelId === "whatsapp"`, and `maybeApplyTtsToPayload()` now sets `audioAsVoice` for WhatsApp when the generated audio is marked `voiceCompatible`. A targeted regression test was added to ensure WhatsApp resolves to Opus output, and the changelog includes an entry documenting the fix for #12672. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - The change is narrowly scoped: it extends an existing Telegram Opus/voice-note path to WhatsApp, adds a regression test for the new behavior, and updates the changelog. No other channel behavior is altered, and the implementation reuses existing constants and code paths. - No files require special attention <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs