Добрый день, думаю у каждого найдутся люди которые на сообщение с просьбой писать текстом отвечают голосовыми. В очередной раз получив голосовые я начал думать как же все-таки решить проблему, и в голову пришла простая идея, создать бота, который будет голосовое преобразовать в текст.
Так как задачу надо было решить максимально быстро в качестве языка программирования был выбран Python3 и несколько библиотек, которые упростили жизнь. Для работы с Telegram API был выбран pyTelegramBotAPI, а в качестве распознавания аудио в текст SpeechRecognition.
Создадим новую папку и откроем там терминал. Нам Нужно создать виртуальное окружение. Если у вас установлен virtualenv, то открываем терминал и вводим virualenv soundbot
Если нет вводим в терминал :
pip install virtualenv
Далее переходим в папку которая создалась то просто выбираем .cmd файл и кидаем его на окно терминала.
Далее по очереди выполняем установку двух модулей командами:
pip install SpeechRecognition
pip install pyTelegramBotAPI
Далее в любимом редакторе создаем главный файл бота с расширением .py В самом начале кода импортируем все библиотеки которые нам нужны.
import telebot
import uuid
import os
import speech_recognition as sr
Модуль telebot нужен для создания Telegram ботов на Python3. Модуль uuid является встроенным в Python3 и используется в данном случае для генерации случайного имени файла. Модуль os используется для запуска конвертации файлов из .ogg в .wav и модуль speech_recognition распознает голос и выдает текст на выходе. Давайте сейчас создадим переменные и инициализируем распознавание голоса в текст и создадим объект бота;
language='ru_RU'
TOKEN='xxxxxxxxxxxxxxxxxxxxxxxx'
bot = telebot.TeleBot(TOKEN)
r = sr.Recognizer()
Здесь объявлены самые главные переменные, language это переменная языка и отвечает за язык распознавания. Токен это токен бота который надо получить. Для этого открываем Telegram и ищем там @BotFather. Начинаем беседу с команды /new_bot и отвечаем на все вопросы бота. В самом последнем сообщении будет как раз токен который нам нужен.
def recognise(filename):
with sr.AudioFile(filename) as source:
audio_text = r.listen(source)
try:
text = r.recognize_google(audio_text,language=language)
print('Converting audio transcripts into text ...')
print(text)
return text
except:
print('Sorry.. run again...')
return "Sorry.. run again..."
В начале мы открываем наш аудиофайл, далее передаем это в r.recognize_google()
которая преобразует это в текст. Однако так как запись может быть низкого качества или просто файл может быть поврежден, Это будет означать что код может выдать исключение и как раз для вылавливания исключения здесь применен блок try/catch. А также обязательно в случае исключения выводится какое-то сообщение, так как мы получим ошибку если попытаемся отправить пустое сообщение.
Вот мы и добрались до основной функции бота которая срабатывает если есть кто-то отметивший бота и при этом сообщение является голосовым.
@bot.message_handler(content_types=['voice'])
def voice_processing(message):
filename = str(uuid.uuid4())
file_name_full="./voice/"+filename+".ogg"
file_name_full_converted="./ready/"+filename+".wav"
file_info = bot.get_file(message.voice.file_id)
downloaded_file = bot.download_file(file_info.file_path)
with open(file_name_full, 'wb') as new_file:
new_file.write(downloaded_file)
os.system("ffmpeg -i "+file_name_full+" "+file_name_full_converted)
text=recognise(file_name_full_converted)
bot.reply_to(message, text)
os.remove(file_name_full)
os.remove(file_name_full_converted)
Стоит обратить ваше внимание еще раз на то что данная функция срабатывает только если есть упоминание бота, и содержит голосовое сообщение. В самом начале мы создаем уникальное имя файла и сохраняем его в переменную. Далее мы создаем путь где будет храниться сам файл, то есть к имени файла добавляем папку где оно будет храниться. Далее создаем имя, но уже сконвертированного в нормальный формат который понятен распознавался текста. Далее вы скачиваем файл и сохраняем по недавно сгенерированному пути. Следующем шагом вы вызываем ffmpeg из консоли* и передаем ему два параметра file_name_full это где лежит исходный файл, а также file_name_full_converted это уже куда сохранить конвертированный файл. После этого вызываем функцию recognise()
которая преобразует наше аудио в текст. И остается дело за малым ответить на сообщение при помощи функции .reply_to()
и удалить оба аудио-файла.
Поздравляю мы почти уже у цели. Осталось запустить бота при запуске нашего файла. Для этого в конце нашего файла напишем: bot.polling()
Все можем сохранить файл и запустить его из консоли командой python3 вашеимяфайла.py
Если все сделано правильно, то в вашей группе бот должен преобразовать голосовые которых он отмечен:
Перед запуском создаем директории ready и voice.
Финальный код: (Спасибо @victoriously)
import telebot
import uuid
import os
import speech_recognition as sr
language='ru_RU'
TOKEN='YOUR_TOKEN'
#CHAT_ID='-100xxxxxxxxxxxxxxxxxxxxx')
bot = telebot.TeleBot(TOKEN)
r = sr.Recognizer()
def recognise(filename):
with sr.AudioFile(filename) as source:
audio_text = r.listen(source)
try:
text = r.recognize_google(audio_text,language=language)
print('Converting audio transcripts into text ...')
print(text)
return text
except:
print('Sorry.. run again...')
return "Sorry.. run again..."
@bot.message_handler(content_types=['voice'])
def voice_processing(message):
filename = str(uuid.uuid4())
file_name_full="./voice/"+filename+".ogg"
file_name_full_converted="./ready/"+filename+".wav"
file_info = bot.get_file(message.voice.file_id)
downloaded_file = bot.download_file(file_info.file_path)
with open(file_name_full, 'wb') as new_file:
new_file.write(downloaded_file)
os.system("ffmpeg -i "+file_name_full+" "+file_name_full_converted)
text=recognise(file_name_full_converted)
bot.reply_to(message, text)
os.remove(file_name_full)
os.remove(file_name_full_converted)
bot.polling()
UPD. Спасибо @victoriously за найденые ошибки в первой версии статьи. А так же за полный и рабочий код .
Комментарии (12)
victoriously
29.08.2021 18:56+4Есть несколько замечаний к вашей статье:
* Не хватает сравнения с уже существующими аналогами.
* Не хватает уже выложенного бота для собственной проверки
* Не хватает выложенного исходного кода, чтобы запустить бота :)
Ну и при попытке самостоятельно запустить его, возникло еще пару замечаний и проблем
* os.system выглядит как костыль. Почему бы не использовать ffmpeg библиотеку для питона?
* Зависимости проще было бы указать черезpip freeze > requirements.txt
* Зачем нам CHAT_ID, если дальше по коду мы его нигде не используем?
* Различные ошибки, в основном из-за того, что код в статье не полныйСами ошибки и их исправление
* Не хватает 1 строчки кода, взял её из примера в документации(venv) [root@vitka-k soundto]$ python soundto.py
Traceback (most recent call last):
File "soundto.py", line 38, in bot.polling()
File "/root/bots/soundto/venv/lib/python3.7/site-packages/telebot/__init__.py", line 622, in polling
self.__threaded_polling(non_stop, interval, timeout, long_polling_timeout, allowed_updates)
File "/root/bots/soundto/venv/lib/python3.7/site-packages/telebot/__init__.py", line 681, in __threaded_polling
raise e
File "/root/bots/soundto/venv/lib/python3.7/site-packages/telebot/__init__.py", line 644, in __threaded_polling
self.worker_pool.raise_exceptions()
File "/root/bots/soundto/venv/lib/python3.7/site-packages/telebot/util.py", line 130, in raise_exceptions
raise self.exception_info
File "/root/bots/soundto/venv/lib/python3.7/site-packages/telebot/util.py", line 82, in run
task(*args, **kwargs)
File "soundto.py", line 29, in voice_processing
downloaded_file = bot.download_file(file_info.file_path)
NameError: name 'file_info' is not defined
Исправляется добавление строчки перед использованием file_infofile_info = bot.get_file(message.voice.file_id)
* Питон жалуется на отсутствие директории voice и ready, создаем её вручную или через сам питонFileNotFoundError: [Errno 2] No such file or directory: './voice/aa9cc69a-26d6-4e43-a84e-99e367c47510.ogg'
Кто хочет потестировать — некоторое время будет работать @soundto_bot, дальше могу передать его автору, если он планирует развивать его.Полный кодimport telebot import uuid import os import speech_recognition as sr language='ru_RU' TOKEN='YOUR_TOKEN' #CHAT_ID='-100xxxxxxxxxxxxxxxxxxxxx') bot = telebot.TeleBot(TOKEN) r = sr.Recognizer() def recognise(filename): with sr.AudioFile(filename) as source: audio_text = r.listen(source) try: text = r.recognize_google(audio_text,language=language) print('Converting audio transcripts into text ...') print(text) return text except: print('Sorry.. run again...') return "Sorry.. run again..." @bot.message_handler(content_types=['voice']) def voice_processing(message): filename = str(uuid.uuid4()) file_name_full="./voice/"+filename+".ogg" file_name_full_converted="./ready/"+filename+".wav" file_info = bot.get_file(message.voice.file_id) downloaded_file = bot.download_file(file_info.file_path) with open(file_name_full, 'wb') as new_file: new_file.write(downloaded_file) os.system("ffmpeg -i "+file_name_full+" "+file_name_full_converted) text=recognise(file_name_full_converted) bot.reply_to(message, text) os.remove(file_name_full) os.remove(file_name_full_converted) bot.polling()
un1t
29.08.2021 22:15+2Google Cloud Speech-to-Text API платное с бесплатными лимитом 60 минут в месяц, каждый запрос округляется до 15 секунд.
Меня удивило, что этот кусок кода сработал без ключа
text = r.recognize_google(audio_text,language=language)
посмотрел исходники там написано что нужно передать key, если key is None то используется ключ по умолчанию зашитый в функции и нет гарантии что это будет работать
AlexZas20 Автор
30.08.2021 19:21Спасибо огромное. По ошибке удалил ее когда писал статью . Однако есть версия с подключеным configparser и немного другим кодом на github . Можно взять как отправную точку: https://github.com/alex5250/TelegramSoundBot
sneg2015
29.08.2021 23:00-2Может вопрос глупый, но объясните
Будет ли бот работать на телефоне? И если да, то что необходимо установить, ведь код должен в чем то обрабатываться.
Flexoplus
19.09.2021 00:54У меня вопрос зачем нужен такой бот, если на Андроиде есть уже голосовая клавиатура?
AlexZas20 Автор
19.09.2021 00:57Отличный вопрос, однако не все умеют ей пользоваться. Мне намного легче научить компьютер обрабатывать голос, чем объяснить людям как правильно общаться. Особенно сложно если эти люди твои знакомые /друзья (не в обиду им) .
centralhardware
Voicy существует уже миллион лет и делает то же самое, если уж нужна была более качественная альтернатива то и писать стоило, что то качественное.
AlexZas20 Автор
Спасибо , не знал .
dobergroup
Ну, не все пустят чужого бота в свою группу. Хотя, для тех, кто об этом задумывается - вряд ли актуальна проблема голосовых сообщений