Telegram Бот #Wonder , который сможет распозновать голосовые сообщения
Голосовые сообщения стали частью нашей жизни. Их используют как в личном, так и в деловом общении. Это экономит время, ведь записать сообщение просто и это быстрее, чем набор текста.
Чаще всего голосовыми сообщениями обмениваются в Telegram. Этот мессенджер сейчас особенно популярен и функционал хорошо подходит для использования аудио формата. Можно с помощью смартфона записать короткое аудио друзьям или надиктовать голосом объемный текст для публичного канала. Самое начало без выделения последней.
from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher
from aiogram.utils import executor
from converter import Converter
from pathlib import Path
import soundfile
import os
Следующий выбор пал на модель whisper от все того же OpenAI. На мой взгляд, этот сервис работает значительно лучше. Во-первых, нет ограничения на длительность файла, только на размер - не больше 25 мб (а этого с головой хватит даже для очень больших голосовых). Во-вторых, нет необходимости передавать исходный язык - whisper автоматически его определяет и отдает результат строкой. Тестировались: английский, турецкий, украинский, русский, испанский. Качество распознавания очень хорошее и, на мой субъективный взгляд, лучше, чем у аналогичного сервиса от Яндекс. В-третьих, whisper понимает, когда человек делает паузы, задает вопросы, восклицает, поэтому в ответ он отдает размеченный текст с пунктуацией. Благодаря этому визуально текст выглядит значительно приятнее. И наконец, последний аргумент в пользу whisper - цена. Он кратно дешевле. После двух строк
async def handle_file(file: types.File, file_name: str, path: str):
Path(f"{path}").mkdir(parents=True, exist_ok=True)
await bot.download_file(file_path=file.file_path, destination=f"{path}/{file_name}")
Я очень хотел сделать на стороне бота подсчет затрат, чтобы видеть статистику использования, поэтому так неизящно приходится вызывать ffmpeg для того, чтобы захватить stdout и затем регулярным выражением вытащить длительность аудио.
Для того, чтобы получить распознанный текст сообщения, сделаем запрос к API после последнего @dp ДО if name:
@dp.message_handler(content_types=[types.ContentType.VOICE])
async def echo_message(msg: types.Message):
voice = await msg.voice.get_file()
path = "/home/ubuntu/demo_bot"
await handle_file(file=voice, file_name=f"{voice.file_id}.ogg", path=path)
full_path = f"{path}/{voice.file_id}.ogg"
data, samplerate = soundfile.read(full_path)
soundfile.write(f"{full_path}.wav", data, samplerate)
converter = Converter(f"{full_path}.wav")
message_text = converter.audio_to_text()
os.remove(full_path)
del converter
await bot.send_message(msg.from_user.id, message_text)
К сожалению, сервис от OpenAI в частности chat/completions нельзя назвать стабильным. Несколько раз в день я получаю сообщение об ошибке, где он возвращает json с текстом, что сервис временно недоступен. Также на практике оказалось, что ± 60% сообщений после распознавания остаются короткими, длиной не больше 200-300 символов. Решил, что будем использовать ChatGPT только для действительно длинных сообщений (>300 символов), а для небольших будем просто отдавать оригинальный текст.
Для короткого голосового converter.py:
import speech_recognition as sr
import os
class Converter:
def __init__(self, path_to_file: str, language: str = "ru-RU"):
self.language = language
self.wav_file = path_to_file
def audio_to_text(self) -> str:
r = sr.Recognizer()
with sr.AudioFile(self.wav_file) as source:
audio = r.record(source)
r.adjust_for_ambient_noise(source)
return r.recognize_google(audio, language=self.language)
def __del__(self):
os.remove(self.wav_file)