H繁中版
<!-- Source: https://hermesbible.com/docs/user-guide/features/tts -->

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 modelhermes 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
WhatsApp音訊檔案附件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 PROFILESCENEDIRECTOR'S NOTESSAMPLE CONTEXTTRANSCRIPT

如果檔案包含 {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 TTS5000
OpenAI4096
xAI15000
MiniMax10000
Mistral4000
Google Gemini32000
ElevenLabs依模型而異(見下表)
NeuTTS2000
KittenTTS2000
Piper5000

ElevenLabs 根據設定的 model_id 選擇上限:

model_id上限(字元)
eleven_flash_v2_540000
eleven_flash_v230000
eleven_multilingual_v2(預設)、eleven_multilingual_v1eleven_english_sts_v2eleven_english_sts_v110000
eleven_v3eleven_ttv_v35000
未知模型回退至提供者預設值(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_audiouse_cuda)與 Piper 的 SynthesisConfig 一一對應。在較舊版本的 piper-tts 中會被忽略。

自訂指令提供者

如果你需要的 TTS 引擎未被原生支援(VoxCPM、MLX-Kokoro、XTTS CLI、語音複製腳本,或任何提供 CLI 介面的工具),你可以將其設定為指令型提供者,無需編寫任何 Python。Hermes 會將輸入文字寫入臨時的 UTF-8 檔案,執行你的 shell 指令,然後讀取指令產生的音訊檔案。

tts.providers.<name> 下宣告一個或多個提供者,並透過 tts.provider: <name> 在它們之間切換 — 與切換內建的 edgeopenai 方式相同。

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}解析後的速度倍率(提供者或全域)

使用 {{}} 表示字面量大括號。

選用鍵值

鍵值預設值意義
timeout120秒數;到期時會終止整個行程樹(Unix 為 killpg,Windows 為 taskkill /T)。
output_formatmp3mp3 / wav / ogg / flac 之一。若 Hermes 自動選擇路徑,會根據輸出副檔名自動推斷。
voice_compatiblefalse設為 true 時,Hermes 會透過 ffmpeg 將 MP3/WAV 輸出轉換為 Opus/OGG,使 Telegram 顯示為語音氣泡。
max_text_length5000渲染指令前會將輸入截斷至此長度。
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_KEYOPENAI_API_KEY

INFO — 零設定

安裝 faster-whisper 後,本地轉錄開箱即用。若無法使用,Hermes 也可使用常見安裝位置(如 /opt/homebrew/bin)的本機 whisper CLI,或透過 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-1gpt-4o-mini-transcribegpt-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 不可用 → 嘗試本機 whisper CLI 或 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 片段)。

如何讀取轉錄結果

指令成功執行後:

  1. {output_path} 存在且非空 → Hermes 將其作為 UTF-8 文字讀取。
  2. 否則,若指令寫入了 stdout → Hermes 使用該輸出。
  3. 否則 → 錯誤:「Command STT provider wrote no output file and produced no stdout」。

這讓你可以用此登錄機制支援檔案寫入型 CLI(whisper-cliparakeet-asr)以及將轉錄結果輸出到 stdout 的 curl 風格一行指令(curl … | jq -r .text)。

對於 format: json / srt / vtt,Hermes 將原始檔案內容作為 transcript 欄位回傳。從 JSON 中提取 .text 不在執行器的範圍內 — 請設定 format: txt,或在下游後處理 JSON。

STT 指令提供者選用鍵值

鍵值預設值意義
timeout300秒數;到期時會終止整個行程樹(Unix 為 start_new_session,Windows 為 taskkill /T)。
formattxttxt / json / srt / vtt 之一。設定 {output_path} 的副檔名。
languageen轉送至 {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: commandHERMES_LOCAL_STT_COMMAND 相同的信任模型。請僅宣告你信任的來源的指令提供者。

Python 外掛提供者(STT)

對於既非內建又無法以 shell 指令表達的 STT 引擎(需要 Python SDK、OAuth 刷新認證、串流分段等),可透過 ctx.register_transcription_provider() 註冊 Python 外掛。該外掛與 6 個內建提供者(locallocal_commandgroqopenaimistralxai)以及 stt.providers.<name>: type: command 登錄機制共存 — 內建提供者保留其原生實作且名稱衝突時永遠優先;指令提供者優於同名外掛(設定比外掛安裝更本地化)。

何時使用何種方式(STT)

後端具備…使用
單一 shell 指令,接收音訊檔案並輸出文字stt.providers.<name>: type: command(無需 Python)
僅需要舊版單指令快速通道HERMES_LOCAL_STT_COMMAND 環境變數(保留向後相容)
僅有 Python SDK,沒有 CLIregister_transcription_provider() 外掛
OAuth 刷新認證、串流分段、語音列表中繼資料register_transcription_provider() 外掛
已有內建提供者涵蓋(localgroqopenai…)設定 stt.provider: <name> — 內建提供者為內聯實作

解析順序

  1. stt.provider 為內建名稱 → 內建分派。永遠優先。
  2. stt.provider 符合 stt.providers.<name> 且設有 command: → 指令提供者執行器(參見 STT 自訂指令提供者)。優於同名外掛。
  3. stt.provider 符合外掛註冊的 TranscriptionProvider → 外掛分派:
    • 若外掛的 is_available() 回傳 False(缺少認證或 SDK),呼叫會傳回一個標明外掛的不可用錯誤格式 — 而非通用的「No STT provider available」訊息。
    • 否則會以 model(來自公開的 model= 參數,回退至 stt.<provider>.model)和 language(來自 stt.<provider>.language)呼叫外掛的 transcribe()
  4. 無符合項 → 「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 中讀取

分派器轉送此區段中的 modellanguage;其餘內容由外掛自行讀取。

最小外掛範例

將以下檔案放入 ~/.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,包含完整文件字串。



MCP(Model Context Protocol)