AincOlGon's picture
Added app.py
595cff0 verified
import speech_recognition as sr
from pydub import AudioSegment
import os
import gradio as gr
import types
import typing
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
def convert_wav_to_text(audio_file_path: str) -> str:
"""
Эта функция получает на вход файл, который который представляет собой аудио. Если формат .wav, то такой файл сразу распознаётся.
А если формат отличается от .wav, то такой аудиофайл сначала конвертируется во временное представление .wav, распознаётся и удаляется.
Args:
audio_file_path (Str): Путь к файлу-голосовому сообщению.
Returns:
text_from_audio (Str): Текст, полученный из голосового сообщения.
error (Str): Сообщение об ошибке.
"""
file_extension = audio_file_path.split('.')[-1].lower() #получаем формат файла
try: #блок для отлова возможных ошибок
if file_extension != 'wav': #если формат не .wav
audio = AudioSegment.from_file(audio_file_path, format=file_extension) #загружаем аудиофайл с указанием его формата
audio = audio.set_channels(1).set_frame_rate(16000) #преобразуем аудио в моно (1 канал) и устанавливаем частоту дискретизации 16000 герц (необходимо для улучшения качества распознавания речи)
temp_wav_path = 'temp.wav' #определяем временный путь для сохранения преорбазованногоаудиофайла в формате .wav
audio.export(temp_wav_path, format='wav') #экспортируем преобразованное аудио в формат .wav и сохраняем по временному пути
else: #иначе
temp_wav_path = audio_file_path #просто сохраняем аудиофайл
recognizer = sr.Recognizer() #создаём объект-распознаватель речи
with sr.AudioFile(temp_wav_path) as source: #открываем аудиофайл
audio_data = recognizer.record(source) #и записываем его содержимое
try: #блок для отлова возможных ошибок
text_from_audio = recognizer.recognize_google(audio_data, language='ru-RU') #пробуем преобразовать данные аудиофайла с помощью сервисов Google
return text_from_audio #возвращаем полученный текст
except sr.UnknownValueError: #если ошибка связана с речью или шумом
error_str = 'Не удалось распознать аудио! Возможно, в данных слишком много шума.' #то создаём сообщение-ошибку
return error_str #и печатаем его
except sr.RequestError as e: #если ошибка при запросе
error_str = f'Возникла неожиданная ошибка: {e}' #то создаём сообщение-ошибку
return error_str #и печатаем его
finally: #этот блок выполняется независимо от наличия ошибок
if file_extension != 'wav' and os.path.exists('temp.wav'): #если есть воеменный файл temp.wav (который создаётся для перезаписывания аудиофайла)
os.remove('temp.wav') #то удаляем этот файл
def recognize_speech_from_microphone(audio: typing.Union[str, types.NoneType, AudioSegment]) -> str:
"""
Функция, которая записывает аудио.
Args:
audio (Str): Путь к аудиофайлу (загруженный файл).
audio (types.NoneType): Появляется при смене типа входных данных.
audio (AudioSegment): При записи звука микрофоном.
Return:
text_from_audio (Str): Результат выполнения функции convert_wav_to_text().
warning_str (Str): Предупреждение при смене типа входных данных.
"""
if isinstance(audio, str): #если входящие данные - путь к файлу (а не записанный звук с микрофона)
audio_file_path = audio #то сразу передаём путь без экспорта
elif isinstance(audio, types.NoneType): #если входящие данные без типа (пользователь кликнул по смене типа входящих данных)
warning_str = 'Вы изменили источник входных данных. Запишите звук или загрузите файл.' #то создаём сообщение-предупреждение
return warning_str #и печатаем его
else: #иначе (пользователь записывает звук микрофоном)
audio_file_path = 'temp_input.wav' #задаём имя файлу
audio.export(audio_file_path, format='wav') #конвертируем в .wav-формат
return convert_wav_to_text(audio_file_path) #передаём в функцию-распознаватель
gui = gr.Interface( #создаём пользовательский интерфейс gradio
fn=recognize_speech_from_microphone, #функция, которая вызывается при записи аудио
inputs=gr.Audio(type='filepath'), #входной компонент для записи аудио с микрофона устройства
outputs='text', #выходной компонент для отображения текста
live=True #позволяет запускаться и работать в реальном времени
)
if __name__ == '__main__':
gui.launch(share=True) #запускаем страницу и локально, и публично