Spaces:
Running
Running
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) | |