Назад к блогу
8 минНаговори

Создайте Telegram-бота для транскрипции за 30 минут

telegramтуториалpythonбот

Создайте Telegram-бота для транскрипции за 30 минут

В этом руководстве вы создадите Telegram-бота, который расшифровывает голосовые сообщения и аудиофайлы через API Наговори. Бот получает голосовое сообщение, отправляет его на транскрипцию и отвечает текстом.

Что понадобится

  • Python 3.10+
  • Токен Telegram-бота от @BotFather
  • API-ключ Наговори (создайте в Профиле)

Установка

Установите зависимости:

pip install python-telegram-bot requests

Задайте переменные окружения:

export TELEGRAM_BOT_TOKEN="токен-вашего-бота"
export NAGOVORI_API_KEY="nag_ваш_ключ"

Код

Создайте файл bot.py:

import os
import time
import tempfile
import requests
from telegram import Update
from telegram.ext import Application, MessageHandler, filters, ContextTypes

TELEGRAM_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
API_KEY = os.environ["NAGOVORI_API_KEY"]
BASE_URL = "https://api.nagovori.ru/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}


async def handle_voice(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Обработка голосовых сообщений и аудиофайлов."""
    message = update.message
    if not message:
        return

    # Получаем файл из Telegram
    if message.voice:
        file = await message.voice.get_file()
        filename = "voice.ogg"
        content_type = "audio/ogg"
    elif message.audio:
        file = await message.audio.get_file()
        filename = message.audio.file_name or "audio.mp3"
        content_type = message.audio.mime_type or "audio/mpeg"
    elif message.document and message.document.mime_type and \
         message.document.mime_type.startswith("audio/"):
        file = await message.document.get_file()
        filename = message.document.file_name or "audio.mp3"
        content_type = message.document.mime_type
    else:
        return

    await message.reply_text("Расшифровываю... подождите.")

    # Скачиваем из Telegram
    with tempfile.NamedTemporaryFile(suffix=".ogg", delete=False) as tmp:
        await file.download_to_drive(tmp.name)
        file_size = os.path.getsize(tmp.name)

        # 1. Получаем presigned URL
        presign = requests.post(
            f"{BASE_URL}/uploads/presign",
            headers=HEADERS,
            json={
                "filename": filename,
                "content_type": content_type,
                "size_bytes": file_size,
            },
        ).json()

        # 2. Загружаем в Наговори
        with open(tmp.name, "rb") as audio:
            requests.put(
                presign["upload_url"],
                data=audio,
                headers={"Content-Type": content_type},
            )

    os.unlink(tmp.name)

    # 3. Создаём транскрипцию
    job = requests.post(
        f"{BASE_URL}/transcriptions",
        headers=HEADERS,
        json={
            "object_key": presign["object_key"],
            "filename": filename,
            "content_type": content_type,
            "size_bytes": file_size,
            "language": "auto",
        },
    ).json()

    # 4. Ожидаем результат
    while job["status"] in ("queued", "processing"):
        time.sleep(2)
        job = requests.get(
            f"{BASE_URL}/transcriptions/{job['id']}",
            headers=HEADERS,
        ).json()

    if job["status"] == "completed":
        text = job["transcript_text"]
        # Ограничение Telegram — 4096 символов
        for i in range(0, len(text), 4000):
            await message.reply_text(text[i:i + 4000])
    else:
        error = job.get("error_message", "Неизвестная ошибка")
        await message.reply_text(f"Транскрипция не удалась: {error}")


def main():
    app = Application.builder().token(TELEGRAM_TOKEN).build()
    app.add_handler(MessageHandler(
        filters.VOICE | filters.AUDIO | filters.Document.AUDIO,
        handle_voice,
    ))
    print("Бот запущен. Слушаю голосовые сообщения...")
    app.run_polling()


if __name__ == "__main__":
    main()

Запуск

python bot.py

Отправьте голосовое сообщение боту — он ответит расшифрованным текстом в течение нескольких секунд.

Развёртывание

Для production рекомендуем:

  • Webhook вместо polling для меньшей задержки
  • Асинхронное ожидание с asyncio вместо time.sleep
  • Обработка ошибок с логикой повторов для API
  • Docker для удобного деплоя

Пример Docker

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY bot.py .
CMD ["python", "bot.py"]

Расширение бота

Идеи для улучшений:

  • Команда /lang для выбора языка распознавания
  • Поддержка видеосообщений (извлечение аудиодорожки)
  • Команда /summary для AI-резюме
  • Хранение истории транскрипций в базе данных
  • Inline-режим для расшифровки пересланных голосовых

Стоимость

Каждое голосовое сообщение расходует ваш баланс минут Наговори. Типичное минутное голосовое сообщение использует 1 минуту баланса. Проверяйте остаток в Профиле.