AincOlGon commited on
Commit
f8f89e3
·
1 Parent(s): 15a4325

Added app.py and requirements.txt

Browse files
Files changed (2) hide show
  1. app.py +91 -0
  2. requirements.txt +3 -0
app.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import os
3
+ import wave
4
+ from pydub import AudioSegment
5
+ from vosk import Model, KaldiRecognizer
6
+ import gradio as gr
7
+ import typing
8
+ import types
9
+ import logging
10
+
11
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
12
+
13
+
14
+ def print_file_info(file_path: str) -> None:
15
+ """
16
+ Данная функция печатает информацию об аудиофайле: количество каналов, ширину выборки, частоту и общее количестов фрагментов.
17
+
18
+ Args:
19
+ file_path (Str): Путь к файлу, который проверяем.
20
+ """
21
+ with wave.open(file_path, 'rb') as wf: #открытие .wav файла в бинарном формате для чтения
22
+ print(f'Channels: {wf.getnchannels()}, Sample Width: {wf.getsampwidth()}, Frame Rates: {wf.getframerate()}, Frames: {wf.getnframes()}') #получение всех данных
23
+
24
+
25
+ def convert_wav_to_text(audio_file_path: str) -> str:
26
+ """
27
+ Данная функция конвертирует любой входящий аудиофайл в .wav формат, после чего распознаёт его с помощью модели Vosk и возвращает либо текст, либо ошибку.
28
+
29
+ Args:
30
+ audio_file_path (Str): Получаемый аудиофайл любого формата.
31
+ Returns:
32
+ text_from_audio (Str): Данные файла в текстовом формате.
33
+ error (Str): Какая-то ошибка.
34
+ """
35
+ file_extension = audio_file_path.split('.')[-1].lower() #получение формата файла
36
+ temp_wav_path = 'temp.wav' #создание временного файла для обработки
37
+ try: #блок для отлова возможных ошибок
38
+ audio = AudioSegment.from_file(audio_file_path, format=file_extension) #получение данных из файла
39
+ audio = audio.set_channels(1).set_sample_width(2).set_frame_rate(16000) #принудительная установка параметров
40
+ audio.export(temp_wav_path, format='wav') #конвертация в .wav формат
41
+ print_file_info(temp_wav_path) #проверяем параметры файла
42
+ if not os.path.exists('model/vosk-model-ru-0.42'): #если не существует папка с моделью
43
+ raise FileNotFoundError('Проверьте наличие обученной модели Vosk в папке model!') #то показываем ошибку
44
+ model = Model('model/vosk-model-ru-0.42') #получаем предобученную модель для распознавания
45
+ recognizer = KaldiRecognizer(model, 16000) #объявление объекта-распознавателя
46
+ with wave.open(temp_wav_path, 'rb') as wave_file: #открытие .wav файла в бинарном формате для чтения
47
+ if wave_file.getnchannels() != 1 or wave_file.getsampwidth() != 2 or wave_file.getframerate() != 16000: #если файл не прошёл проверку параметров
48
+ raise ValueError('Проверьте файл, он должен быть в формате .wav с 1 каналом, 16-bit и 16000 Hz!') #то показываем ошибку
49
+ recognizer.AcceptWaveform(wave_file.readframes(wave_file.getnframes())) #распознавание файла
50
+ result = recognizer.Result() #получение результата распознавания
51
+ text_from_audio = result.split('"text" : ')[1].strip('} \n"') #форматируем вывод, а то там словарь на выходе
52
+ return text_from_audio #возвращаем текст сообщения
53
+ except Exception as e: #если какая-то шелуха
54
+ return f'Возникла неожиданная ошибка: {e}' #то показываем ошибку
55
+ finally: #этот блок выполняется в любом случае
56
+ if os.path.exists(temp_wav_path): #если есть временный файл
57
+ os.remove(temp_wav_path) #то сносим его нафиг, чтобы место не занимал
58
+
59
+
60
+ def recognize_speech_from_microphone(audio: typing.Union[str, types.NoneType, AudioSegment]) -> str:
61
+ """
62
+ Функция, которая записывает аудио.
63
+
64
+ Args:
65
+ audio (Str): Путь к аудиофайлу (загруженный файл).
66
+ audio (types.NoneType): Появляется при смене типа входных данных.
67
+ audio (AudioSegment): При записи звука микрофоном.
68
+ Return:
69
+ text_from_audio (Str): Результат выполнения функции convert_wav_to_text().
70
+ warning_str (Str): Предупреждение при смене типа входных данных.
71
+ """
72
+ if isinstance(audio, str): #если входящие данные - путь к файлу (а не записанный звук с микрофона)
73
+ audio_file_path = audio #то сразу передаём путь без экспорта
74
+ elif isinstance(audio, types.NoneType): #если входящие данные без типа (пользователь кликнул по смене типа входящих данных)
75
+ warning_str = 'Вы изменили источник входных данных. Запишите звук или загрузите файл.' #то создаём сообщение-предупреждение
76
+ return warning_str #и печатаем его
77
+ else: #иначе (пользователь записывает звук микрофоном)
78
+ audio_file_path = 'temp_input.wav' #задаём имя файлу
79
+ audio.export(audio_file_path, format='wav') #конвертируем в .wav-формат
80
+ return convert_wav_to_text(audio_file_path) #передаём в функцию-распознаватель
81
+
82
+
83
+ gui = gr.Interface( #создаём пользовательский интерфейс gradio
84
+ fn=recognize_speech_from_microphone, #функция, которая вызывается при записи аудио
85
+ inputs=gr.Audio(type='filepath'), #входной компонент для записи аудио с микрофона устройства
86
+ outputs='text', #выходной компонент для отображения текста
87
+ live=True #позволяет запускаться и работать в реальном времени
88
+ )
89
+
90
+ if __name__ == '__main__':
91
+ gui.launch(share=True)
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ pydub
2
+ vosk
3
+ gradio