Голос и TTS
VibeOS поддерживает как синтез речи из текста (TTS), так и транскрибацию голосовых сообщений на всех платформах обмена сообщениями.
Если у вас есть платная подписка Nous Portal, OpenAI TTS доступен через Tool Gateway без отдельного ключа API OpenAI. Для новых установок выполните vibeos setup --portal, чтобы войти и сразу включить все инструменты шлюза; для существующих установок выберите Nous Subscription только для TTS через vibeos model или vibeos tools.
Синтез речи (Text-to-Speech)
Преобразуйте текст в речь с помощью десяти провайдеров:
| Провайдер | Качество | Стоимость | API-ключ |
|---|---|---|---|
| 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 | Сохраняется в ~/.vibeos/audio_cache/ | MP3 |
Конфигурация
# В ~/.vibeos/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: '' # По умолчанию: ~/.vibeos/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 }}, VibeOS заменяет этот плейсхолдер на текущий текст TTS. В противном случае VibeOS автоматически добавляет раздел TRANSCRIPT с меткой. Персональная подсказка остается локальной и не отображается в ответе чата.
tts:
provider: gemini
gemini:
voice: Algieba
persona_prompt_file: ~/.vibeos/tts/butler-voice.md
Аудиотеги Gemini
Gemini 3.1 Flash TTS поддерживает аудиотеги в квадратных скобках на естественном языке, такие как [whispers], [excitedly], [very slow], [laughs] и другие выразительные ремарки. Включите tts.gemini.audio_tags, чтобы VibeOS выполнял скрытый проход перезаписи перед Gemini TTS. Перезапись вставляет встроенные теги только в скрипт TTS; видимый ответ чата остается неизменным.
tts:
provider: gemini
gemini:
model: gemini-3.1-flash-tts-preview
audio_tags: true
Перезапись использует auxiliary.tts_audio_tags и по умолчанию использует вашу основную модель чата. Переопределите эту вспомогательную задачу, если хотите, чтобы вставка тегов обрабатывалась более дешевой или быстрой моделью.
Ограничения длины ввода
Каждый провайдер имеет документированное ограничение на количество символов в одном запросе. VibeOS обрезает текст перед вызовом провайдера, чтобы запросы никогда не завершались ошибкой из-за длины:
| Провайдер | Лимит по умолчанию (символов) |
|---|---|
| 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) |
Переопределение для каждого провайдера с помощью max_text_length: в разделе провайдера вашей конфигурации TTS:
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 отправляются как обычные аудиофайлы (воспроизводятся, но отображаются в виде прямоугольного плеера вместо голосового сообщения).
Если вы хотите получать голосовые сообщения без установки ffmpeg, переключитесь на провайдера OpenAI, ElevenLabs или Mistral.
Пользовательские голоса xAI (клонирование голоса)
xAI поддерживает клонирование вашего голоса и его использование в TTS. Создайте пользовательский голос в консоли xAI, затем установите полученный voice_id в вашей конфигурации:
tts:
provider: xai
xai:
voice_id: "nlbqfwie" # ваш пользовательский ID голоса
Подробнее о записи, поддерживаемых форматах и ограничениях см. в документации xAI по пользовательским голосам.
Piper (локально, 44 языка)
Piper — это быстрый локальный нейросетевой TTS-движок от Open Home Foundation (сопровождающие Home Assistant). Он полностью работает на CPU, поддерживает 44 языка с предварительно обученными голосами и не требует API-ключа.
Установка через vibeos tools → Voice & TTS → Piper — VibeOS выполнит pip install piper-tts за вас. Или установите вручную: pip install piper-tts.
Переключение на Piper:
tts:
provider: piper
piper:
voice: en_US-lessac-medium
При первом вызове TTS для голоса, который не кэширован локально, VibeOS выполняет python -m piper.download_voices <name> и загружает модель (~20-90 МБ в зависимости от уровня качества) в ~/.vibeos/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) соответствуют 1:1 SynthesisConfig Piper. Они игнорируются в старых версиях piper-tts.
Пользовательские провайдеры команд
Если нужный вам TTS-движок не поддерживается изначально (VoxCPM, MLX-Kokoro, XTTS CLI, скрипт клонирования голоса или что-либо еще, имеющее CLI), вы можете подключить его как провайдера командного типа без написания Python-кода. VibeOS записывает входной текст во временный UTF-8 файл, выполняет вашу команду оболочки и читает аудиофайл, созданный командой.
Объявите одного или нескольких провайдеров в разделе 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 также поддерживает пользовательские .onnx через tts.piper.voice
type: command
command: "piper -m /path/to/custom.onnx -f {output_path} < {input_path}"
output_format: wav
Пример: Doubao (китайский seed-tts-2.0)
Для высококачественного китайского TTS через двунаправленный потоковый API ByteDance seed-tts-2.0 установите пакет PyPI doubao-speech и подключите его как командного провайдера:
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
Учетные данные берутся из вашего окружения оболочки (VOLCENGINE_APP_ID / VOLCENGINE_ACCESS_TOKEN) или ~/.doubao-speech/config.yaml. Выберите голос, добавив --voice zh-female-warm (или любой другой псевдоним из doubao-speech list-voices) в команду. doubao-speech также включает потоковое ASR — см. раздел STT ниже для интеграции с VibeOS. Исходный код и полная документация: github.com/Hypnus-Yuan/doubao-speech.
Плейсхолдеры
Ваш шаблон команды может ссылаться на эти плейсхолдеры. VibeOS подставляет их во время выполнения и экранирует каждое значение для соответствующего контекста (голый / в одинарных кавычках / в двойных кавычках), поэтому пути с пробелами и другими чувствительными для оболочки символами безопасны.
| Плейсхолдер | Значение |
|---|---|
{input_path} | Путь к временному UTF-8 текстовому файлу, созданному VibeOS |
{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. Автоматически определяется из расширения вывода, если VibeOS выбирает путь. |
voice_compatible | false | Если true, VibeOS конвертирует вывод MP3/WAV в Opus/OGG через ffmpeg, чтобы Telegram отображал голосовое сообщение. |
max_text_length | 5000 | Ввод обрезается до этой длины перед выполнением команды. |
voice / model | пусто | Передаются в команду только как значения плейсхолдеров. |
Примечания по поведению
- Встроенные имена всегда побеждают. Запись
tts.providers.openaiникогда не заменяет родной провайдер OpenAI, поэтому никакая пользовательская конфигурация не может незаметно заменить встроенный. - Доставка по умолчанию — документ. Командные провайдеры доставляют аудио как обычные вложения на всех платформах. Включите доставку в виде голосового сообщения для каждого провайдера с помощью
voice_compatible: true. - Сбои команд передаются агенту. Ненулевой код возврата, пустой вывод или тайм-аут возвращают ошибку с stderr/stdout команды, чтобы вы могли отладить провайдера из диалога.
type: command— значение по умолчанию, если заданcommand:. Явное указаниеtype: command— хорошая практика, но не обязательна; запись с непустой строкойcommandобрабатывается как командный провайдер.{input_path}/{text_path}взаимозаменяемы. Используйте тот, который лучше читается в вашей команде.
Безопасность
Командные провайдеры выполняют любую команду оболочки, которую вы настроили, с вашими правами пользователя. VibeOS экранирует значения плейсхолдеров и обеспечивает заданный тайм-аут, но сам шаблон команды является доверенным локальным вводом — относитесь к нему так же, как к скрипту оболочки в вашем PATH.
Плагины-провайдеры на Python
Для TTS-движков, которые нельзя выразить в виде одной команды оболочки — Python SDK без CLI, потоковые движки, API со списком голосов, аутентификация с обновлением OAuth — зарегистрируйте плагин Python через ctx.register_tts_provider(). Плагин сосуществует с (не заменяет) реестром пользовательских командных провайдеров; выберите тот интерфейс, который подходит для вашего движка.
Когда что выбирать
| Ваш бэкенд имеет… | Используйте |
|---|---|
| Один CLI, читающий текст из файла/stdin и записывающий аудио в файл/stdout | Командный провайдер (Python не нужен) |
| Два или три CLI, объединенных конвейером оболочки | Командный провайдер |
| Только Python SDK — без CLI | Плагин |
| Потоковые байты, которые вы хотите доставлять частями (голосовые сообщения во время генерации) | Плагин (переопределить stream()) |
API со списком голосов, используемый vibeos setup | Плагин (переопределить list_voices()) |
| Поток обновления OAuth (не статический токен Bearer) | Плагин |
Встроенные всегда побеждают, а командные провайдеры побеждают плагины с тем же именем — поэтому плагины безопасно регистрировать под любым не встроенным именем, не беспокоясь о замене существующей конфигурации.
Минимальный плагин
Поместите это в ~/.vibeos/plugins/my-tts/:
plugin.yaml:
name: my-tts
version: 0.1.0
description: "Мой пользовательский Python TTS-бэкенд"
__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())
Включите его (vibeos plugins enable my-tts), укажите tts.provider на него (tts.provider: my-tts в config.yaml), и инструмент text_to_speech будет направляться через ваш плагин.
Необязательные хуки
Переопределите эти методы в вашем классе провайдера для более богатой интеграции:
list_voices()→ список словарей{id, display, language, gender, preview_url}, отображаемых вvibeos tools.list_models()→ список словарей{id, display, languages, max_text_length}.get_setup_schema()→ вернуть{name, badge, tag, env_vars: [{key, prompt, url}]}для строки выбора вvibeos tools/vibeos setup. Без этого плагин все равно работает, но его строка в средстве выбора минимальна.stream(text, *, voice, model, format, **extra)→ итератор, возвращающий аудиобайты для потоковой доставки (по умолчанию вызываетNotImplementedError).- Свойство
voice_compatible→ установитеTrue, если ваш вывод совместим с Opus и шлюз должен доставлять его как голосовое сообщение (по умолчаниюFalse= обычное аудиовложение).
См. agent/tts_provider.py для полного ABC, включая строки документации.
Транскрибация голосовых сообщений (STT)
Голосовые сообщения, отправленные в Telegram, Discord, WhatsApp, Slack или Signal, автоматически транскрибируются и вставляются в виде текста в диалог. Агент видит транскрипт как обычный текст.
| Провайдер | Качество | Стоимость | API-ключ |
|---|---|---|---|
| Локальный Whisper (по умолчанию) | Хорошее | Бесплатно | Не требуется |
| Groq Whisper API | Хорошее–Лучшее | Бесплатный тариф | GROQ_API_KEY |
| OpenAI Whisper API | Хорошее–Лучшее | Платно | VOICE_TOOLS_OPENAI_KEY или OPENAI_API_KEY |
Локальная транскрибация работает «из коробки», если установлен faster-whisper. Если он недоступен, VibeOS также может использовать локальный CLI whisper из стандартных мест установки (например, /opt/homebrew/bin) или пользовательскую команду через VIBEOS_LOCAL_STT_COMMAND.
Конфигурация
# В ~/.vibeos/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) — Запускает Whisper локально через faster-whisper. Использует CPU по умолчанию, GPU, если доступен. Размеры моделей:
| Модель | Размер | Скорость | Качество |
|---|---|---|---|
tiny | ~75 МБ | Самая быстрая | Базовое |
base | ~150 МБ | Быстрая | Хорошее (по умолчанию) |
small | ~500 МБ | Средняя | Лучше |
medium | ~1.5 ГБ | Медленнее | Отличное |
large-v3 | ~3 ГБ | Самая медленная | Наилучшее |
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. Использует модели Voxtral Transcribe от Mistral. Поддерживает 13 языков, диаризацию говорящих и временные метки на уровне слов. Установка: cd ~/.vibeos/vibeos-agent && uv pip install -e ".[mistral]".
xAI Grok STT — Требует XAI_API_KEY. Отправляет запрос на https://api.x.ai/v1/stt как multipart/form-data. Хороший выбор, если вы уже используете xAI для чата или TTS и хотите один API-ключ для всего. Порядок автоопределения ставит его после Groq — явно укажите stt.provider: xai, чтобы принудительно его использовать.
Пользовательское резервное решение локального CLI — Установите VIBEOS_LOCAL_STT_COMMAND, если хотите, чтобы VibeOS напрямую вызывал локальную команду транскрибации. Шаблон команды поддерживает плейсхолдеры {input_path}, {output_dir}, {language} и {model}. Ваша команда должна записать транскрипт .txt где-нибудь в {output_dir}.
Пример: Doubao / Volcengine ASR
Если вы используете doubao-speech для Doubao TTS (см. выше), тот же пакет обрабатывает распознавание речи через интерфейс локальной команды STT:
pip install doubao-speech
export VOLCENGINE_APP_ID="your-app-id"
export VOLCENGINE_ACCESS_TOKEN="your-access-token"
export VIBEOS_LOCAL_STT_COMMAND='doubao-speech transcribe {input_path} --out {output_dir}/transcript.txt'
stt:
provider: local_command
VibeOS записывает входящее голосовое сообщение в {input_path}, выполняет команду и читает файл .txt, созданный в {output_dir}. Язык определяется автоматически эндпо