NousResearch/hermes-agent

Edge TTS audio conversion scoped to Telegram only

Cluster 26404. Data as of

Nothing open on GitHub. Fix merged in #28512 on 19 May 2026. Check it covers your case.

The short answer

0open issues
0open PRs
4items grouped
Known?
Yes. 4 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #28512. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this unresolved. That is separate from the fix event.
Still open
Nothing open on GitHub.

A bug was identified where Edge TTS audio was being unnecessarily converted from MP3 to OGG even outside of Telegram voice delivery contexts, breaking local CLI playback on macOS. Fixes aim to restrict the OGG conversion to only when Telegram voice delivery is the target.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #28512 fix(tts): preserve native audio outside Telegram voice delivery

    merged to main

    files: scripts/release.py, tests/tools/test_tts_opus_routing.py, tools/tts_tool.py

    Show the diff
    • scripts/release.py
      @@ -174,6 +174,7 @@
           "[redacted:email]": "Zyrixtrex",  # PR #26754 salvage (avoid duplicate text after auto-TTS)
           "[email protected]": "nftpoetrist",  # PR #25856 salvage (escape slash-confirm preview)
           "[email protected]": "samahn0601",  # PR #27887 salvage (retry wrapped connect timeouts)
      +    "[redacted:email]": "aqilaziz",  # PR #26406 salvage (preserve native audio outside Telegram)
           "[email protected]": "eliteworkstation94-ai",  # PR #28157 salvage (group reply session splits)
           "[redacted:email]": "hllqkb",
           "[email protected]": "Bongulielmi",
    • tests/tools/test_tts_opus_routing.py
      @@ -0,0 +1,70 @@
      +import json
      +from pathlib import Path
      +from unittest.mock import Mock
      +
      +import pytest
      +
      +from gateway.session_context import _UNSET, _VAR_MAP
      +from tools import tts_tool
      +
      +
      +def _reset_session_context() -> None:
      +    for var in _VAR_MAP.values():
      +        var.set(_UNSET)
      +
      +
      [redacted:email](autouse=True)
      +def _clean_session_platform(monkeypatch):
      +    _reset_session_context()
      +    monkeypatch.delenv("HERMES_SESSION_PLATFORM", raising=False)
      +    yield
      +    _reset_session_context()
      +
      +
      +async def _write_edge_output(_text: str, output_path: str, _tts_config: dict) -> str:
      +    Path(output_path).write_bytes(b"mp3")
      +    return output_path
      +
      +
      +def test_edge_cli_preserves_native_mp3(tmp_path, monkeypatch):
      +    out = tmp_path / "speech.mp3"
      +    convert = Mock()
      +
      +    monkeypatch.setattr(tts_tool, "_load_tts_config", lambda: {"provider": "edge"})
      +    monkeypatch.setattr(tts_tool, "_import_edge_tts", lambda: object())
      +    monkeypatch.setattr(tts_tool, "_generate_edge_tts", _write_edge_output)
      +    monkeypatch.setattr(tts_tool, "_convert_to_opus", convert)
      +
      +    result = json.loads(tts_tool.text_to_speech_tool("hello", output_path=str(out)))
      +
      +    assert result["success"] is True
      +    assert result["file_path"] == str(out)
      +    assert result["voice_compatible"] is False
      +    assert result["media_tag"] == f"MEDIA:{out}"
      +    convert.assert_not_called()
      +
      +
      +def test_edge_telegram_converts_to_opus_voice(tmp_path, monkeypatch):
      +    out = tmp_path / "speech.mp3"
      +    opus = tmp_path / "speech.ogg"
      +
      +    def fake_convert(path: str) -> str:
      +        assert path == str(out)
      +        opus.write_bytes(b"ogg")
      +        return str(opus)
      +
      +    convert = Mock(side_effect=fake_convert)
      +
      +    monkeypatch.setenv("HERMES_SESSION_PLATFORM", "telegram")
      +    monkeypatch.setattr(tts_tool, "_load_tts_config", lambda: {"provider": "edge"})
      +    monkeypatch.setattr(tts_tool, "_import_edge_tts", lambda: object())
      +    monkeypatch.setattr(tts_tool, "_generate_edge_tts", _write_edge_output)
      +    monkeypatch.setattr(tts_tool, "_convert_to_opus", convert)
      +
      +    result = json.loads(tts_tool.text_to_speech_tool("hello", output_path=str(out)))
      +
      +    assert result["success"] is True
      +    assert result["file_path"] == str(opus)
      +    assert result["voice_compatible"] is True
      +    assert result["media_tag"] == f"[[audio_as_voice]]\nMEDIA:{opus}"
      +    convert.assert_called_once_with(str(out))
    • tools/tts_tool.py
      @@ -1830,8 +1830,10 @@ def text_to_speech_tool(
                       "error": f"TTS generation produced no output (provider: {provider})"
                   }, ensure_ascii=False)
       
      -        # Try Opus conversion for Telegram compatibility
      -        # Edge TTS outputs MP3, NeuTTS/KittenTTS output WAV — all need ffmpeg conversion
      +        # Try Opus conversion for Telegram compatibility.
      +        # Edge TTS outputs MP3, NeuTTS/KittenTTS output WAV. Keep those native
      +        # formats for local/CLI playback and only convert when the current
      +        # platform actually needs Opus voice delivery.
               voice_compatible = False
               if command_provider_config is not None:
                   # Command providers are documents by default. Voice-bubble
      @@ -1843,13 +1845,17 @@ def text_to_speech_tool(
                           if opus_path:
                               file_str = opus_path
                       voice_compatible = file_str.endswith(".ogg")
      -        elif provider in {"edge", "neutts", "minimax", "xai", "kittentts", "piper"} and not file_str.endswith(".ogg"):
      +        elif (
      +            want_opus
      +            and provider in {"edge", "neutts", "minimax", "xai", "kittentts", "piper"}
      +            and not file_str.endswith(".ogg")
      +        ):
                   opus_path = _convert_to_opus(file_str)
                   if opus_path:
                       file_str = opus_path
                       voice_compatible = True
               elif provider in {"elevenlabs", "openai", "mistral", "gemini"}:
      -            voice_compatible = file_str.endswith(".ogg")
      +            voice_compatible = want_opus and file_str.endswith(".ogg")
       
               file_size = os.path.getsize(file_str)
               logger.info("TTS audio saved: %s (%s bytes, provider: %s)", file_str, f"{file_size:,}", provider)

2 PRs closed without merging

From the close comments: duplicate 1 · merged via another change 1

  • #26406 fix(tts): preserve native audio outside Telegram voice delivery · merged via another change → #28512
  • #26748 fix(tts): gate Edge TTS OGG conversion on Telegram delivery (#26404) · duplicate → #26406, #26404
Closed issues · 1
  • Closed#26404[Bug]: Unnecessary MP3→OGG conversion in Edge TTS breaks local CLI playback on macOS
How this cluster was grouped
  • Link evidence (structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
  • Pairwise link density 0.50: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Merged PRs
#28512
Closed issues
1
Attempts
2 PRs closed without merging
Fix link checked
19 May 2026

For your agent

The same facts, typed.