initial: Piper TTS default plugin
Runtime monkey-patch that changes tools.tts_tool.DEFAULT_PROVIDER from 'edge' to 'piper' at plugin load time. Zero fork needed. - plugin.yaml with requires_pip: piper-tts - __init__.py with _apply_piper_patch() + on_session_start hook - README with installation and safety notes
This commit is contained in:
58
README.md
58
README.md
@@ -1,3 +1,57 @@
|
|||||||
# hermes-piper-plugin
|
# Hermes Piper Plugin
|
||||||
|
|
||||||
Hermes TTS plugin — makes Piper the default TTS provider instead of Edge. Runtime monkey-patch, zero fork needed.
|
Makes Piper TTS the default provider instead of Microsoft Edge TTS.
|
||||||
|
|
||||||
|
**Zero modifications to the Hermes repo.** No fork required. The plugin
|
||||||
|
monkey-patches `tools.tts_tool.DEFAULT_PROVIDER` at plugin load time.
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
- Piper is local, free, CPU-only — no API key, no cloud dependency
|
||||||
|
- Edge TTS requires internet access and ffmpeg for Telegram voice bubbles
|
||||||
|
- This eliminates the need to maintain a fork just to change the default
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
```python
|
||||||
|
# At plugin load time, this single line runs:
|
||||||
|
tools.tts_tool.DEFAULT_PROVIDER = "piper"
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it. `DEFAULT_PROVIDER` is read at call time, so changing it after
|
||||||
|
import is safe. The plugin also logs the effective default at session start.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Ensure piper-tts is installed
|
||||||
|
pip install piper-tts
|
||||||
|
|
||||||
|
# 2. Install the plugin from Gitea
|
||||||
|
hermes plugins install ssh://git@code.lazyworkhorse.net:2222/Hermes/hermes-piper-plugin.git
|
||||||
|
|
||||||
|
# 3. Restart gateways to load the plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
## Config
|
||||||
|
|
||||||
|
The plugin changes the **default** provider. You can still override per
|
||||||
|
session by setting `tts.provider` in `~/.hermes/config.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
tts:
|
||||||
|
provider: elevenlabs # override per-session
|
||||||
|
voice: "Adam" # ElevenLabs voice
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requires
|
||||||
|
|
||||||
|
- `piper-tts` Python package (installed via pip)
|
||||||
|
- Piper voice models (downloaded automatically on first use, ~50MB each)
|
||||||
|
|
||||||
|
## Safety
|
||||||
|
|
||||||
|
- If `piper-tts` is not installed, the TTS tool returns an error asking
|
||||||
|
the user to install it — no silent fallback to Edge
|
||||||
|
- Removing the plugin restores the original Hermes default (Edge)
|
||||||
|
- No data loss risk. No changes to any file in the Hermes repo.
|
||||||
|
|||||||
59
__init__.py
Normal file
59
__init__.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
"""
|
||||||
|
hermes-piper-plugin (piper)
|
||||||
|
|
||||||
|
Overrides Hermes' default TTS provider from Edge to Piper at plugin load
|
||||||
|
time. Uses runtime monkey-patching — zero modifications to the Hermes repo.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
_PATCHED = False
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_piper_patch() -> None:
|
||||||
|
"""Replace Edge default with Piper in TTS tool's provider selection.
|
||||||
|
|
||||||
|
Python module-level constants are mutable — ``DEFAULT_PROVIDER`` is a
|
||||||
|
string that ``_get_provider()`` reads at call time (not import time).
|
||||||
|
Changing it after import is safe and immediately effective.
|
||||||
|
"""
|
||||||
|
global _PATCHED
|
||||||
|
if _PATCHED:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
import tools.tts_tool
|
||||||
|
|
||||||
|
old_default = getattr(tools.tts_tool, "DEFAULT_PROVIDER", "edge")
|
||||||
|
tools.tts_tool.DEFAULT_PROVIDER = "piper"
|
||||||
|
|
||||||
|
logger.info("piper-plugin: DEFAULT_PROVIDER changed from '%s' → 'piper'", old_default)
|
||||||
|
_PATCHED = True
|
||||||
|
except ImportError:
|
||||||
|
logger.warning("piper-plugin: tools.tts_tool not importable — patch deferred")
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning("piper-plugin: failed to patch DEFAULT_PROVIDER: %s", exc)
|
||||||
|
|
||||||
|
|
||||||
|
def _on_session_start(**kw):
|
||||||
|
"""Log Piper default status at session start (idempotent)."""
|
||||||
|
if not _PATCHED:
|
||||||
|
_apply_piper_patch()
|
||||||
|
|
||||||
|
try:
|
||||||
|
import tools.tts_tool
|
||||||
|
current = getattr(tools.tts_tool, "DEFAULT_PROVIDER", "?")
|
||||||
|
logger.info("piper-plugin: TTS default provider = %s (patched=%s)", current, _PATCHED)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def register(ctx) -> None:
|
||||||
|
"""Register Piper default override."""
|
||||||
|
_apply_piper_patch()
|
||||||
|
ctx.register_hook("on_session_start", _on_session_start)
|
||||||
|
logger.info("piper-plugin: registered ✓ (TTS default → piper)")
|
||||||
11
plugin.yaml
Normal file
11
plugin.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
name: piper
|
||||||
|
version: 1.0.0
|
||||||
|
description: >
|
||||||
|
Makes Piper TTS the default provider instead of Edge. Zero fork needed —
|
||||||
|
uses runtime monkey-patching to set DEFAULT_PROVIDER = "piper" at plugin
|
||||||
|
load time. Survives Hermes upgrades without merge conflicts.
|
||||||
|
author: "@gortium"
|
||||||
|
hooks:
|
||||||
|
- on_session_start
|
||||||
|
requires_pip:
|
||||||
|
- piper-tts
|
||||||
Reference in New Issue
Block a user