IT-инфраструктура для бизнеса и творчества
Разработка
NTA

Офлайн распознавание речи. Библиотека Vosk

Преобразование аудио в текст — популярная и повсеместно используемая технология. В этой статье мы расскажем, как распознать речь из аудиофайла на своем ПК без использования онлайн сервисов.

Недавно нам была поставлена задача конвертировать аудиозаписи в текст для дальнейшего анализа. Обязательные условия: офлайн обработка, невысокая требовательность к системным ресурсам, и возможность автоматизации процесса. Мы выбрали Python и библиотеку vosk-api.

Что может Vosk

Vosk – это автономный инструмент для распознавания речи с открытым исходным кодом. Он позволяет использовать модели для 17 языков и диалектов (на момент написания статьи). Модели Vosk малы (50Мб) и позволяют преобразовывать речь в текст «на лету». Существуют и более точные модели. Их размер достигает 2Гб.

Существует реализация библиотеки на Python, Java, NodeJS, C#, C++ и др.

Возможен запуск на ОС Windows, Linux, Android.

Установка

Нам понадобится: python 3.8, библиотеки PyAudio == 0.2.11, vosk == 0.3.1.2

Следующим шагом загружаем модель распознавания. На данный момент для русского доступны две модели:

  • vosk-model-small-ru-0.4 50Мб

  • vosk-model-ru-0.10 2Гб

Большая модель распознает чуть-чуть лучше, а занимает в 40 раз больше места.

После распаковки в каталог модели будет содержать каталоги am, conf, graph и другие.

При появлении ошибки вида:

RuntimeError: Cannot open config file: Z:\Python\Trifonov\vosk\vosk-model-ru-0.10/mfcc.conf

необходимо найти файл в одной из папок модели и переместить в корневой каталог модели. В нашем случае в файл mfcc.conf можно обнаружить в папку conf и переместить его на уровень наверх. С подобной ошибкой я сталкивался на ОС Windows. Для запуска мне пришлось переместить все содержимое папок am, conf, graph, ivector, rmmlm в корень модели.

Использование

Важным параметром является частота дискретизации. Большая модель поддерживает частоту 8000, следовательно, и читать данные с микрофона нужно с такой же частотой

Распознавание «на лету» с микрофона:

from vosk import Model, KaldiRecognizer import os import pyaudio model = Model(r"/home/user/vosk-model-ru-0.10") # полный путь к модели rec = KaldiRecognizer(model, 8000) p = pyaudio.PyAudio() stream = p.open( format=pyaudio.paInt16, channels=1, rate=8000, input=True, frames_per_buffer=8000 ) stream.start_stream() while True: data = stream.read(4000) if len(data) == 0: break print(rec.Result() if rec.AcceptWaveform(data) else rec.PartialResult()) print(rec.FinalResult())

Для распознавания аудио из файлов необходимо конвертировать в формат WAV с частотой дискретизации, поддерживаемый выбранной моделью, в моем случае 8000 Гц.

Листинг кода распознавания аудио файла:

from vosk import Model, KaldiRecognizer import sys import json import os import time import wave model = Model(r"/home/user/vosk-model-ru-0.10") wf = wave.open(r'test.wav', "rb") rec = KaldiRecognizer(model, 8000) result = '' last_n = False while True: data = wf.readframes(8000) if len(data) == 0: break if rec.AcceptWaveform(data): res = json.loads(rec.Result()) if res['text'] != '': result += f" {res['text']}" last_n = False elif not last_n: result += '\n' last_n = True res = json.loads(rec.FinalResult()) result += f" {res['text']}" print(result)

Для примера я распознал новогоднюю речь президента РФ за 2021 год используя большую модель:

уважаемые граждане россии дорогие друзья всего через несколько минут две тысячи двадцатый заканчивает встречая его ровно год назад мы с вами как и люди во всем мире конечно же думали мечтали о добрых перемен и тогда никто не мог представить через какие испытания всем нам придётся пройти и сейчас кажется что уходящий год вместил в себя груз нескольких лет он был трудным для каждого из нас с тревогами и большими материальными сложностей с переживаниями а для кого то горькими утратами близких любимых людей но безусловно уходящий год был связан и с надеждами на преодолении невзгод с гордостью за тех кто проявил свои лучшие человеческие и профессиональные качества с осознанием того как много значат надёжный искренне настоящие отношения между людьми дружбы и доверия между нами

Качество распознавания очень сильно зависит от шумов в исходном файле. Менее удачный пример распознавания той же моделью (минута из видео c YouTube):

сенсор встречается уже поздний базы багажа его нужно то сам что вот я тебе все скажу ну да точнее его машина сломалась у меня монастыря и нежелательно не знаешь нужно надо пройти сначала думаю да а уж потом переходить через вроде как следствие тени это уже это уже изменить эту нишу а когда вот у нас все равно два быть дотронуться прости очень много всего нужно фанат и пройдя очень много кружков и очень многое даже власть имущих неважно как сбор отдавать бывший министр что заяц сэр очень такой хороший дядька мне посоветовал и незамедлительно он выдаёт рады нас видеть смита трейдеры лазеров что у нас перед зрителями

Также стоит отметить, что данная библиотека распознавания речи не обучена определять жаргонизмы и ненормативную лексику, но позволяет проводить дообучение моделей на пользователькой выборке. Описание данной функции можно найти в документации: https://alphacephei.com/vosk/adaptation.

Библиотека vosk показала хороший результат при обработке аудио в «тепличных условиях», но при появлении шумов качество распознавания значительно снижается.

На слабом офисном ПК мне удалось обработать запись длиной 4 часа за 20 минут.

{ "author_name": "NTA", "author_type": "editor", "tags": [], "comments": 0, "likes": 6, "favorites": 17, "is_advertisement": false, "subsite_label": "dev", "id": 247450, "is_wide": true, "is_ugc": false, "date": "Tue, 18 May 2021 11:01:32 +0300", "is_special": false }
(function () { let cdnUrl = `https://specialsf378ef5-a.akamaihd.net/SelectelBranding/images/` let previousArticleNumber = null let currentArticleNumber = 0 let platform = 'Desktop' let articles = [ // { // name: 'camera', // url: `${cdnUrl}CameraCat`, // text: 'умную камеру для\u00A0наблюдения за\u00A0котиками', // link: '1', // }, { name: 'chill', url: `${cdnUrl}ChillCat`, text: 'трекер, который подскажет, когда пора отдохнуть', link: 'https://vc.ru/promo/288561-eye-tracker', }, // { // name: 'cloud', // url: `${cdnUrl}CloudCat`, // text: 'котика: даёшь ему «пять», а\u00A0он делает бэкап в облако', // link: '3', // } ] let buttonCycle = document.querySelector('.button--cycle') let textField = document.querySelector('.selectel-footer-subtitle') let imageAgent = document.querySelector('.image--agent') let banner = document.querySelector('.selectel-footer') buttonCycle.addEventListener('click', cycleClick) let media = window.matchMedia("(max-width: 570px)") media.addEventListener('change', matchMedia) function matchMedia() { if (media.matches) { platform = 'Mobile' } else { platform = 'Desktop' } update() } matchMedia() function cycleClick(event) { if (event) { event.preventDefault() event.stopPropagation() } window.open('https://vc.ru/tag/selectelDIY', '_blank') //cycle(event) } function cycle(event) { // incrementArticleNumber() textField.innerHTML = generatedText() imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' imageAgent.setAttribute("class", "") imageAgent.classList.add('image--agent', articles[currentArticleNumber].name) banner.href = articles[currentArticleNumber].link } function update() { banner.href = articles[currentArticleNumber].link imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?5' textField.innerHTML = generatedText() } function incrementArticleNumber() { previousArticleNumber = currentArticleNumber if (currentArticleNumber >= articles.length - 1) { currentArticleNumber = 0 } else { currentArticleNumber++ } } function generatedText() { let defaultText if (platform === 'Desktop') { defaultText = `Мы тут собрали %text%. Хотите почитать?` } else { defaultText = `Мы тут собрали %text%.` } return defaultText.replace('%text%', articles[currentArticleNumber].text) } function getRandom(min, max) { min = Math.ceil(min) max = Math.floor(max) return Math.floor(Math.random() * (max - min + 1)) + min } (function create() { currentArticleNumber = getRandom(0, articles.length - 1) cycle() let page = document.querySelector('.page--entry') if (page) { function insertAfter() { let parents = page.querySelectorAll('[data-id="7"]') let referenceNode = parents[0] referenceNode.parentNode.insertBefore(banner, referenceNode.nextSibling); loaded() } setTimeout(() => insertAfter(), 0) } }()) function loaded() { banner.classList.add('loaded') } loadImages([ `${cdnUrl}CameraCatDesktop.svg`, `${cdnUrl}ChillCatDesktop.svg`, `${cdnUrl}CloudCatDesktop.svg`, `${cdnUrl}CameraCatMobile.svg`, `${cdnUrl}ChillCatMobile.svg`, `${cdnUrl}CloudCatMobile.svg`, ]) function loadImages(urls) { return Promise.all(urls.map(function (url) { return new Promise(function (resolve) { var img = document.createElement('img'); img.onload = resolve; img.onerror = resolve; img.src = url; }); })); } }())
0
0 комментариев
Популярные
По порядку
Читать все 0 комментариев
Прошел финал программы скаутинга в киберспорте Winstrike

Итоги программы Winstrike Scouting powered by UltraGear

Как испортить лучшую систему комментариев в рунете на примере vc.ru

Иногда мне кажется, на vc.ru идёт прогресс дизайна ради дизайна, а не ради прогресса. Вот и до комментариев добрались.

Нужны ли в России сити-фермы

И появятся ли грядки на крышах пятиэтажек.

re-thinkingthefuture.com
Увидеть первые Apple, сделать копию на ксероксе и потрогать мышку: как в Минске-88 прошла выставка «Информатика в США» Статьи редакции

Выставка стала потрясением для жителей: это было похоже на фильм «Назад в будущее», который на выставке тоже показывали, рассказывает dev.by. Издание поговорило с экс-гидом той выставки и минчанами, которые до сих пор хранят значки с её логотипом.

Создал ледовый комбайн в 50, а вместе с ним и рынок таких машин, который сразу захватил — это изобретатель Фрэнк Замбони Статьи редакции

Иногда ледозаливочные машины других производителей по ошибке называют «Замбони», пишет The Hustle.

Ледовый комбайн Замбони Time
Как традиционному малому бизнесу превратиться в стартап: план действий

Сейчас в России предприниматели переходят из традиционного малого бизнеса в стартапы очень редко — меньше чем в 0,02% случаев. Это не больше 1 000 стартапов из около 6 млн предприятий малого бизнеса. Поговорим о том, что мешает предпринимателям и как действовать, если есть желание создать стартап.

Как мы проводили командную ретроспективу в Minecraft

Рассказываем историю, на что стоит обратить внимание при проведении командного мероприятия в игре Minecraft, какие грабли могут быть, как организовать онлайн- и офлайн-участие.

Готовы выбрать победителя премии «Экспортер года eBay — 2021»?
Я скрестил «Трибуну» и Product Hunt

Теперь вы никогда не пропустите самые перспективные русскоязычные стартапы.

Жизнь и удаленная работа во Вьетнаме: почему работать со сдвигом на 4 часа — это хорошо

Чтобы разобраться, как живется во Вьетнаме на самом деле, мы пообщались с аналитиком, которая с 2013 года живет здесь с супругом и не собирается никуда уезжать. Она расскажет, какие тут на самом деле цены, как обстоят дела с развлечениями и медициной и в чем главное отличие Вьетнама от других стран Юго-Восточной Азии.

Почему кейс с хомяком - не ошибка выжившего и не случайность

Сегодня Интернет облетела новость о том, что хомяк, бегая по своей клетке, заработал +29% на крипте. В комментария к публикации на VC многие писали, что это ошибка выжившего и просто случайность, которая ни о чем не значит. Я же постараюсь объяснить, почему это закономерность, и как сделать так, чтобы ваш кот/собака/рыбка показали такой же…

null