Added app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import speech_recognition as sr
|
| 3 |
+
from pydub import AudioSegment
|
| 4 |
+
import os
|
| 5 |
+
import gradio as gr
|
| 6 |
+
import types
|
| 7 |
+
import typing
|
| 8 |
+
import logging
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def convert_wav_to_text(audio_file_path: str) -> str:
|
| 15 |
+
"""
|
| 16 |
+
Эта функция получает на вход файл, который который представляет собой аудио. Если формат .wav, то такой файл сразу распознаётся.
|
| 17 |
+
А если формат отличается от .wav, то такой аудиофайл сначала конвертируется во временное представление .wav, распознаётся и удаляется.
|
| 18 |
+
|
| 19 |
+
Args:
|
| 20 |
+
audio_file_path (Str): Путь к файлу-голосовому сообщению.
|
| 21 |
+
Returns:
|
| 22 |
+
text_from_audio (Str): Текст, полученный из голосового сообщения.
|
| 23 |
+
error (Str): Сообщение об ошибке.
|
| 24 |
+
"""
|
| 25 |
+
file_extension = audio_file_path.split('.')[-1].lower() #получаем формат файла
|
| 26 |
+
try: #блок для отлова возможных ошибок
|
| 27 |
+
if file_extension != 'wav': #если формат не .wav
|
| 28 |
+
audio = AudioSegment.from_file(audio_file_path, format=file_extension) #загружаем аудиофайл с указанием его формата
|
| 29 |
+
audio = audio.set_channels(1).set_frame_rate(16000) #преобразуем аудио в моно (1 канал) и устанавливаем частоту дискретизации 16000 герц (необходимо для улучшения качества распознавания речи)
|
| 30 |
+
temp_wav_path = 'temp.wav' #определяем временный путь для сохранения преорбазованногоаудиофайла в формате .wav
|
| 31 |
+
audio.export(temp_wav_path, format='wav') #экспортируем преобразованное аудио в формат .wav и сохраняем по временному пути
|
| 32 |
+
else: #иначе
|
| 33 |
+
temp_wav_path = audio_file_path #просто сохраняем аудиофайл
|
| 34 |
+
recognizer = sr.Recognizer() #создаём объект-распознаватель речи
|
| 35 |
+
with sr.AudioFile(temp_wav_path) as source: #открываем аудиофайл
|
| 36 |
+
audio_data = recognizer.record(source) #и записываем его содержимое
|
| 37 |
+
try: #блок для отлова возможных ошибок
|
| 38 |
+
text_from_audio = recognizer.recognize_google(audio_data, language='ru-RU') #пробуем преобразовать данные аудиофайла с помощью сервисов Google
|
| 39 |
+
return text_from_audio #возвращаем полученный текст
|
| 40 |
+
except sr.UnknownValueError: #если ошибка связана с речью или шумом
|
| 41 |
+
error_str = 'Не удалось распознать аудио! Возможно, в данных слишком много шума.' #то создаём сообщение-ошибку
|
| 42 |
+
return error_str #и печатаем его
|
| 43 |
+
except sr.RequestError as e: #если ошибка при запросе
|
| 44 |
+
error_str = f'Возникла неожиданная ошибка: {e}' #то создаём сообщение-ошибку
|
| 45 |
+
return error_str #и печатаем его
|
| 46 |
+
finally: #этот блок выполняется независимо от наличия ошибок
|
| 47 |
+
if file_extension != 'wav' and os.path.exists('temp.wav'): #если есть ��оеменный файл temp.wav (который создаётся для перезаписывания аудиофайла)
|
| 48 |
+
os.remove('temp.wav') #то удаляем этот файл
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def recognize_speech_from_microphone(audio: typing.Union[str, types.NoneType, AudioSegment]) -> str:
|
| 52 |
+
"""
|
| 53 |
+
Функция, которая записывает аудио.
|
| 54 |
+
|
| 55 |
+
Args:
|
| 56 |
+
audio (Str): Путь к аудиофайлу (загруженный файл).
|
| 57 |
+
audio (types.NoneType): Появляется при смене типа входных данных.
|
| 58 |
+
audio (AudioSegment): При записи звука микрофоном.
|
| 59 |
+
Return:
|
| 60 |
+
text_from_audio (Str): Результат выполнения функции convert_wav_to_text().
|
| 61 |
+
warning_str (Str): Предупреждение при смене типа входных данных.
|
| 62 |
+
"""
|
| 63 |
+
if isinstance(audio, str): #если входящие данные - путь к файлу (а не записанный звук с микрофона)
|
| 64 |
+
audio_file_path = audio #то сразу передаём путь без экспорта
|
| 65 |
+
elif isinstance(audio, types.NoneType): #если входящие данные без типа (пользователь кликнул по смене типа входящих данных)
|
| 66 |
+
warning_str = 'Вы изменили источник входных данных. Запишите звук или загрузите файл.' #то создаём сообщение-предупреждение
|
| 67 |
+
return warning_str #и печатаем его
|
| 68 |
+
else: #иначе (пользователь записывает звук микрофоном)
|
| 69 |
+
audio_file_path = 'temp_input.wav' #задаём имя файлу
|
| 70 |
+
audio.export(audio_file_path, format='wav') #конвертируем в .wav-формат
|
| 71 |
+
return convert_wav_to_text(audio_file_path) #передаём в функцию-распознаватель
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
gui = gr.Interface( #создаём пользовательский интерфейс gradio
|
| 75 |
+
fn=recognize_speech_from_microphone, #функция, которая вызывается при записи аудио
|
| 76 |
+
inputs=gr.Audio(type='filepath'), #входной компонент для записи аудио с микрофона устройства
|
| 77 |
+
outputs='text', #выходной компонент для отображения текста
|
| 78 |
+
live=True #позволяет запускаться и работать в реальном времени
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
if __name__ == '__main__':
|
| 83 |
+
gui.launch(share=True) #запускаем страницу и локально, и публично
|