Skip to content

fix(tts): filter emoji characters from text-to-speech input - #18598

Closed
Jasonlib wants to merge 1 commit into
NousResearch:mainfrom
Jasonlib:feat/tts-emoji-strip
Closed

fix(tts): filter emoji characters from text-to-speech input#18598
Jasonlib wants to merge 1 commit into
NousResearch:mainfrom
Jasonlib:feat/tts-emoji-strip

Conversation

@Jasonlib

@Jasonlib Jasonlib commented May 2, 2026

Copy link
Copy Markdown

Summary

Add emoji regex filter to all TTS text preprocessing paths to prevent voice engines from attempting to pronounce emoji characters.

Problem

When users send messages with emojis (😊, 👍, etc.), the text-to-speech engines (Edge TTS, ElevenLabs, MiniMax, etc.) attempt to pronounce them as literal characters (e.g., "smiling face with smiling eyes", "thumbs up"). This degrades voice output quality and creates awkward listening experiences.

Solution

Add an emoji regex filter to all TTS text preprocessing functions:

  • tools/tts_tool.py: _strip_markdown_for_tts()
  • cli.py: _voice_speak_response()
  • hermes_cli/voice.py: speak_text()

The regex pattern covers the full Unicode emoji range:

  • Emoticons (U+1F600-U+1F64F)
  • Symbols & Pictographs (U+1F300-U+1F5FF)
  • Transport & Map (U+1F680-U+1F6FF)
  • Flags (U+1F1E0-U+1F1FF)
  • And other emoji blocks

Testing

Verified locally:

  1. Send message with emojis (e.g., "你好😊这个功能很棒👍")
  2. TTS reads clean text without emoji pronunciations
  3. All three TTS paths (CLI, TUI, gateway) work correctly

Files Changed

  • cli.py: +2 lines
  • hermes_cli/voice.py: +2 lines
  • tools/tts_tool.py: +13 lines

Total: 17 insertions, 0 deletions

Add emoji regex filter to all TTS text preprocessing paths to prevent
voice engines from attempting to pronounce emoji characters.

Affected files:
- tools/tts_tool.py: _strip_markdown_for_tts()
- cli.py: _voice_speak_response()
- hermes_cli/voice.py: speak_text()

Fixes issue where emojis would be read as literal characters by TTS,
degrading voice output quality.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have tool/tts Text-to-speech and transcription duplicate This issue or pull request already exists labels May 2, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #13311 — Duplicate of #13311 — same approach: regex strip emoji from TTS input. Also related to more comprehensive #8205 (text preprocessing with localized emoji names).

@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 targeting a real TTS cleanup gap.

Problems

  • The added tools/tts_tool.py filter only changes _strip_markdown_for_tts(). The agent-callable text_to_speech_tool() still forwards raw text to providers, including ElevenLabs at tools/tts_tool.py:2284, OpenAI at tools/tts_tool.py:2295, and Edge at tools/tts_tool.py:2371. The PR therefore does not cover a live TTS entry point.
  • The PR changes no test files. Current sanitizer coverage at tests/tools/test_voice_cli_integration.py:48-123 covers Markdown stripping only.

Suggested changes

  • Centralize emoji normalization and invoke it at the text_to_speech_tool() boundary, then reuse it from the gateway/streaming helper and CLI/TUI voice paths.
  • Add focused direct-tool, streaming, and emoji-sequence regression tests.

Automated hermes-sweeper review.

Comment thread tools/tts_tool.py
text = _MD_HR.sub('', text)
text = _MD_EXCESS_NL.sub('\n\n', text)
# Strip emojis so TTS doesn't read out emoji descriptions
text = re.sub(r'[\U0001F600-\U0001F64F' # emoticons

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.

This helper is not called by text_to_speech_tool(): current main dispatches its raw text argument directly to every provider. Please extract a shared normalizer and invoke it at the tool boundary as well, so agent-issued text_to_speech calls receive the same cleanup.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 12, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Emoji stripping is now covered on every TTS path by the shared prepare_spoken_text cleaner merged in #73513 — main already had _EMOJI on the streaming path and the residual tool-path gap is closed there. Thanks!

(Landed via #73513, merge 4aac89b429.) Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades 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