# NousResearch/hermes-agent · Edge TTS audio conversion scoped to Telegram only

## Open now

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

## TL;DR

- 4 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 2 PR(s) closed without merging.
- A fix was merged to main in PR #28512. Verify it addresses your case.
- **Recommended:** read PR #28512 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `unresolved`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.50`: the share of member 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.

## Closed / duplicate issues

- #26404: \[Bug\]: Unnecessary MP3→OGG conversion in Edge TTS breaks local CLI playback on macOS

## Prior & competing PRs

- **#28512: fix(tts): preserve native audio outside Telegram voice delivery**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `scripts/release.py`, `tests/tools/test_tts_opus_routing.py`, `tools/tts_tool.py`
  - fix hunks:
  - `scripts/release.py`

    ```diff
    @@ -174,6 +174,7 @@
         "[redacted:email]": "Zyrixtrex",  # PR #26754 salvage (avoid duplicate text after auto-TTS)
         "264138787+nftpoetrist@users.noreply.github.com": "nftpoetrist",  # PR #25856 salvage (escape slash-confirm preview)
         "197455947+samahn0601@users.noreply.github.com": "samahn0601",  # PR #27887 salvage (retry wrapped connect timeouts)
    +    "[redacted:email]": "aqilaziz",  # PR #26406 salvage (preserve native audio outside Telegram)
         "282919977+eliteworkstation94-ai@users.noreply.github.com": "eliteworkstation94-ai",  # PR #28157 salvage (group reply session splits)
         "[redacted:email]": "hllqkb",
         "25840394+Bongulielmi@users.noreply.github.com": "Bongulielmi",
    ```
  - `tests/tools/test_tts_opus_routing.py`

    ```diff
    @@ -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`

    ```diff
    @@ -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
    ```

    ```diff
    @@ -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)
    ```
- **#26406: fix(tts): preserve native audio outside Telegram voice delivery**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#28512`
- **#26748: fix(tts): gate Edge TTS OGG conversion on Telegram delivery (#26404)**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#26406`, `#26404`

## Fix status

- Merged to main in PR #28512 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-05-19`.
