Как сделать распознавание голоса на java

Обновлено: 07.07.2024

В последнее время я думал о запуске приложения на основе распознавания речи. Значение определенных результатов для выполнения конкретных задач. Мне было интересно, как лучше всего двигаться дальше. Я тоже думаю о ПК или Android. Я считаю JAVA своим сильным языком программирования.

Я сделал некоторые поиски, но все же я не знаю, какой из них лучше всего подходит.

Есть ли у открытого программного обеспечения часть распознавания речи для меня и работа с другой частью? Сделай все это сам? И если да, возможно ли это в JAVA?

Любая информация будет оценена по достоинству.

Лучший способ приблизиться к этому – использовать существующий инструментарий распознавания и язык и акустические модели, которые приходят с ним. Вы можете обучать модели в соответствии с вашими потребностями.

CMUSphinx , вероятно, является лучшим программным обеспечением для распознавания речи FOSS. CMUSphinx также обеспечивает хорошую интеграцию с Java и демонстрационные приложения.

После оценки нескольких сторонних функций распознавания речи распознавание голоса Google, безусловно, является наиболее точным. При использовании распознавания голоса Google существуют два основных подхода. Самый простой способ – запустить Intent и обработать результаты соответственно:

То в вашем onActivityResults () вы будете обрабатывать совпадения, возвращаемые службой:

Второй подход более активен, но позволяет лучше обрабатывать условие ошибки, которое может случиться во время работы службы распознавания. Используя этот подход, вы должны создать свой собственный метод прослушивания и обратного вызова. Например:

Затем создайте своего слушателя:

Вы можете добавить handleResults (), чтобы делать все, что хотите.

Вы также можете использовать API Google Speech. С Android он доступен через справочник SpeechRecognizer

Вот ссылка на вопрос stackoverflow, который также содержит демонстрационный код в Java: распознавание речи в Java

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

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

Что может Vosk

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

Нам понадобится: python 3.8, библиотеки PyAudio == 0.2.11, vosk == 0.3.1.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, следовательно, и читать данные с микрофона нужно с такой же частотой

Для распознавания аудио из файлов необходимо конвертировать в формат 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" " last_n = False elif not last_n: result += '\n' last_n = True res = json.loads(rec.FinalResult()) result += f" " print(result)

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

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

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

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

В этой статье я подробно расскажу и покажу, как правильно и быстро прикрутить распознавание русской речи на движке Pocketsphinx (для iOS порт OpenEars) на реальном Hello World примере управления домашней техникой.
Почему именно домашней техникой? Да потому что благодаря такому примеру можно оценить ту скорость и точность, которой можно добиться при использовании полностью локального распознавания речи без серверов типа Google ASR или Яндекс SpeechKit.
К статье я также прилагаю все исходники программы и саму сборку под Android.

С чего вдруг?

Наткнувшись недавно на статью о прикручивании Яндекс SpeechKit-а к iOS приложению, я задал вопрос автору, почему для своей программы он захотел использовать именно серверное распознавание речи (по моему мнению, это было излишним и приводило к некоторым проблемам). На что получил встречный вопрос о том, не мог бы я поподробней описать применение альтернативных способов для проектов, где нет необходимости распознавать что угодно, а словарь состоит из конечного набора слов. Да еще и с примером практического применения…

Зачем нам что-то еще кроме Яндекса и Google?

Так Android же умеет распознавать речь без интернета!

Да-да… Только на JellyBean. И только с полуметра, не более. И это распознавание — это та же диктовка, только с использованием гораздо меньшей модели. Так что управлять ею и настраивать ее мы тоже не можем. И что она вернет нам в следующий раз — неизвестно. Хотя для СМС-ок в самый раз!

Что будем делать?



Будем реализовывать голосовой пульт управления домашней техникой, который будет работать точно и быстро, с нескольких метров и даже на дешевом тормозном хламе очень недорогих Android смартфонах, планшетах и часах.
Логика будет простой, но очень практичной. Активируем микрофон и произносим одно или несколько названий устройств. Приложение их распознает и включает-выключает их в зависимости от текущего состояния. Либо получает от них состояние и произносит его приятным женским голосом. Например, текущая температура в комнате.

Микрофон будем активировать или голосом, или нажатием на иконку микрофона, или даже просто положив руку на экран. Экран в свою очередь может быть и полностью выключенным.

На видео показано, что получилось в итоге. Далее же речь пойдет о технической реализации с выдержками из реально работающего кода и немного теории.

Что такое Pocketsphinx

Формат грамматики JSGF используется Pocketsphinx, как и многими другими подобными проектами. В нем можно с достаточной гибкостью описать те варианты фраз, которые будет произносить пользователь. В нашем случае грамматика будет строиться из названий устройств, которые есть в нашей сети, примерно так:

Pocketsphinx также может работать по статистической модели языка, что позволяет распознавать спонтанную речь, не описываемую контекстно-свободной грамматикой. Но для нашей задачи это как раз не нужно. Наша грамматика будет состоять только из названий устройств. После процесса распознавания Pocketsphinx вернет нам обычную строчку текста, где устройства будут идти один за другим.

Знак плюса обозначает, что пользователь может назвать не одно, а несколько устройств подряд.
Приложение получает список устройств от контроллера умного дома (см далее) и формирует такую грамматику в классе Grammar.

Транскрипции



Грамматика описывает то, что может говорить пользователь. Для того, чтобы Pocketsphinx знал, как он это будет произносить, необходимо для каждого слова из грамматики написать, как оно звучит в соответствующей языковой модели. То есть транскрипцию каждого слова. Это называется словарь.

Транскрипции описываются с помощью специального синтаксиса. Например:

В принципе, ничего сложного. Двойная гласная в транскрипции обозначает ударение. Двойная согласная — мягкую согласную, за которой идет гласная. Все возможные комбинации для всех звуков русского языка можно найти в самой языковой модели.

Голосовая активация

Одно стоит упомянуть обязательно. Для активационной фразы нужно не только указать транскрипцию, но и подобрать подходящее значение порога чувствительности. Слишком маленькое значение приведет к множеству ложных срабатываний (это когда вы не говорили активационную фразу, а система ее распознает). А слишком высокое — к невосприимчивости. Поэтому данная настройка имеет особую важность. Примерный диапазон значений — от 1e-1 до 1e-40 в зависимости от активационной фразы.

Запускаем распознование

Pocketsphinx предоставляет удобный API для конфигурирования и запуска процесса распознавания. Это классы SppechRecognizer и SpeechRecognizerSetup.
Вот как выглядит конфигурация и запуск распознавания:

Здесь мы сперва копируем все необходимые файлы на диск (Pocketpshinx требует наличия на диске аккустической модели, грамматики и словаря с транскрипциями). Затем конфигурируется сам движок распознавания. Указываются пути к файлам модели и словаря, а также некоторые параметры (порог чувствительности для активационной фразы). Далее конфигурируется путь к файлу с грамматикой, а также активационная фраза.

Как видно из этого кода, один движок конфигурируется сразу и для грамматики, и для распознавания активационной фразы. Зачем так делается? Для того, чтобы мы могли быстро переключаться между тем, что в данный момент нужно распознавать. Вот как выглядит запуск процесса распознавания активационной фразы:

А вот так — распозанвание речи по заданной грамматике:

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

Как получить результат распознавания

Чтобы получить результат распознавания, нужно также указать слушателя событий, имплементирующего интерфейс RecognitionListener.
У него есть несколько методов, которые вызываются pocketsphinx-ом при наступлении одного из событий:

  • onBeginningOfSpeech — движок услышал какой-то звук, может быть это речь (а может быть и нет)
  • onEndOfSpeech — звук закончился
  • onPartialResult — есть промежуточные результаты распознавания. Для активационной фразы это значит, что она сработала. Аргумент Hypothesis содержит данные о распознавании (строка и score)
  • onResult — конечный результат распознавания. Этот метод будет вызыван после вызова метода stop у SpeechRecognizer. Аргумент Hypothesis содержит данные о распознавании (строка и score)

Реализуя тем или иным способом методы onPartialResult и onResult, можно изменять логику распознавания и получать окончательный результат. Вот как это сделано в случае с нашим приложением:

Когда мы получаем событие onEndOfSpeech, и если при этом мы распознаем команду для выполнения, то необходимо остановить распознавание, после чего сразу будет вызван onResult.
В onResult нужно проверить, что только что было распознано. Если это команда, то нужно запустить ее на выполнение и переключить движок на распознавание активационной фразы.
В onPartialResult нас интересует только распознавание активационной фразы. Если мы его обнаруживаем, то сразу запускаем процесс распознавания команды. Вот как он выглядит:

Здесь мы сперва играем небольшой сигнал для оповещения пользователя, что мы его услышали и готовы к его команде. На это время микрофон долже быть выключен. Поэтому мы запускаем распознавание после небольшого таймаута (чуть больше, чем длительность сигнала, чтобы не услышать его эха). Также запускается поток, который остановит распознавание принудительно, если пользователь говорит слишком долго. В данном случае это 3 секунды.

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

Как синтезировать речь

Синтез речи — это операция, обратная распознаванию. Здесь наоборот — нужно превратить строку текста в речь, чтобы ее услышал пользователь.
В случае с термостатом мы должны заставить наше Android устройство произнести текущую температуру. С помощью API TextToSpeech это сделать довольно просто (спасибо гуглу за прекрасный женский TTS для русского языка):

Скажу наверное банальность, но перед процессом синтеза нужно обязательно отключить распознавание. На некоторых устройствах (например, все самсунги) вообще невозсожно одновременно и слушать микрофон, и что-то синтезировать.
Окончание синтеза речи (то есть окончание процесса говорения текста синтезатором) можно отследить в слушателе:

В нем мы просто проверяем, нет ли еще чего-то в очереди на синтез, и включаем распозанвание активационной фразы, если ничего больше нет.

И это все?

Да! Как видите, быстро и качественно распознать речь прямо на устройстве совсем несложно, благодаря наличию таких замечательных проектов, как Pocketsphinx. Он предоставляет очень удобный API, который можно использовать в решении задач, связанных с распознаванием голосовых команд.

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

Все исходники, а также саму сборку приложения вы можете найти в репозитории на GitHub.
Также на моем канале в YouTube вы можете увидеть некоторые другие реализации голосового управления, и не только системами умных домов.

Дима Шалыгин

Десктопное приложение Java SE + Swing. Хочется вставить распознавание голоса (русских и английских фраз), преобразование в текст. Возможно с привлечением чужих API.
Кто-нибудь сталкивался - что порекомендуете?

Михаил Вайсман

все что вам гугл выдал - вам не подходить? а почему? какие дополнительные требование делают не пригодными все результаты выдаваемые гуглом?

Павел Бортников

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

Михаил Вайсман

Павел, вы сами гугл попробовали. Там действительно тонна информации? :) просто советы давать можно если знаешь почему человеку не подошел конкретный вариант. Например, стандартный API от Оракла. И не тактично обвинять людей в нетактичности ;)

Читайте также: