Legan Studio
Все статьи
~ 13 мин чтения

Голосовой Telegram-бот: распознавание речи через Whisper

Как принять голосовое сообщение в Telegram, распознать его через Whisper и ответить голосом. Архитектура, форматы, нюансы тишины и шумов.

  • Telegram
  • AI
  • сценарии

Голосовое — самый ленивый способ написать боту. Пользователю не надо набирать длинный запрос на ходу, в перчатках, с ребёнком на руках или за рулём. А боту достаточно превратить аудио в текст и пустить его в обычный пайплайн обработки. STT-движки последних поколений (Whisper Large v3, Distil-Whisper, Yandex SpeechKit, GigaAM, SaluteSpeech) делают это стабильно даже на шумной записи из метро или с улицы.

В этой статье разберём весь жизненный цикл голосового Telegram-бота: как Telegram передаёт voice-сообщения, какие STT-сервисы выбрать под русский язык, как сравнивать TTS-движки, как собрать пайплайн на aiogram, посчитать стоимость на 1000 пользователей и не нарушить 152-ФЗ при работе с биометрией.

Зачем боту голос

Голосовой ввод — это не модный гаджет, а реальный UX-паттерн с понятной аудиторией.

  • В дороге. Пользователь за рулём или с пакетами в руках не может набрать текст. Голос — единственный канал ввода.
  • Скорость диктовки. Средняя скорость набора на мобильной клавиатуре — 30–40 слов в минуту, диктовка — 120–160. Для длинных сообщений выигрыш в 4 раза.
  • Accessibility. Пользователи с нарушениями зрения, моторики, дислексией. Голос снимает барьер.
  • Снижение трения. Открыть бот, нажать и держать кнопку микрофона — 2 действия. Открыть бот, тапнуть в поле, набрать, отправить — 4 действия плюс умственная нагрузка на формулировку.
  • Эмоциональный канал. В голосе есть интонация, паузы, сомнение. Для бота-собеседника или коуча это даёт глубину, недоступную тексту.

Сценарии использования

Самые жизнеспособные продуктовые сценарии для голосовых ботов в Telegram.

  • Голосовой ассистент по делам. Пользователь надиктовывает «купить молоко, забрать заказ, позвонить маме» — бот раскладывает по задачам и ставит напоминания.
  • Расшифровка чужих voice-сообщений. Пользователь пересылает в бот голосовое из рабочего чата, получает текст. Незаменимо для тех, кто на встречах или в шумном офисе.
  • Бот-собеседник и психолог. Голос делает разговор живым. GPT-обвязка с TTS-ответом превращает чат в диалог.
  • Обучение языкам. Бот произносит фразу, пользователь повторяет, STT оценивает произношение, TTS даёт обратную связь.
  • Медицинские заметки. Врач после приёма надиктовывает протокол — бот сохраняет в EHR. Один из самых платежеспособных сегментов.
  • Полевые отчёты. Курьер, монтажник, сервис-инженер диктует отчёт по объекту с фото. Бот собирает структурированную карточку.
  • Транскрибация подкастов и интервью. Пользователь шлёт длинный аудио-файл, бот возвращает текст с таймкодами и спикерами.

Базовый pipeline

voice (OGG/OPUS) → download → ffmpeg (WAV 16kHz mono) → STT → текст
                                                               ↓
                                                     LLM / handler / FSM
                                                               ↓
                                  ответ ← sendVoice (OGG) ← ffmpeg ← TTS

Минимальный цикл умещается в 200 строк кода на Python с aiogram + faster-whisper. На холодный старт уходит 3–7 секунд из-за загрузки модели в память — держите процесс живым, не запускайте Whisper на каждый запрос.

Что приходит из Telegram

Голосовые сообщения приходят в апдейте как voice — это file_id, duration, mime_type (обычно audio/ogg) и file_size. Аудиофайл — OGG-контейнер с кодеком OPUS, моно, 48 кГц. Скачивается через getFile плюс загрузку по file_path.

Помимо voice бывает audio (музыкальные файлы, mp3/m4a) и video_note — кружок. Голосовой бот обычно поддерживает все три типа, унифицированно конвертируя в один формат для STT.

Лимит размера файла для скачивания через Bot API — 20 МБ. Если пользователь шлёт длинную запись (Telegram пускает голосовые до 60 минут), часть случаев упрётся в этот лимит. Решение — Local Bot API Server, который снимает ограничение до 2 ГБ.

Сравнение STT-сервисов

Под русский язык реально работают следующие движки. Цены актуальны на начало 2026 года, проверяйте перед интеграцией.

ДвижокЯзык RUЦена за минутуLatencyТочность (WER)On-prem
OpenAI Whisper APIХорошооколо 0.006 USD1–3 с5–8%Нет
Whisper large-v3 (локально)ХорошоТолько GPU0.5–2 с (GPU)5–8%Да
faster-whisper (CTranslate2)ХорошоТолько CPU/GPU0.3–1 с (GPU)5–8%Да
Distil-WhisperУдовл.Только GPU0.1–0.5 с6–9%Да
Yandex SpeechKitОтличнооколо 0.18 RUB0.5–1.5 с4–7%Гибрид
SaluteSpeech (Сбер)Отличнооколо 0.15 RUB0.5–1.5 с4–7%Гибрид
Google Speech-to-TextХорошооколо 0.024 USD1–2 с5–8%Нет
Azure SpeechХорошооколо 1 USD за час1–2 с5–8%Контейнер
GigaAM (Сбер, open)ОтличноТолько GPU0.3–1 с4–7%Да

Что выбрать. Для прототипа — OpenAI Whisper API, минимум кода. Для продакшна с деньгами на API — Yandex SpeechKit или SaluteSpeech, оба заточены под русский с лучшим WER. Для on-prem (медицина, госзакупки, чувствительные данные) — faster-whisper large-v3 или GigaAM на собственном GPU.

Сравнение TTS-движков

ДвижокЯзык RUЦенаКачествоЭмоции/SSMLOn-prem
Yandex SpeechKit TTSОтличнооколо 0.40 RUB за 1000 симв.ВысокоеДа, SSMLГибрид
SaluteSpeech TTSОтличнооколо 0.35 RUB за 1000 симв.ВысокоеДаГибрид
OpenAI TTS (tts-1, tts-1-hd)Удовл.около 15 USD за 1М симв.ВысокоеБазовоНет
ElevenLabsУдовл. (есть мультиязычная v2)около 22 USD за 100k симв.Очень высокоеДаНет
Silero TTSХорошоБесплатноСреднееБазовоДа
Coqui TTS (XTTS v2)Удовл.БесплатноСреднее-высокоеДа, голосовое клонированиеДа

Что выбрать. Для русского коммерческого продукта — Yandex SpeechKit TTS, хороший каталог голосов и SSML. Для on-prem без бюджета — Silero TTS, запускается на CPU без GPU. Для голосового клонирования (свой бренд-голос) — Coqui XTTS v2 или ElevenLabs с осторожностью к ограничениям.

Скачивание voice через Telegram API

from aiogram import Bot
import aiofiles

async def download_voice(bot: Bot, file_id: str, dest: str) -> None:
    file = await bot.get_file(file_id)
    file_path = file.file_path
    async with aiofiles.open(dest, "wb") as f:
        await bot.download_file(file_path, destination=f)

После скачивания получаем OGG/OPUS. Конвертируем в WAV 16 кГц моно — оптимальный вход для большинства STT.

ffmpeg -i voice.ogg -ar 16000 -ac 1 -c:a pcm_s16le voice.wav

В Python вызываем через subprocess или используем pydub/ffmpeg-python.

Handler на aiogram: voice → STT → LLM → TTS

Полный цикл — приём голосового, распознавание через Whisper API, ответ от LLM, синтез речи через Yandex SpeechKit и отправка обратно как sendVoice.

import asyncio
import tempfile
from pathlib import Path
from aiogram import Bot, Dispatcher, F, types
from aiogram.types import FSInputFile
from openai import AsyncOpenAI
import httpx

bot = Bot(token=BOT_TOKEN)
dp = Dispatcher()
oai = AsyncOpenAI(api_key=OPENAI_KEY)

@dp.message(F.voice)
async def voice_handler(msg: types.Message) -> None:
    await bot.send_chat_action(msg.chat.id, "typing")

    with tempfile.TemporaryDirectory() as tmp:
        ogg_path = Path(tmp) / "in.ogg"
        wav_path = Path(tmp) / "in.wav"
        out_ogg = Path(tmp) / "out.ogg"

        # 1. Скачать voice
        file = await bot.get_file(msg.voice.file_id)
        await bot.download_file(file.file_path, destination=ogg_path)

        # 2. Конвертировать в WAV 16kHz mono
        await run_ffmpeg(["-i", str(ogg_path), "-ar", "16000",
                          "-ac", "1", str(wav_path)])

        # 3. STT через Whisper API
        with open(wav_path, "rb") as f:
            stt = await oai.audio.transcriptions.create(
                model="whisper-1", file=f, language="ru"
            )
        user_text = stt.text

        # 4. LLM ответ
        chat = await oai.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": "Ты дружелюбный ассистент."},
                {"role": "user", "content": user_text},
            ],
        )
        answer = chat.choices[0].message.content

        # 5. TTS через Yandex SpeechKit
        wav_out = Path(tmp) / "out.wav"
        await yandex_tts(answer, wav_out)

        # 6. Конвертировать обратно в OGG/OPUS для sendVoice
        await run_ffmpeg(["-i", str(wav_out), "-c:a", "libopus",
                          "-b:a", "24k", str(out_ogg)])

        # 7. Отправить
        await msg.answer_voice(FSInputFile(out_ogg))


async def run_ffmpeg(args: list[str]) -> None:
    proc = await asyncio.create_subprocess_exec(
        "ffmpeg", "-y", *args,
        stdout=asyncio.subprocess.DEVNULL,
        stderr=asyncio.subprocess.DEVNULL,
    )
    await proc.wait()

Вызов Yandex SpeechKit TTS

async def yandex_tts(text: str, dest: Path) -> None:
    url = "https://tts.api.cloud.yandex.net/speech/v1/tts:synthesize"
    headers = {"Authorization": f"Api-Key {YANDEX_API_KEY}"}
    data = {
        "text": text,
        "lang": "ru-RU",
        "voice": "ermil",
        "emotion": "good",
        "format": "lpcm",
        "sampleRateHertz": 48000,
    }
    async with httpx.AsyncClient(timeout=30) as client:
        async with client.stream("POST", url, headers=headers,
                                 data=data) as resp:
            with open(dest, "wb") as f:
                async for chunk in resp.aiter_bytes():
                    f.write(chunk)

LPCM — сырые сэмплы без заголовка. Для отдачи в ffmpeg используйте флаги -f s16le -ar 48000 -ac 1 на входе.

Какую модель Whisper брать

Whisper выпускается в нескольких размерах: tiny, base, small, medium, large-v3.

  • tiny / base — для русского почти не подходят, WER 15–25%.
  • small (244M) — реалистичный минимум, WER 8–12%.
  • medium (769M) — стабильная рабочая лошадка, WER 6–9%.
  • large-v3 (1.5B) — идеал, WER 5–8%.
  • Distil-Whisper — компактнее в 6 раз, скорость в 6 раз выше, потеря качества порядка 1% WER.

На GPU 16 ГБ large-v3 обрабатывает 30 секунд аудио примерно за секунду. На CPU — 10–30 секунд. Для продакшна на CPU берите faster-whisper с моделью medium и квантизацией int8.

Стриминг ответа

Для естественности диалога ответ можно отдавать порциями: пока LLM генерирует следующее предложение, TTS уже синтезирует предыдущее, а Telegram уже воспроизводит первое. Это даёт ощущение живой реакции вместо монолитной паузы в 5–10 секунд.

Подход: разбиваем ответ LLM по предложениям через re.split(r'(?<=[.!?])\s+', text), на каждое предложение запускаем TTS параллельно, отправляем sendVoice по мере готовности. Минус — пользователь получает несколько голосовых вместо одного, нужно обсудить с дизайнером сценария.

Распознавание длинных voice

Telegram пускает голосовые до 60 минут, музыкальные файлы — до 2 ГБ (через Local Bot API). Whisper рассчитан на чанки до 30 секунд, дальше сегментирует сам, но память растёт линейно от длины.

Стратегия для длинных файлов:

  • VAD-сегментация. Silero VAD режет на куски по паузам, длиной 20–30 секунд каждый.
  • Параллельная обработка в пуле воркеров.
  • Сборка результата с учётом перекрытий (5% overlap, чтобы не терять слова на стыках).
  • Дедупликация повторов на стыках по совпадению последних 3 слов.
from silero_vad import load_silero_vad, get_speech_timestamps

vad = load_silero_vad()
timestamps = get_speech_timestamps(audio, vad, sampling_rate=16000,
                                    min_silence_duration_ms=500)
chunks = [audio[ts["start"]:ts["end"]] for ts in timestamps]

Качество и подводные камни

Что регулярно ломает распознавание.

  • Долгие паузы. Whisper иногда «галлюцинирует» субтитры на участках тишины (известный баг — повторяет «спасибо за просмотр»). Помогает VAD (Silero VAD, WebRTC VAD) — отрезает тишину перед прогоном.
  • Шум вокруг. Транспорт, ветер, чужая речь. Помогает шумодав вроде RNNoise или DeepFilterNet перед распознаванием.
  • Суржик. Whisper хорошо знает русский, но если пользователь смешивает русский с английскими терминами, явно укажите language="ru" — иначе модель может уйти в украинский или белорусский.
  • Длинные сообщения. Бейте на куски по 30 секунд через VAD и склеивайте текст с учётом перекрытий.
  • Низкое качество микрофона. Дешёвые гарнитуры через Bluetooth дают сэмпл-рейт 8 кГц после кодеков HFP. Whisper переживает, но WER растёт на 3–5%.

Распознавание спикеров (диаризация)

Для группового voice или интервью полезно отличать «кто говорит». Базовая диаризация:

  • pyannote.audio — open source, точность 5–10% DER на русском.
  • Yandex SpeechKit Speaker Diarization — облачное API.
  • AssemblyAI — английский лучше, русский слабее.

Pipeline: STT даёт текст и таймкоды слов, диаризация — таймкоды спикеров; объединяем по пересечению временных интервалов и получаем диалог вида «Спикер 1: …», «Спикер 2: …».

Латентность

Восприятие голосового бота сильно зависит от задержки. Целевая планка — менее 3 секунд от конца записи до начала ответа. На что влияет.

  • Размер модели. Distil-Whisper-small справится быстрее, чем Whisper-large.
  • Видеокарта против CPU. GPU быстрее в 5–20 раз.
  • Стриминговое распознавание. Некоторые движки (SaluteSpeech, Yandex SpeechKit, Deepgram) выдают частичный текст уже во время загрузки. Whisper API так не умеет.
  • Параллельные запросы. Модель не масштабируется бесконечно — нужен пул воркеров и очередь.
  • Сетевой round-trip. Облачный STT добавляет 200–500 мс на загрузку файла. На длинных voice это терпимо, на коротких реакциях ощутимо.
  • Холодный старт. На запуск Whisper уходит 3–7 секунд из-за загрузки модели в память. Держите процесс живым.

Приватность и 152-ФЗ

Голос — это биометрические персональные данные (специальная категория по 152-ФЗ). Юридические последствия серьёзнее, чем при работе с обычным текстом.

  • В политике конфиденциальности нужна отдельная строка про обработку голоса, цели и срок хранения.
  • Отдельное письменное согласие на обработку биометрии. В контексте бота — клик с явной формулировкой и логированием.
  • С июня 2025 биометрия для коммерческих целей должна сдаваться в ГИС ЕБС или храниться с дополнительной сертификацией. Для большинства ботов проще не хранить аудио.
  • Если можно не хранить аудио после распознавания — не храните, оставляйте только текст.
  • Хранение аудио увеличивает риски утечки и требует усиленной защиты: шифрование в покое, доступ только по необходимости, журнал доступа.
  • Для медицинских и финансовых ботов — отдельный аудит и согласие с подписью.

Передача голоса в OpenAI/Google/ElevenLabs = трансграничная передача ПДн в недружественные страны. Требуется уведомление РКН и юридическая обвязка. На практике большинство студий выбирает Yandex SpeechKit или GigaAM именно по этой причине.

Стоимость на 1000 пользователей

Допустим, 1000 активных пользователей в день, средний пользователь шлёт 3 голосовых по 15 секунд и получает 3 голосовых ответа по 200 символов.

Облачный сценарий (Yandex SpeechKit STT + TTS).

  • STT: 1000 × 3 × 15 с = 45000 с = 750 мин × 0.18 RUB = 135 RUB в день.
  • TTS: 1000 × 3 × 200 = 600 000 симв. = 600 × 0.40 RUB = 240 RUB в день.
  • Итого: примерно 375 RUB в день, около 11 000 RUB в месяц на STT/TTS.
  • Плюс LLM (если есть): GPT-4o-mini примерно 1500–3000 RUB в день при тех же объёмах.

Self-hosted сценарий (faster-whisper large-v3 + Silero TTS на одной GPU).

  • Аренда GPU-сервера с RTX 4090 (24 ГБ): около 25 000 RUB в месяц.
  • Электричество и обслуживание (если своё железо): около 10 000 RUB в месяц.
  • При нагрузке выше 5000 пользователей в день облако становится дороже железа. Точка перелома — 3000–5000 DAU.

Кеширование и оптимизация

Простые приёмы экономии на STT/TTS.

  • Кеш TTS. Часто повторяющиеся фразы (приветствие, ошибки, подтверждения) синтезируем один раз, хранится в Redis или на диске. Telegram умеет переиспользовать file_id после первой отправки — отправили один раз, дальше шлём только file_id без повторной загрузки.
  • Хеш по voice. Если одно и то же голосовое присылается повторно (часто бывает при пересылках в групповых чатах), считаем sha256 файла, кеш на текст распознавания.
  • Дешёвая модель на коротких voice. До 3 секунд — Whisper-small, дольше — large-v3. Экономия 30–40% GPU-времени без потери UX.
  • Фоновая прогрузка модели. На старте контейнера держим Whisper в памяти, не загружаем по запросу.
  • Батчинг. faster-whisper умеет batch inference; при большом потоке коротких voice экономия времени до 2 раз.

Итого

Голосовой бот — это стандартный пайплайн «приём → декодирование → STT → логика → TTS → отправка», в котором главные риски сидят в качестве распознавания, выборе движка и юридической обвязке вокруг биометрии. Берите Yandex SpeechKit или SaluteSpeech для коммерческого продукта на русском, faster-whisper large-v3 — для on-prem. TTS — Yandex SpeechKit или Silero. Обязательно VAD против тишины, явное language="ru", кеш частых ответов через file_id. Считайте экономику до запуска: на 5000+ DAU собственная GPU дешевле облака. Не храните аудио без явной нужды и согласия, это снимает 90% юридических вопросов с биометрией.

Частые вопросы

Как Telegram передаёт голосовые сообщения боту?

Голосовые приходят в апдейте как voice — это file_id, duration, mime_type (обычно audio/ogg) и file_size. Аудиофайл — OGG-контейнер с кодеком OPUS, моно, 48 кГц. Скачивается через getFile плюс загрузку по file_path. Помимо voice бывает audio (музыкальные файлы, mp3/m4a) и video_note — кружок. Голосовой бот обычно поддерживает все три типа, унифицированно конвертируя в один формат для STT. Лимит размера файла для скачивания через Bot API — 20 МБ. Решение для длинных файлов — Local Bot API Server, который снимает ограничение до 2 ГБ.

Какой STT-движок выбрать для русскоязычного бота?

Для прототипа — OpenAI Whisper API, минимум кода и около 0.006 USD за минуту. Для продакшна с деньгами на API — Yandex SpeechKit или SaluteSpeech, оба заточены под русский с лучшим WER 4–7% и ценой около 0.15–0.18 RUB за минуту. Для on-prem (медицина, госзакупки, чувствительные данные) — faster-whisper large-v3 или GigaAM на собственном GPU. Для CPU-only сервера берите faster-whisper medium с квантизацией int8. Distil-Whisper компактнее в 6 раз и быстрее в 6 раз с потерей 1% WER.

Какой TTS-движок брать для ответа голосом?

Для русского коммерческого продукта — Yandex SpeechKit TTS, около 0.40 RUB за 1000 символов, хороший каталог голосов, SSML и эмоции. SaluteSpeech дешевле — около 0.35 RUB за 1000 символов. Для on-prem без бюджета — Silero TTS, запускается на CPU без GPU, бесплатно, среднее качество. Для голосового клонирования (свой бренд-голос) — Coqui XTTS v2 или ElevenLabs с осторожностью к ограничениям и трансграничной передаче ПДн. OpenAI TTS работает с русским удовлетворительно и стоит около 15 USD за 1М символов.

Какие проблемы распознавания речи в Telegram-боте?

Долгие паузы — Whisper иногда «галлюцинирует» субтитры на тишине (повторяет «спасибо за просмотр»), помогает VAD (Silero VAD, WebRTC VAD). Шум вокруг — транспорт, ветер, чужая речь; помогает шумодав вроде RNNoise или DeepFilterNet. Суржик — Whisper хорошо знает русский, но при смешении с английскими терминами явно указывайте language="ru", иначе модель уходит в украинский или белорусский. Длинные сообщения — бейте на куски по 30 секунд через VAD, склеивайте с overlap. Низкое качество микрофона через Bluetooth HFP даёт 8 кГц, WER растёт на 3–5%.

Какая целевая латентность голосового Telegram-бота?

Восприятие голосового бота сильно зависит от задержки. Целевая планка — менее 3 секунд от конца записи до начала ответа. На что влияет. Размер модели (Distil-Whisper-small справится быстрее, чем Whisper-large). GPU против CPU (GPU быстрее в 5–20 раз). Стриминговое распознавание — SaluteSpeech, Yandex SpeechKit, Deepgram выдают частичный текст уже во время загрузки. Параллельные запросы — модель не масштабируется бесконечно, нужен пул воркеров и очередь. Сетевой round-trip облачного STT добавляет 200–500 мс. Холодный старт Whisper — 3–7 секунд, держите процесс живым.

Сколько стоит голосовой Telegram-бот на 1000 пользователей?

При 1000 DAU, 3 voice по 15 секунд и 3 ответа по 200 символов в день. Облачный сценарий на Yandex SpeechKit: STT около 135 RUB в день, TTS около 240 RUB в день, итого примерно 11 000 RUB в месяц на распознавание и синтез. Плюс LLM (GPT-4o-mini) — примерно 1500–3000 RUB в день. Self-hosted на faster-whisper large-v3 + Silero TTS на одной GPU RTX 4090: аренда около 25 000 RUB в месяц, электричество около 10 000 RUB. Точка перелома между облаком и железом — 3000–5000 DAU.

Как соблюдать 152-ФЗ при работе с голосом в боте?

Голос — это биометрические персональные данные, специальная категория по 152-ФЗ. В политике конфиденциальности нужна отдельная строка про обработку голоса, цели и срок хранения. Требуется отдельное письменное согласие на обработку биометрии — в контексте бота это клик с явной формулировкой и логированием. С июня 2025 биометрия для коммерческих целей должна сдаваться в ГИС ЕБС или храниться с дополнительной сертификацией; проще не хранить аудио вообще. Передача голоса в OpenAI/Google/ElevenLabs = трансграничная передача ПДн с уведомлением РКН. Большинство студий выбирает Yandex SpeechKit или GigaAM именно поэтому.