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) #запускаем страницу и локально, и публично
|