Section: Core Features · URL: https://hermesbible.com/docs/user-guide/features/tts
Hermes Agent 支援所有訊息平台的文字轉語音輸出和語音訊息轉錄。
TIP — Nous 訂閱者
如果你有付費的 Nous Portal 訂閱,OpenAI TTS 可透過 Tool Gateway 使用,無需另外取得 OpenAI API Key。新安裝可執行
hermes setup --portal登入並一次啟用所有 Gateway 工具;已安裝的使用者可透過hermes model或hermes tools選擇 Nous Subscription 來啟用 TTS。
文字轉語音
支援十個提供者,將文字轉換為語音:
| 提供者 | 品質 | 費用 | API Key |
|---|---|---|---|
| Edge TTS(預設) | 優良 | 免費 | 無需設定 |
| ElevenLabs | 卓越 | 付費 | ELEVENLABS_API_KEY |
| OpenAI TTS | 優良 | 付費 | VOICE_TOOLS_OPENAI_KEY |
| MiniMax TTS | 卓越 | 付費 | MINIMAX_API_KEY |
| Mistral (Voxtral TTS) | 卓越 | 付費 | MISTRAL_API_KEY |
| Google Gemini TTS | 卓越 | 免費額度 | GEMINI_API_KEY |
| xAI TTS | 卓越 | 付費 | XAI_API_KEY |
| NeuTTS | 優良 | 免費(本機) | 無需設定 |
| KittenTTS | 優良 | 免費(本機) | 無需設定 |
| Piper | 優良 | 免費(本機) | 無需設定 |
平台傳遞方式
| 平台 | 傳遞方式 | 格式 |
|---|---|---|
| Telegram | 語音氣泡(內建播放) | Opus .ogg |
| Discord | 語音氣泡(Opus/OGG),備選為檔案附件 | Opus/MP3 |
| 音訊檔案附件 | MP3 | |
| CLI | 儲存至 ~/.hermes/audio_cache/ | MP3 |
設定
# In ~/.hermes/config.yaml
tts:
provider: "edge" # "edge" | "elevenlabs" | "openai" | "minimax" | "mistral" | "gemini" | "xai" | "neutts" | "kittentts" | "piper"
speed: 1.0 # 全域速度倍率(各提供者的個別設定會覆蓋此值)
edge:
voice: "en-US-AriaNeural" # 322 種語音,74 種語言
speed: 1.0 # 轉換為速率百分比(+/-%)
elevenlabs:
voice_id: "pNInz6obpgDQGcFmaJgB" # Adam
model_id: "eleven_multilingual_v2"
openai:
model: "gpt-4o-mini-tts"
voice: "alloy" # alloy, echo, fable, onyx, nova, shimmer
base_url: "https://api.openai.com/v1" # 覆蓋為 OpenAI 相容的 TTS 端點
speed: 1.0 # 0.25 - 4.0
minimax:
model: "speech-2.8-hd" # speech-2.8-hd(預設), speech-2.8-turbo
voice_id: "English_Graceful_Lady" # 參見 https://platform.minimax.io/faq/system-voice-id
speed: 1 # 0.5 - 2.0
vol: 1 # 0 - 10
pitch: 0 # -12 - 12
mistral:
model: "voxtral-mini-tts-2603"
voice_id: "c69964a6-ab8b-4f8a-9465-ec0925096ec8" # Paul - Neutral(預設)
gemini:
model: "gemini-2.5-flash-preview-tts" # 或 gemini-3.1-flash-tts-preview
voice: "Kore" # 30 種預建語音:Zephyr, Puck, Kore, Enceladus, Gacrux 等
audio_tags: false # 啟用隱藏的 Gemini 3.1 TTS 音訊標籤插入
persona_prompt_file: "" # 可選的 Markdown/純文字檔案,描述 Gemini 語音方向
xai:
voice_id: "eve" # 或自訂語音 ID — 參見下方文件
language: "en" # ISO 639-1 語言代碼
sample_rate: 24000 # 22050 / 24000(預設) / 44100 / 48000
bit_rate: 128000 # MP3 位元率;僅在 codec=mp3 時生效
# base_url: "https://api.x.ai/v1" # 可透過 XAI_BASE_URL 環境變數覆蓋
neutts:
ref_audio: ''
ref_text: ''
model: neuphonic/neutts-air-q4-gguf
device: cpu
kittentts:
model: KittenML/kitten-tts-nano-0.8-int8 # 25MB int8;另有:kitten-tts-micro-0.8 (41MB), kitten-tts-mini-0.8 (80MB)
voice: Jasper # Jasper, Bella, Luna, Bruno, Rosie, Hugo, Kiki, Leo
speed: 1.0 # 0.5 - 2.0
clean_text: true # 展開數字、貨幣、單位
piper:
voice: en_US-lessac-medium # 語音名稱(自動下載)或 .onnx 檔案的絕對路徑
# voices_dir: '' # 預設:~/.hermes/cache/piper-voices/
# use_cuda: false # 需要 onnxruntime-gpu
# length_scale: 1.0 # 2.0 = 速度減半
# noise_scale: 0.667
# noise_w_scale: 0.8
# volume: 1.0 # 0.5 = 音量減半
# normalize_audio: true
速度控制:全域 tts.speed 值預設適用於所有提供者。每個提供者可透過自身的 speed 設定覆蓋此值(例如 tts.openai.speed: 1.5)。提供者專屬的速度設定優先於全域值。預設為 1.0(正常速度)。
Gemini 角色提示詞
Gemini TTS 支援自然語言的演出指導。設定 tts.gemini.persona_prompt_file 指向本機的 Markdown 或純文字檔案,描述語音的角色設定。檔案可包含 Gemini 風格的區段,如 AUDIO PROFILE、SCENE、DIRECTOR'S NOTES、SAMPLE CONTEXT 和 TRANSCRIPT。
如果檔案包含 {transcript} 或 {{ transcript }},Hermes 會將該佔位符替換為即時的 TTS 文字。否則,Hermes 會自動附加一個標記為 TRANSCRIPT 的區段。角色提示詞僅在本機使用,不會顯示在聊天回覆中。
tts:
provider: gemini
gemini:
voice: Algieba
persona_prompt_file: ~/.hermes/tts/butler-voice.md
Gemini 音訊標籤
Gemini 3.1 Flash TTS 支援自由格式的方括號音訊標籤,例如 [whispers]、[excitedly]、[very slow]、[laughs] 等表達性演出指示。啟用 tts.gemini.audio_tags 後,Hermes 會在 Gemini TTS 執行前進行隱藏的重寫處理。重寫僅將內聯標籤插入 TTS 腳本中;可見的聊天回覆保持不變。
tts:
provider: gemini
gemini:
model: gemini-3.1-flash-tts-preview
audio_tags: true
重寫使用 auxiliary.tts_audio_tags,預設為你的主要聊天模型。如果你想用更便宜或更快的模型處理標籤插入,可覆蓋此輔助任務。
輸入長度限制
每個提供者都有文件記載的單次請求字元上限。Hermes 會在呼叫提供者前截斷文字,確保請求不會因長度錯誤而失敗:
| 提供者 | 預設上限(字元) |
|---|---|
| Edge TTS | 5000 |
| OpenAI | 4096 |
| xAI | 15000 |
| MiniMax | 10000 |
| Mistral | 4000 |
| Google Gemini | 32000 |
| ElevenLabs | 依模型而異(見下表) |
| NeuTTS | 2000 |
| KittenTTS | 2000 |
| Piper | 5000 |
ElevenLabs 根據設定的 model_id 選擇上限:
model_id | 上限(字元) |
|---|---|
eleven_flash_v2_5 | 40000 |
eleven_flash_v2 | 30000 |
eleven_multilingual_v2(預設)、eleven_multilingual_v1、eleven_english_sts_v2、eleven_english_sts_v1 | 10000 |
eleven_v3、eleven_ttv_v3 | 5000 |
| 未知模型 | 回退至提供者預設值(10000) |
各提供者可自行覆蓋,在 TTS 設定的提供者區段下使用 max_text_length::
tts:
openai:
max_text_length: 8192 # 提高或降低提供者上限
僅接受正整數。零、負數、非數字或布林值會回退至提供者預設值,因此損壞的設定不會意外停用截斷功能。
Telegram 語音氣泡與 ffmpeg
Telegram 語音氣泡需要 Opus/OGG 音訊格式:
- OpenAI、ElevenLabs 和 Mistral 原生產生 Opus — 無需額外設定
- Edge TTS(預設)輸出 MP3,需要 ffmpeg 進行轉換:
- MiniMax TTS 輸出 MP3,需要 ffmpeg 進行轉換以產生 Telegram 語音氣泡
- Google Gemini TTS 輸出原始 PCM,使用 ffmpeg 直接編碼為 Opus 以產生 Telegram 語音氣泡
- xAI TTS 輸出 MP3,需要 ffmpeg 進行轉換以產生 Telegram 語音氣泡
- NeuTTS 輸出 WAV,需要 ffmpeg 進行轉換以產生 Telegram 語音氣泡
- KittenTTS 輸出 WAV,需要 ffmpeg 進行轉換以產生 Telegram 語音氣泡
- Piper 輸出 WAV,需要 ffmpeg 進行轉換以產生 Telegram 語音氣泡
# Ubuntu/Debian
sudo apt install ffmpeg
# macOS
brew install ffmpeg
# Fedora
sudo dnf install ffmpeg
沒有 ffmpeg 時,Edge TTS、MiniMax TTS、NeuTTS、KittenTTS 和 Piper 的音訊會作為一般音訊檔案傳送(可播放,但顯示為矩形播放器而非語音氣泡)。
TIP
如果你想使用語音氣泡但不想安裝 ffmpeg,請切換至 OpenAI、ElevenLabs 或 Mistral 提供者。
xAI 自訂語音(語音複製)
xAI 支援複製你的語音並用於 TTS。在 xAI Console 建立自訂語音,然後在設定中填入取得的 voice_id:
tts:
provider: xai
xai:
voice_id: "nlbqfwie" # 你的自訂語音 ID
詳見 xAI Custom Voices 文件 了解錄音方式、支援格式和限制。
Piper(本機,44 種語言)
Piper 是來自 Open Home Foundation(Home Assistant 維護者)的快速本機神經網路 TTS 引擎。完全在 CPU 上運作,支援 44 種語言的預訓練語音,無需 API Key。
透過 hermes tools 安裝 → Voice & TTS → Piper — Hermes 會為你執行 pip install piper-tts。或手動安裝:pip install piper-tts。
切換至 Piper:
tts:
provider: piper
piper:
voice: en_US-lessac-medium
首次對尚未在本機快取的語音進行 TTS 呼叫時,Hermes 會執行 python -m piper.download_voices <name> 並將模型(約 20-90MB,依品質等級而異)下載至 ~/.hermes/cache/piper-voices/。後續呼叫會重用已快取的模型。
選擇語音。 完整語音目錄涵蓋英語、西班牙語、法語、德語、義大利語、荷蘭語、葡萄牙語、俄語、波蘭語、土耳其語、中文、阿拉伯語、印地語等 — 每種語言都有 x_low / low / medium / high 品質等級。可於 rhasspy.github.io/piper-samples 試聽語音。
使用預先下載的語音。 將 tts.piper.voice 設為以 .onnx 結尾的絕對路徑:
tts:
piper:
voice: /path/to/my-custom-voice.onnx
進階參數(tts.piper.length_scale / noise_scale / noise_w_scale / volume / normalize_audio、use_cuda)與 Piper 的 SynthesisConfig 一一對應。在較舊版本的 piper-tts 中會被忽略。
自訂指令提供者
如果你需要的 TTS 引擎未被原生支援(VoxCPM、MLX-Kokoro、XTTS CLI、語音複製腳本,或任何提供 CLI 介面的工具),你可以將其設定為指令型提供者,無需編寫任何 Python。Hermes 會將輸入文字寫入臨時的 UTF-8 檔案,執行你的 shell 指令,然後讀取指令產生的音訊檔案。
在 tts.providers.<name> 下宣告一個或多個提供者,並透過 tts.provider: <name> 在它們之間切換 — 與切換內建的 edge 和 openai 方式相同。
tts:
provider: voxcpm # 在 tts.providers 下自訂名稱
providers:
voxcpm:
type: command
command: "voxcpm --ref ~/voice.wav --text-file {input_path} --out {output_path}"
output_format: mp3
timeout: 180
voice_compatible: true # 嘗試以 Telegram 語音氣泡傳遞
mlx-kokoro:
type: command
command: "python -m mlx_kokoro --in {input_path} --out {output_path} --voice {voice}"
voice: af_sky
output_format: wav
piper-custom: # 原生 Piper 也支援透過 tts.piper.voice 使用自訂 .onnx
type: command
command: "piper -m /path/to/custom.onnx -f {output_path} < {input_path}"
output_format: wav
範例:豆包(中文 seed-tts-2.0)
要透過字節跳動的 seed-tts-2.0 雙向串流 API 進行高品質中文 TTS,請安裝 doubao-speech PyPI 套件,並將其設定為指令提供者:
pip install doubao-speech
export VOLCENGINE_APP_ID="your-app-id"
export VOLCENGINE_ACCESS_TOKEN="your-access-token"
tts:
provider: doubao
providers:
doubao:
type: command
command: "doubao-speech say --text-file {input_path} --out {output_path}"
output_format: mp3
max_text_length: 1024
timeout: 30
認證資訊來自你的 shell 環境(VOLCENGINE_APP_ID / VOLCENGINE_ACCESS_TOKEN)或 ~/.doubao-speech/config.yaml。透過在指令中加入 --voice zh-female-warm(或 doubao-speech list-voices 中的其他別名)來選擇語音。doubao-speech 也內建串流 ASR — 參見下方 STT 區段了解 Hermes 整合方式。原始碼與完整文件:github.com/Hypnus-Yuan/doubao-speech。
佔位符
你的指令模板可引用以下佔位符。Hermes 在渲染時替換它們,並為周圍環境(裸字串/單引號/雙引號)進行 shell 引號處理,因此包含空格和其他 shell 特殊字元的路徑是安全的。
| 佔位符 | 意義 |
|---|---|
{input_path} | Hermes 寫入的臨時 UTF-8 文字檔案路徑 |
{text_path} | {input_path} 的別名 |
{output_path} | 指令必須寫入音訊的路徑 |
{format} | mp3 / wav / ogg / flac |
{voice} | tts.providers.<name>.voice,未設定時為空 |
{model} | tts.providers.<name>.model |
{speed} | 解析後的速度倍率(提供者或全域) |
使用 {{ 和 }} 表示字面量大括號。
選用鍵值
| 鍵值 | 預設值 | 意義 |
|---|---|---|
timeout | 120 | 秒數;到期時會終止整個行程樹(Unix 為 killpg,Windows 為 taskkill /T)。 |
output_format | mp3 | mp3 / wav / ogg / flac 之一。若 Hermes 自動選擇路徑,會根據輸出副檔名自動推斷。 |
voice_compatible | false | 設為 true 時,Hermes 會透過 ffmpeg 將 MP3/WAV 輸出轉換為 Opus/OGG,使 Telegram 顯示為語音氣泡。 |
max_text_length | 5000 | 渲染指令前會將輸入截斷至此長度。 |
voice / model | 空 | 僅作為佔位符值傳遞給指令。 |
行為說明
- 內建名稱永遠優先。
tts.providers.openai條目不會遮蔽原生 OpenAI 提供者,因此使用者設定不會悄悄替換內建提供者。 - 預設傳遞方式為檔案附件。 指令提供者在所有平台上都以一般音訊附件傳遞。可透過
voice_compatible: true為各提供者選擇啟用語音氣泡傳遞。 - 指令失錯會回報給代理。 非零結束碼、空輸出或逾時都會傳回錯誤,包含指令的 stderr/stdout,方便你從對話中除錯。
- 設定
command:時,type: command為預設值。 明確撰寫type: command是好習慣但非必要;有非空command字串的條目會被視為指令提供者。 {input_path}/{text_path}可互換使用。 在你的指令中使用可讀性更好的那個。
安全性
指令型提供者以你的使用者權限執行你設定的 shell 指令。Hermes 會處理佔位符值的引號並強制執行設定的逾時,但指令模板本身是受信任的本地輸入 — 請以與 PATH 中的 shell 腳本相同的方式對待它。
Python 外掛提供者
對於無法以單一 shell 指令表達的 TTS 引擎 — 沒有 CLI 的 Python SDK、串流引擎、語音列表 API、需要 OAuth 刷新認證的引擎 — 可透過 ctx.register_tts_provider() 註冊 Python 外掛。該外掛與自訂指令提供者登錄機制共存(不會取代它);選擇適合你引擎的介面即可。
何時使用何種方式
| 你的後端具備… | 使用 |
|---|---|
| 單一 CLI,從檔案/stdin 讀取文字並寫入音訊至檔案/stdout | 指令提供者(無需 Python) |
| 兩三個 CLI 透過 shell 管道串接 | 指令提供者 |
| 僅有 Python SDK,沒有 CLI | 外掛 |
| 想要分段傳遞的串流位元組(邊生成邊播報的語音氣泡) | 外掛(覆寫 stream()) |
被 hermes setup 使用的語音列表 API | 外掛(覆寫 list_voices()) |
| OAuth 刷新流程(非靜態 Bearer Token) | 外掛 |
內建提供者永遠優先,指令提供者優先於同名外掛 — 因此你可以安心地對任何非內建名稱註冊外掛,不必擔心遮蔽現有設定。
最小外掛範例
將以下檔案放入 ~/.hermes/plugins/my-tts/:
plugin.yaml:
name: my-tts
version: 0.1.0
description: "My custom Python TTS backend"
__init__.py:
from agent.tts_provider import TTSProvider
class MyTTSProvider(TTSProvider):
@property
def name(self) -> str:
return "my-tts" # tts.provider 對應的名稱
@property
def display_name(self) -> str:
return "My Custom TTS"
def is_available(self) -> bool:
# 當認證或相依套件缺失時回傳 False — 選擇器會略過此行,
# 但分派器在明確設定時仍會路由至此。
import os
return bool(os.environ.get("MY_TTS_API_KEY"))
def synthesize(self, text, output_path, *, voice=None, model=None,
speed=None, format="mp3", **extra) -> str:
# 將音訊位元組寫入 output_path,回傳路徑。
# 失敗時拋出例外 — 分派器會將例外轉換為標準錯誤格式。
import my_tts_sdk
client = my_tts_sdk.Client()
audio_bytes = client.synthesize(text=text, voice=voice or "default")
with open(output_path, "wb") as f:
f.write(audio_bytes)
return output_path
def register(ctx):
ctx.register_tts_provider(MyTTSProvider())
啟用它(hermes plugins enable my-tts),在 config.yaml 中將 tts.provider 指向它(tts.provider: my-tts),text_to_speech 工具就會透過你的外掛路由。
選用鉤子
在你的提供者類別上覆寫以下方法以獲得更豐富的整合:
list_voices()→ 在hermes tools中顯示的{id, display, language, gender, preview_url}字典列表。list_models()→{id, display, languages, max_text_length}字典列表。get_setup_schema()→ 回傳{name, badge, tag, env_vars: [{key, prompt, url}]}以驅動hermes tools/hermes setup中的選擇器列。沒有此方法時,外掛仍可運作,但選擇器中的列只顯示基本資訊。stream(text, *, voice, model, format, **extra)→ 產生音訊位元組的迭代器,用於串流傳遞(預設拋出NotImplementedError)。voice_compatible屬性 → 若你的輸出與 Opus 相容且 Gateway 應將其作為語音氣泡傳遞,設為True(預設False= 一般音訊附件)。
完整的 ABC 定義請參見 agent/tts_provider.py,包含完整文件字串。
語音訊息轉錄(STT)
在 Telegram、Discord、WhatsApp、Slack 或 Signal 上傳送的語音訊息會自動轉錄並作為文字注入對話中。代理會將轉錄內容視為一般文字。
| 提供者 | 品質 | 費用 | API Key |
|---|---|---|---|
| 本地 Whisper(預設) | 優良 | 免費 | 無需設定 |
| Groq Whisper API | 優良至卓越 | 免費額度 | GROQ_API_KEY |
| OpenAI Whisper API | 優良至卓越 | 付費 | VOICE_TOOLS_OPENAI_KEY 或 OPENAI_API_KEY |
INFO — 零設定
安裝
faster-whisper後,本地轉錄開箱即用。若無法使用,Hermes 也可使用常見安裝位置(如/opt/homebrew/bin)的本機whisperCLI,或透過HERMES_LOCAL_STT_COMMAND使用自訂指令。
設定
# In ~/.hermes/config.yaml
stt:
provider: "local" # "local" | "groq" | "openai" | "mistral" | "xai"
local:
model: "base" # tiny, base, small, medium, large-v3
openai:
model: "whisper-1" # whisper-1, gpt-4o-mini-transcribe, gpt-4o-transcribe
mistral:
model: "voxtral-mini-latest" # voxtral-mini-latest, voxtral-mini-2602
xai:
model: "grok-stt" # xAI Grok STT
提供者詳細說明
本地(faster-whisper) — 透過 faster-whisper 在本機執行 Whisper。預設使用 CPU,如有 GPU 則自動使用。模型大小:
| 模型 | 大小 | 速度 | 品質 |
|---|---|---|---|
tiny | ~75 MB | 最快 | 基礎 |
base | ~150 MB | 快速 | 優良(預設) |
small | ~500 MB | 中等 | 較佳 |
medium | ~1.5 GB | 較慢 | 優秀 |
large-v3 | ~3 GB | 最慢 | 最佳 |
Groq API — 需要 GROQ_API_KEY。想要免費的雲端 STT 選項時,是不錯的備援方案。
OpenAI API — 優先接受 VOICE_TOOLS_OPENAI_KEY,其次回退至 OPENAI_API_KEY。支援 whisper-1、gpt-4o-mini-transcribe 和 gpt-4o-transcribe。
Mistral API(Voxtral Transcribe) — 需要 MISTRAL_API_KEY。使用 Mistral 的 Voxtral Transcribe 模型。支援 13 種語言、說話者區分和字級時間戳。安裝指令:pip install hermes-agent[mistral]。
xAI Grok STT — 需要 XAI_API_KEY。透過 multipart/form-data 向 https://api.x.ai/v1/stt 傳送請求。如果你已使用 xAI 進行聊天或 TTS,想用同一個 API Key 搞定所有功能,這是不錯的選擇。自動偵測順序將其排在 Groq 之後 — 需明確設定 stt.provider: xai 才會強制使用。
自訂本機 CLI 備援 — 如果你想讓 Hermes 直接呼叫本地轉錄指令,請設定 HERMES_LOCAL_STT_COMMAND。指令模板支援 {input_path}、{output_dir}、{language} 和 {model} 佔位符。你的指令必須在 {output_dir} 下某處寫入 .txt 轉錄檔案。
範例:豆包 / 火山引擎 ASR
如果你使用 doubao-speech 進行豆包 TTS(參見上方),同一個套件也可透過本機指令 STT 介面處理語音轉文字:
pip install doubao-speech
export VOLCENGINE_APP_ID="your-app-id"
export VOLCENGINE_ACCESS_TOKEN="your-access-token"
export HERMES_LOCAL_STT_COMMAND='doubao-speech transcribe {input_path} --out {output_dir}/transcript.txt'
stt:
provider: local_command
Hermes 會將收到的語音訊息寫入 {input_path},執行指令,然後讀取 {output_dir} 下產生的 .txt 檔案。語言由火山引擎大模型端點自動偵測。
備援行為
如果你設定的提供者不可用,Hermes 會自動回退:
- 本地 faster-whisper 不可用 → 嘗試本機
whisperCLI 或HERMES_LOCAL_STT_COMMAND,再回退至雲端提供者 - Groq Key 未設定 → 回退至本地轉錄,再回退至 OpenAI
- OpenAI Key 未設定 → 回退至本地轉錄,再回退至 Groq
- Mistral Key/SDK 未設定 → 自動偵測時跳過;回退至下一個可用提供者
- 所有提供者均不可用 → 語音訊息會直接傳遞並附上準確的使用者提示
STT 自訂指令提供者
如果你需要的 STT 引擎未被原生支援(豆包 ASR、NVIDIA Parakeet、whisper.cpp 建構版、開源 SenseVoice CLI,或任何提供 shell 指令介面的工具),你可以將其設定為指令型提供者,無需編寫任何 Python。Hermes 會對音訊檔案執行你的 shell 指令,然後讀取轉錄結果。
在 stt.providers.<name> 下宣告一個或多個提供者,並透過 stt.provider: <name> 在它們之間切換 — 與 TTS 指令提供者登錄機制格式相同,僅方向調整為輸入=音訊 → 輸出=轉錄。
stt:
provider: parakeet # 在 stt.providers 下自訂名稱
providers:
parakeet:
type: command
command: "parakeet-asr --model nvidia/parakeet-tdt-0.6b-v2 --in {input_path} --out {output_path}"
format: txt
language: en
timeout: 300
whispercpp:
type: command
command: "whisper-cli -m ~/models/ggml-large-v3.bin -f {input_path} -otxt -of {output_dir}/transcript"
format: txt
sensevoice:
type: command
command: "sensevoice-cli {input_path} --json | tee {output_path}"
format: json
這補充了舊版的 HERMES_LOCAL_STT_COMMAND 快速通道 — 該環境變數仍可透過內建的 local_command 路徑正常使用。當你需要多個 shell 驅動的 STT 引擎、可透過 stt.provider 選擇的名稱、或需要各提供者專屬的 language / model / timeout 時,請使用 stt.providers.<name>。
STT 佔位符
你的指令模板可引用以下佔位符。Hermes 在渲染時替換它們,並為周圍環境(裸字串/單引號/雙引號)進行 shell 引號處理,因此包含空格的路徑是安全的。
| 佔位符 | 意義 |
|---|---|
{input_path} | 輸入音訊檔案的絕對路徑(原始位置,唯讀) |
{output_path} | 指令應寫入轉錄結果的絕對路徑 |
{output_dir} | {output_path} 的父目錄(方便 whisper 風格的工具使用) |
{format} | 設定的輸出格式:txt / json / srt / vtt |
{language} | 設定的語言代碼(預設為 en) |
{model} | stt.providers.<name>.model,未設定時為空 |
使用 {{ 和 ``}}` 表示字面量大括號(方便在指令中嵌入 JSON 片段)。
如何讀取轉錄結果
指令成功執行後:
- 若
{output_path}存在且非空 → Hermes 將其作為 UTF-8 文字讀取。 - 否則,若指令寫入了 stdout → Hermes 使用該輸出。
- 否則 → 錯誤:「Command STT provider wrote no output file and produced no stdout」。
這讓你可以用此登錄機制支援檔案寫入型 CLI(whisper-cli、parakeet-asr)以及將轉錄結果輸出到 stdout 的 curl 風格一行指令(curl … | jq -r .text)。
對於 format: json / srt / vtt,Hermes 將原始檔案內容作為 transcript 欄位回傳。從 JSON 中提取 .text 不在執行器的範圍內 — 請設定 format: txt,或在下游後處理 JSON。
STT 指令提供者選用鍵值
| 鍵值 | 預設值 | 意義 |
|---|---|---|
timeout | 300 | 秒數;到期時會終止整個行程樹(Unix 為 start_new_session,Windows 為 taskkill /T)。 |
format | txt | txt / json / srt / vtt 之一。設定 {output_path} 的副檔名。 |
language | en | 轉送至 {language}。預設為 stt.language,再回退至 en。 |
model | 空 | 轉送至 {model}。transcribe_audio() 的 model= 參數會覆蓋此值。 |
STT 指令提供者行為說明
- 內建名稱永遠優先。 宣告
stt.providers.openai: type: command不會覆寫真正的 OpenAI Whisper 處理器。內建名稱在指令提供者解析器執行前就已被短路。 - 行程樹清理。 超過
timeout的指令會終止整個行程樹,而不僅是 shell 封裝程式。會 fork 模型載入子行程的長時間執行 ASR 管道也能可靠地被回收。 - Shell 引號處理是自動的。
'…'內的佔位符會進行單引號安全逸脫;"…"內的會進行$/`/"逸脫;引號外的會使用shlex.quote。不要預先為佔位符值加引號。
STT 指令提供者安全性
Shell 指令以與 Hermes 相同的使用者身分執行,具有完整的檔案系統存取權限 — 與 tts.providers.<name>: type: command 和 HERMES_LOCAL_STT_COMMAND 相同的信任模型。請僅宣告你信任的來源的指令提供者。
Python 外掛提供者(STT)
對於既非內建又無法以 shell 指令表達的 STT 引擎(需要 Python SDK、OAuth 刷新認證、串流分段等),可透過 ctx.register_transcription_provider() 註冊 Python 外掛。該外掛與 6 個內建提供者(local、local_command、groq、openai、mistral、xai)以及 stt.providers.<name>: type: command 登錄機制共存 — 內建提供者保留其原生實作且名稱衝突時永遠優先;指令提供者優於同名外掛(設定比外掛安裝更本地化)。
何時使用何種方式(STT)
| 後端具備… | 使用 |
|---|---|
| 單一 shell 指令,接收音訊檔案並輸出文字 | stt.providers.<name>: type: command(無需 Python) |
| 僅需要舊版單指令快速通道 | HERMES_LOCAL_STT_COMMAND 環境變數(保留向後相容) |
| 僅有 Python SDK,沒有 CLI | register_transcription_provider() 外掛 |
| OAuth 刷新認證、串流分段、語音列表中繼資料 | register_transcription_provider() 外掛 |
已有內建提供者涵蓋(local、groq、openai…) | 設定 stt.provider: <name> — 內建提供者為內聯實作 |
解析順序
stt.provider為內建名稱 → 內建分派。永遠優先。stt.provider符合stt.providers.<name>且設有command:→ 指令提供者執行器(參見 STT 自訂指令提供者)。優於同名外掛。stt.provider符合外掛註冊的TranscriptionProvider→ 外掛分派:- 若外掛的
is_available()回傳False(缺少認證或 SDK),呼叫會傳回一個標明外掛的不可用錯誤格式 — 而非通用的「No STT provider available」訊息。 - 否則會以
model(來自公開的model=參數,回退至stt.<provider>.model)和language(來自stt.<provider>.language)呼叫外掛的transcribe()。
- 若外掛的
- 無符合項 → 「No STT provider available」錯誤。
各提供者設定命名空間
外掛從 config.yaml 中的 stt.<provider> 讀取其各提供者設定,與內建提供者讀取 stt.openai.model / stt.mistral.model 的方式相同:
stt:
provider: my-stt
my-stt:
model: whisper-large-v3
language: ja # 作為 language= 轉送至 transcribe()
# 其他外掛專屬鍵值放在此處;透過你自己的
# config.yaml 存取方式在 __init__/is_available/transcribe 中讀取
分派器轉送此區段中的 model 和 language;其餘內容由外掛自行讀取。
最小外掛範例
將以下檔案放入 ~/.hermes/plugins/my-stt/:
plugin.yaml:
name: my-stt
version: 0.1.0
description: "My custom Python STT backend"
__init__.py:
from agent.transcription_provider import TranscriptionProvider
class MySTTProvider(TranscriptionProvider):
@property
def name(self) -> str:
return "my-stt" # stt.provider 對應的名稱
@property
def display_name(self) -> str:
return "My Custom STT"
def is_available(self) -> bool:
# 當認證或相依套件缺失時回傳 False — 選擇器會略過此行,
# 但分派器在明確設定時仍會路由至此。
import os
return bool(os.environ.get("MY_STT_API_KEY"))
def transcribe(self, file_path, *, model=None, language=None, **extra):
# 回傳標準的轉錄格式:
# {"success": bool, "transcript": str, "provider": str, "error": str}
# 不要拋出例外 — 將例外轉換為錯誤格式,讓
# Gateway/CLI 呼叫者在失敗時看到一致的格式。
try:
import my_stt_sdk
client = my_stt_sdk.Client()
text = client.transcribe(open(file_path, "rb"))
return {
"success": True,
"transcript": text,
"provider": "my-stt",
}
except Exception as exc:
return {
"success": False,
"transcript": "",
"error": f"my-stt failed: {exc}",
"provider": "my-stt",
}
def register(ctx):
ctx.register_transcription_provider(MySTTProvider())
啟用它(hermes plugins enable my-stt),在 config.yaml 中設定 stt.provider: my-stt,語音訊息轉錄就會透過你的外掛路由。
選用鉤子
在你的提供者類別上覆寫以下方法以獲得更豐富的整合:
list_models()→{id, display, languages, max_audio_seconds}字典列表。default_model()→ 使用者未覆蓋模型時回傳的字串。get_setup_schema()→ 回傳{name, badge, tag, env_vars: [{key, prompt, url}]}以驅動hermes tools/hermes setup中的選擇器列(STT 的選擇器類別尚未上線 — 此中繼資料供外掛前瞻性相容使用)。
完整的 ABC 定義請參見 agent/transcription_provider.py,包含完整文件字串。