Vosk-in-Russian / app.py
AincOlGon's picture
Added app.py and requirements.txt
f8f89e3
raw
history blame
8.89 kB
import os
import wave
from pydub import AudioSegment
from vosk import Model, KaldiRecognizer
import gradio as gr
import typing
import types
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
def print_file_info(file_path: str) -> None:
"""
Данная функция печатает информацию об аудиофайле: количество каналов, ширину выборки, частоту и общее количестов фрагментов.
Args:
file_path (Str): Путь к файлу, который проверяем.
"""
with wave.open(file_path, 'rb') as wf: #открытие .wav файла в бинарном формате для чтения
print(f'Channels: {wf.getnchannels()}, Sample Width: {wf.getsampwidth()}, Frame Rates: {wf.getframerate()}, Frames: {wf.getnframes()}') #получение всех данных
def convert_wav_to_text(audio_file_path: str) -> str:
"""
Данная функция конвертирует любой входящий аудиофайл в .wav формат, после чего распознаёт его с помощью модели Vosk и возвращает либо текст, либо ошибку.
Args:
audio_file_path (Str): Получаемый аудиофайл любого формата.
Returns:
text_from_audio (Str): Данные файла в текстовом формате.
error (Str): Какая-то ошибка.
"""
file_extension = audio_file_path.split('.')[-1].lower() #получение формата файла
temp_wav_path = 'temp.wav' #создание временного файла для обработки
try: #блок для отлова возможных ошибок
audio = AudioSegment.from_file(audio_file_path, format=file_extension) #получение данных из файла
audio = audio.set_channels(1).set_sample_width(2).set_frame_rate(16000) #принудительная установка параметров
audio.export(temp_wav_path, format='wav') #конвертация в .wav формат
print_file_info(temp_wav_path) #проверяем параметры файла
if not os.path.exists('model/vosk-model-ru-0.42'): #если не существует папка с моделью
raise FileNotFoundError('Проверьте наличие обученной модели Vosk в папке model!') #то показываем ошибку
model = Model('model/vosk-model-ru-0.42') #получаем предобученную модель для распознавания
recognizer = KaldiRecognizer(model, 16000) #объявление объекта-распознавателя
with wave.open(temp_wav_path, 'rb') as wave_file: #открытие .wav файла в бинарном формате для чтения
if wave_file.getnchannels() != 1 or wave_file.getsampwidth() != 2 or wave_file.getframerate() != 16000: #если файл не прошёл проверку параметров
raise ValueError('Проверьте файл, он должен быть в формате .wav с 1 каналом, 16-bit и 16000 Hz!') #то показываем ошибку
recognizer.AcceptWaveform(wave_file.readframes(wave_file.getnframes())) #распознавание файла
result = recognizer.Result() #получение результата распознавания
text_from_audio = result.split('"text" : ')[1].strip('} \n"') #форматируем вывод, а то там словарь на выходе
return text_from_audio #возвращаем текст сообщения
except Exception as e: #если какая-то шелуха
return f'Возникла неожиданная ошибка: {e}' #то показываем ошибку
finally: #этот блок выполняется в любом случае
if os.path.exists(temp_wav_path): #если есть временный файл
os.remove(temp_wav_path) #то сносим его нафиг, чтобы место не занимал
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)