Всем привет! Недавно вдохновилась всякими ботами в тгшке и решила для будущего портфолио сделать своего первого бота + подумала, что может быть это будет полезно кому-то из вас :-)

В этой статье разберём теоретические основы (базу) для его создания и сам код с понятными комментариями к нему.

Что такое API, TOKEN и с чем их едят?

Т.к. в данной статье будет создаваться телеграмм бот, то нужно чуть больше узнать про API.
API (Application Programming Interface) - программный интерфейс приложения. То есть, набор способов и правил, по которым различные программы общаются между собой и обмениваются данными.

Именно в качестве ТГ-бота работа апишки выглядит так:
Наше пайтон приложение отсылает токен, название функции, параметры (адресат, данные) на сервер телеграмм.
А сервер телеграмм уже присылает в наше приложение входящие сообщения (отправитель, данные).

Визуализация взаимодейтсвия API с клиентом API
Визуализация взаимодейтсвия API с клиентом API

Зачем регать бота через токен? По сути это как паспорт, чтобы наше приложение понимало к какому именно боту идёт привязка. В общем, уникальный идентификатор. Самое главное - никому не сообщать ваш токен.

С этими приколами разобрались, переходим к коду!

Разработка бота и разбор кода

Думаю, все понимают, что для нормальных проектов нужно использовать библиотеки. С первого же сайта можно найти определение:

Библиотека (или модуль) в Python — это файл с кодом, содержащий функции, классы и переменные, которые вы можете использовать в своих программах.

Если мы используем библиотеку, то обязательно в коде нужно сказать окружению что именно мы собираемся заюзать.
Делается это так: import имя_пакета

Если же пакет не входит в стандартный набор, то его можно скачать с помощью команды: pip install имя_пакета

Итак, для начала нам нужно сделать несколько импортов, каждый из них объяснён в комментарии.

import os
import telebot
import speech_recognition # Преобразование голоса в текст (базаримся на готовенькое от Гугла)
from pydub import AudioSegment # Обработка аудиофайла, который присылает пользователь

Обязательно устанавливаем все эти библиотеки (я делала установку через cmd): pip install pydub telebot SpeechRecognition

ВАЖНО ПРИМЕЧАНИЕ!!

Для работы библиотеки pydub ОБЯЗАТЕЛЬНО нужен скачанный ffmpeg. Без него чуть ли не все функции pydub не будут работать (увы)

И чуть не забыла! Нашего бота надо создать в самом телеграмме через BotFather. Работа с ним показана ниже.

Создание нового бота
Создание нового бота
Выбор юза для бота и получение заветного токена
Выбор юза для бота и получение заветного токена

Абсолютно во всех тг-ботах при создании чуть ли не первой строчкой после импортов идёт token = 'ваш токен из BotFather'

Объект - это составная переменная, к которой привязан набор атрибутов и функций.
Сам бот представляет собой объект, а токен является его обязательным атрибутом.

bot = telebot.TeleBot(token) . В этой части кода мы запускаем бота и даём ему запомнить токен.

Теперь приступаем к написанию функций. Всего их будет три штуки:

  • def ogg2wav(filename) - перевод голосового сообщения из формата .ogg в формат .wav, с которыми удобнее работать.

  • def recognize_speech(ogg_filename) - перевод голоса в текст с помощью библиотеки SpeechRecognition + реализация удаления использованных файлов, чтобы память не засорять бллин.

  • def download_file(bot, file_id) - скачивание голосового сообщения, которое прислал пользователь.

Начнём с первой функции конвертации голосового сообщения. Вот так она выглядит:

def ogg2wav(filename):

    new_filename = filename.replace('.ogg', '.wav')

    audio = AudioSegment.from_file(filename)

    audio.export(new_filename, format='wav')

    return new_filename

Как это работает:

  1. Замена расширения:
    Создаёт имя для нового файла, заменяя .ogg на .wav (например, voice.oggvoice.wav).

  2. Чтение и конвертация:
    Использует библиотеку pydub для загрузки OGG-файла и преобразования данных в аудиопоток.

  3. Экспорт результата:
    Сохраняет конвертированные данные как WAV-файл с 16-битной глубиной и частотой дискретизации исходника (стандарт для Telegram-голосовых сообщений).

Ретурнит (возвращает):
Путь к созданному wav-файлу для нашей дальнейшей обработки.

Дальше уже функция, которая работает с нашим созданным wav-файлом. Вот как она выглядит:

def recognize_speech(ogg_filename):

    wav_filename = ogg2wav(ogg_filename)

    recognizer = speech_recognition.Recognizer()

    with speech_recognition.WavFile(wav_filename) as source:

        wav_audio = recognizer.record(source)

    text = recognizer.recognize_google(wav_audio, language='ru')

    if os.path.exists(ogg_filename):

        os.remove(ogg_filename)

    if os.path.exists(wav_filename):

        os.remove(wav_filename)

    return text 

Как это работает:

  1. Конвертация в WAV:
    Сначала вызывает ogg2wav() для преобразования входного OGG-файла в WAV-формат (необходим для библиотек распознавания).

  2. Распознавание речи:

    • Создает объект-распознаватель speech_recognition.Recognizer()

    • Читает аудиоданные из wav-файла

    • Отправляет данные в Google Speech Recognition API с указанием русского языка (language='ru')

  3. Очистка ресурсов:
    Удаляет как исходный OGG-файл, так и временный WAV-файл после обработки (чтобы избежать накопления данных).

Ретурнит жоско:
Распознанный текст в виде строки.

И теперь самая важна функция, с которой, по сути, и должен начинать работу наш бот. Вот её код:

def download_file(bot, file_id):

    file_info = bot.get_file(file_id)

    downloaded_file = bot.download_file(file_info.file_path)

    filename = file_id + file_info.file_path

    filename = filename.replace('/','_') #Чтобы ошибок с косой чертой не было бллин

    with open(filename, 'wb') as f:

        f.write(downloaded_file)

    return filename

Как это работает:

  1. Получение метаданных:
    Через bot.get_file() получает информацию о файле (путь, размер и т.д.) по его идентификатору file_id.

  2. Скачивание контента:
    Использует bot.download_file() для загрузки бинарных данных файла.

  3. Генерация имени файла:

    • Комбинирует file_id и оригинальное имя файла для уникальности

    • Важно: Заменяет / на _ в имени (чтобы избежать ошибок создания поддиректорий)

  4. Сохранение:
    Записывает бинарные данные в локальный файл в режиме wb (raw byte-запись).

Ретурн:
Имя сохранённого файла (например: AwBD...xyz_voice.ogg)

Теперь осталось только прописать логику работы бота. По базе, начинаем с обработчика дефолт команды /start, которую вводим при запуске бота. В моём случае на это сообщение он будет просить пользователя прислать ему голосовое собщение. Код выглядит следующим образом:

@bot.message_handler(commands=['start'])

def say_hi(message):

    bot.send_message(message.chat.id, 'Привет! Отправь мне голосовое, чтобы я его расшифровал в текст йоооу')

И, самое главное - сердце нашего goofy ahh бота, а именно поочерёдность выполнения функций. Тут много комментировать не буду, т.к. все приколы написаны были ранее :)

@bot.message_handler(content_types=['voice']) #Бот реагирует на голос, поэтому пишем voice

def transcript(message):

    filename = download_file(bot, message.voice.file_id) #Скачиваем голосовуху

    text = recognize_speech(filename) #Преобразуем её в вав-файл + расшифровываем

    response = f"? Вот расшифровка вашего голосового сообщения:\n\n{text}" #Форматируем, чтобы на выходе пользователь получил не пустую расшифровку, а хоть какую-то красоту

    bot.send_message(message.chat.id, response) #Отправляем ответ пользователю :)

И теперь пишем самую последнюю команду, которая запускает нашего бота (не дай боже вы напишите её в предыдущую функцию друзья) - bot.polling()

Вот и всё! Наш бот готов трудиться на благо человечества. К сожалению, дать его юз, чтобы вы проверили я не могу, т.к. не размещала его на сервере для работы 24/7. Поэтому прикрепляю скромный скриншот, где видно, что всё работает!

Работа тг-бота
Работа тг-бота

Полный код к данному приколу есть на моём гитхабе по ссылке.

Всем спасибо, кто прочитал статью! Надеюсь это кому-то поможет. Если будут какие-то комментарии/предложения по улучшению/поправки - пишите, всегда буду рада почитать :)

Комментарии (3)


  1. pol_pot
    19.08.2025 07:42

    Тут можно взять почти безлимитный очень быстрый и стабильный whisper https://console.groq.com

    Ему не нужно будет конвертировать звук, он поддерживает большинство форматов и так

    Скрытый текст

    Размер модели: Оптимизированная архитектура для скорости

    Скорость: Фактор скорости 216x

    Аудиоконтекст: Оптимизирован для 30-секундных аудиосегментов, с минимумом 10 секунд на сегмент

    Поддерживаемое аудио: FLAC, MP3, M4A, MPEG, MPGA, OGG, WAV или WEBM

    Язык: Поддерживается более 99 языков

    И там же можно взять ллм что бы добавить немного магии, переписать полученный после транскрибации текст, добавить переносы строк итп.

    Легким движением руки телебота можно сделать "асинхронным" так что бы долгое выполнение команды не блокировало бота и он мог делать несколько запросов одновременно

    добавить декоратор перед хендлерами

    def async_run_with_limit(max_threads: int):
        """
        Decorator to run a function in a separate thread asynchronously,
        with a limit on the number of concurrent threads.
    
        Args:
            max_threads: The maximum number of threads allowed to run concurrently.
        """
        semaphore = threading.Semaphore(max_threads)
    
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kwargs):
                def task():
                    try:
                        func(*args, **kwargs)
                    finally:
                        semaphore.release()
    
                semaphore.acquire()
                thread = threading.Thread(target=task)
                thread.start()
                return thread  # Optionally return the thread object
            return wrapper
        return decorator


  1. pol_pot
    19.08.2025 07:42

    Сохранять на диск скаченный файл не обязательно, можно скачать его в оперативку и так использовать.


  1. EmmaShpedt
    19.08.2025 07:42

    Вообще штука удобная - получать таким образом текст. Спасибо за экономию времени.