Окончательное руководство по распознаванию речи с Python

5 мая, 2020

Подписывайся на наш канал в Telegram, чтобы ежедневно совершенствоваться в Python. Там выходят задачи, полезные советы и сливы платных курсов - перейти

Перевод статьи

Оглавление

  • Как работает распознавание речи – обзор
  • Выбор пакета распознавания речи Python
  • Установка SpeechRecognition
  • Класс распознавателя
  • Работа с аудио файлами
    • Поддерживаемые типы файлов
    • Использование record () для захвата данных из файла
    • Захват сегментов со смещением и продолжительностью
    • Влияние шума на распознавание речи
  • Работа с микрофонами
    • Установка PyAudio
    • Класс микрофона
    • Использование listen () для ввода с микрофона
    • Обработка неузнаваемой речи
  • Соедини все вместе: игра «Угадай слово»
  • Резюме и дополнительные ресурсы
  • Приложение: Распознавание речи на языках, отличных от английского

Задумывались ли вы, как добавить распознавание речи в ваш проект Python? Если так, то продолжайте читать! Это проще, чем вы думаете.

Отнюдь не будучи увлечением, ошеломляющий успех продуктов с поддержкой речи, таких как Amazon Alexa, доказал, что некоторая степень речевой поддержки будет важным аспектом бытовой техники в обозримом будущем. Если подумать, причины этого довольно очевидны. Включение распознавания речи в ваше приложение Python обеспечивает уровень интерактивности и доступности, которому могут соответствовать немногие технологии.

Стоит рассмотреть только улучшения доступности. Распознавание речи позволяет пожилым людям и людям с нарушениями зрения и зрения быстро и естественным образом взаимодействовать с самыми современными продуктами и услугами – без графического интерфейса!

Лучше всего, в том числе распознавание речи в проекте Python действительно просто. В этом руководстве вы узнаете, как это сделать. Вы узнаете:

  • Как работает распознавание речи,
  • Какие пакеты доступны на PyPI; а также
  • Как установить и использовать пакет SpeechRecognition – полнофункциональную и простую в использовании библиотеку распознавания речи Python.

В конце концов, вы примените то, что вы узнали, к простой игре «Угадай слово» и посмотрим, как все это сложится.

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

Как работает распознавание речи – обзор

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

Распознавание речи коренится в исследованиях, проведенных в лаборатории Bell в начале 1950-х годов. Ранние системы были ограничены одним говорящим и имели ограниченный словарный запас из примерно дюжины слов. Современные системы распознавания речи прошли долгий путь со времен своих древних аналогов. Они могут распознавать речь от нескольких носителей и имеют огромные словари на многих языках.

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

Большинство современных систем распознавания речи опираются на так называемую скрытую марковскую модель (HMM). Этот подход работает в предположении, что речевой сигнал при просмотре на достаточно коротком временном интервале (скажем, десять миллисекунд) может быть разумно аппроксимирован как стационарный процесс, то есть процесс, в котором статистические свойства не изменяются со временем.

В типичном HMM речевой сигнал делится на 10-миллисекундные фрагменты. Спектр мощности каждого фрагмента, который по сути является графиком мощности сигнала как функции частоты, отображается на вектор действительных чисел, известный как кепстральные коэффициенты. Размерность этого вектора обычно невелика – иногда до 10, хотя более точные системы могут иметь размерность 32 или более. Окончательный результат HMM представляет собой последовательность этих векторов.

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

Можно представить, что весь этот процесс может быть вычислительно дорогим. Во многих современных системах распознавания речи нейронные сети используются для упрощения речевого сигнала с использованием методов преобразования признаков и уменьшения размерности до распознавания НММ. Детекторы голосовой активности (VAD) также используются для уменьшения аудиосигнала только до тех участков, которые могут содержать речь. Это не позволяет распознавателю тратить время на анализ ненужных частей сигнала.

К счастью, как программист на Python, вам не нужно беспокоиться об этом. Некоторые службы распознавания речи доступны для использования в режиме онлайн через API, и многие из этих служб предлагают Python SDK .

Выбор пакета распознавания речи Python

В PyPI существует несколько пакетов для распознавания речи. Некоторые из них включают в себя:

Некоторые из этих пакетов, такие как wit и apiai, предлагают встроенные функции, такие как обработка на естественном языке для определения намерений говорящего, которые выходят за рамки базового распознавания речи. Другие, такие как google-cloud-speech, сосредоточены исключительно на преобразовании речи в текст.

Существует один пакет, который отличается простотой использования: SpeechRecognition.

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

Библиотека SpeechRecognition действует как оболочка для нескольких популярных речевых API и, таким образом, является чрезвычайно гибкой. Один из них – Google Web Speech API – поддерживает ключ API по умолчанию, который жестко запрограммирован в библиотеке SpeechRecognition. Это означает, что вы можете подняться без необходимости подписываться на услугу.

Гибкость и простота использования пакета SpeechRecognition делают его отличным выбором для любого проекта Python. Тем не менее, поддержка каждой функции каждого API, который он включает, не гарантируется. Вам нужно будет потратить некоторое время на изучение доступных вариантов, чтобы выяснить, будет ли SpeechRecognition работать в вашем конкретном случае.

Итак, теперь, когда вы убеждены, что вам стоит попробовать SpeechRecognition, следующим шагом будет установка его в вашей среде.

Установка SpeechRecognition

SpeechRecognition совместим с Python 2.6, 2.7 и 3.3+, но требует некоторых дополнительных шагов установки для Python 2 . В этом уроке я предполагаю, что вы используете Python 3.3+.

Вы можете установить SpeechRecognition из терминала с помощью pip:

$ pip install SpeechRecognition

После установки вы должны проверить установку, открыв сеанс интерпретатора и набрав:>>>

>>> import speech_recognition as sr
>>> sr.__version__
'3.8.1'

Примечание. Номер получаемой вами версии может отличаться. Версия 3.8.1 была последней на момент написания.

Продолжайте и держите эту сессию открытой. Вы начнете работать с ним чуть позже.

SpeechRecognition будет работать из коробки, если все, что вам нужно, это работать с существующими аудиофайлами. Однако конкретные случаи использования требуют нескольких зависимостей. В частности, пакет PyAudio необходим для захвата микрофонного входа.

Вы увидите, какие зависимости вам нужны, когда будете читать дальше. А пока давайте углубимся и изучим основы пакета.

RecognizerКласс

Вся магия в SpeechRecognition происходит с Recognizerклассом.

Основной целью Recognizerэкземпляра, конечно же, является распознавание речи. Каждый экземпляр поставляется с различными настройками и функциями для распознавания речи из аудиоисточника.

Создать Recognizerэкземпляр легко. В текущем сеансе интерпретатора просто введите:>>>

>>> r = sr.Recognizer()

Каждый Recognizerэкземпляр имеет семь методов для распознавания речи из аудиоисточника с использованием различных API. Эти:

Из семи recognize_sphinx()работает только в автономном режиме с движком CMU Sphinx. Остальные шесть требуют подключения к интернету.

Полное обсуждение функций и преимуществ каждого API выходит за рамки данного руководства. Поскольку SpeechRecognition поставляется с ключом API по умолчанию для Google Web Speech API, вы можете сразу начать работу с ним. По этой причине мы будем использовать API веб-речи в этом руководстве. Все остальные шесть API-интерфейсов требуют аутентификации либо по ключу API, либо по комбинации имени пользователя и пароля. Для получения дополнительной информации обратитесь к документации SpeechRecognition .

Внимание: ключ по умолчанию, предоставляемый SpeechRecognition, предназначен только для целей тестирования, и Google может отозвать его в любое время . Это не очень хорошая идея использовать API Google Web Speech в производстве. Даже при наличии действующего ключа API вы будете ограничены только 50 запросами в день, и вы не сможете повысить эту квоту . К счастью, интерфейс SpeechRecognition практически идентичен для каждого API, поэтому то, что вы узнаете сегодня, будет легко преобразовать в реальный проект.

Каждый recognize_*()метод генерирует speech_recognition.RequestErrorисключение, если API недоступен. Для recognize_sphinx(), это может произойти в результате отсутствующей, коррумпированной или несовместимой установки Sphinx. Для других шести методов RequestErrorможет быть выброшено, если соблюдены ограничения квоты, сервер недоступен или отсутствует подключение к Интернету.

Хорошо, достаточно болтовни. Давайте испачкаем руки. Продолжайте и попробуйте позвонить recognize_google()на ваш сеанс переводчика.>>>

>>> r.recognize_google()

Что случилось?

Вы, вероятно, получили что-то похожее на это:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: recognize_google() missing 1 required positional argument: 'audio_data'

Вы могли догадаться, что это произойдет. Как можно что-то узнать из ничего?

Все семь recognize_*()методов Recognizerкласса требуют audio_dataаргумента. В каждом случае audio_dataдолжен быть экземпляр класса SpeechRecognition AudioData.

Существует два способа создания AudioDataэкземпляра: из аудиофайла или аудио, записанного с помощью микрофона. С аудиофайлами немного легче начать, так что давайте сначала посмотрим на это.

Работа с аудио файлами

Прежде чем продолжить, вам нужно скачать аудиофайл. Тот, который я использовал для начала, «harvard.wav», можно найти здесь . Убедитесь, что вы сохранили его в том же каталоге, в котором работает сеанс интерпретатора Python.

SpeechRecognition облегчает работу с аудиофайлами благодаря удобному AudioFileклассу. Этот класс может быть инициализирован путем к пути к аудиофайлу и предоставляет интерфейс диспетчера контекста для чтения и работы с содержимым файла.

Поддерживаемые типы файлов

В настоящее время SpeechRecognition поддерживает следующие форматы файлов:

  • WAV: должен быть в формате PCM / LPCM
  • AIFF
  • AIFF-C,
  • FLAC: должен быть родным форматом FLAC; OGG-FLAC не поддерживается

Если вы работаете на Linux, MacOS или Windows на основе x-86, вы сможете без проблем работать с файлами FLAC. На других платформах вам нужно будет установить кодировщик FLAC и убедиться, что у вас есть доступ к flacинструменту командной строки. Вы можете найти больше информации здесь, если это относится к вам.

Использование record()для захвата данных из файла

Введите в сеанс интерпретатора следующую команду для обработки содержимого файла «harvard.wav»:>>>

>>> harvard = sr.AudioFile('harvard.wav')
>>> with harvard as source:
...    audio = r.record(source)
...

Диспетчер контекста открывает файл и считывает его содержимое, сохраняя данные в AudioFileэкземпляре с именем. source.Затем record()метод записывает данные из всего файла в AudioDataэкземпляр. Вы можете подтвердить это, проверив тип audio:>>>

>>> type(audio)
<class 'speech_recognition.AudioData'>

Теперь вы можете вызвать recognize_google()попытку распознать любую речь в аудио. В зависимости от скорости вашего интернет-соединения, вам может потребоваться подождать несколько секунд, прежде чем вы увидите результат.>>>

>>> r.recognize_google(audio)
'the stale smell of old beer lingers it takes heat
to bring out the odor a cold dip restores health and
zest a salt pickle taste fine with ham tacos al
Pastore are my favorite a zestful food is the hot
cross bun'

Поздравляем! Вы только что расшифровали свой первый аудиофайл!

Если вам интересно, откуда взяты фразы в файле «harvard.wav», это примеры предложений Гарварда. Эти фразы были опубликованы IEEE в 1965 году для использования при тестировании разборчивости речи телефонных линий. Они все еще используются в тестировании VoIP и сотовой связи сегодня.

Гарвардские предложения состоят из 72 списков из десяти фраз. Вы можете найти свободно доступные записи этих фраз на веб-сайте Open Speech Repository . Записи доступны на английском, китайском, французском и хинди. Они предоставляют отличный источник бесплатного материала для тестирования вашего кода.

Захват сегментов с offsetиduration

Что делать, если вы хотите захватить только часть речи в файле? record()Метод принимает durationключевое слово аргумент , который останавливает запись после определенного количества секунд.

Например, следующее фиксирует любую речь в первые четыре секунды файла:>>>

>>> with harvard as source:
...     audio = r.record(source, duration=4)
...
>>> r.recognize_google(audio)
'the stale smell of old beer lingers'

record()Метод, когда используется внутри withблока, всегда движется вперед в потоке файла. Это означает, что если вы записываете один раз в течение четырех секунд, а затем снова записываете в течение четырех секунд, второй раз возвращает четыре секунды звука после первых четырех секунд.>>>

>>> with harvard as source:
...     audio1 = r.record(source, duration=4)
...     audio2 = r.record(source, duration=4)
...
>>> r.recognize_google(audio1)
'the stale smell of old beer lingers'
>>> r.recognize_google(audio2)
'it takes heat to bring out the odor a cold dip'

Обратите внимание, что audio2содержит часть третьей фразы в файле. При указании длительности запись может останавливаться в середине фразы или даже в середине слова, что может повлиять на точность транскрипции. Подробнее об этом чуть позже.

В дополнение к указанию продолжительности записи, record()метод может быть задан конкретной отправной точкой, используя offsetключевое слово аргумент. Это значение представляет количество секунд от начала файла, которое нужно игнорировать перед началом записи.

Чтобы захватить только вторую фразу в файле, вы можете начать со смещения в четыре секунды и записывать, скажем, три секунды.>>>

>>> with harvard as source:
...     audio = r.record(source, offset=4, duration=3)
...
>>> r.recognize_google(audio)
'it takes heat to bring out the odor'

В offsetи durationключевых аргументах могут быть использованы для сегментирования звукового файла , если у вас есть предварительное знание структуры речи в файле. Однако их быстрое использование может привести к плохой транскрипции. Чтобы увидеть этот эффект, попробуйте следующее в вашем интерпретаторе:>>>

>>> with harvard as source:
...     audio = r.record(source, offset=4.7, duration=2.8)
...
>>> r.recognize_google(audio)
'Mesquite to bring out the odor Aiko'

Начав запись в 4,7 секунды, вы пропускаете часть «it t» в начале фразы «требуется тепло, чтобы выявить запах», поэтому API получил только «akes heat», что соответствует «Mesquite. »

Точно так же в конце записи вы записали «со», что является началом третьей фразы «холодное падение восстанавливает здоровье и радость». Это соответствует «Айко» API.

Есть еще одна причина, по которой вы можете получить неточные записи. Шум! Приведенные выше примеры хорошо работали, потому что аудиофайл достаточно чистый. В реальном мире, если у вас нет возможности предварительно обработать аудиофайлы, вы не можете ожидать, что звук будет свободным от шума.

Влияние шума на распознавание речи

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

Чтобы понять, как шум может повлиять на распознавание речи, загрузите файл «jackhammer.wav» здесь . Как всегда, убедитесь, что вы сохранили это в рабочем каталоге сеанса интерпретатора.

В этом файле есть фраза «несвежий запах старого пива, задерживающегося», на котором громкий отбойный молоток на заднем плане.

Что происходит, когда вы пытаетесь расшифровать этот файл?>>>

>>> jackhammer = sr.AudioFile('jackhammer.wav')
>>> with jackhammer as source:
...     audio = r.record(source)
...
>>> r.recognize_google(audio)
'the snail smell of old gear vendors'

Далеко!

Так как вы справляетесь с этим? Одна вещь, которую вы можете попробовать, это использовать adjust_for_ambient_noise()метод Recognizerкласса.>>>

>>> with jackhammer as source:
...     r.adjust_for_ambient_noise(source)
...     audio = r.record(source)
...
>>> r.recognize_google(audio)
'still smell of old beer vendors'

Это немного приблизило вас к настоящей фразе, но она все еще не идеальна. Кроме того, «the» отсутствует в начале фразы. Это почему?

adjust_for_ambient_noise()Метод считывает первые второй из потока файлов и калибрует распознаватель к уровню шума аудио. Следовательно, эта часть потока используется перед вызовом record()для захвата данных.

Вы можете настроить период времени, который adjust_for_ambient_noise()используется для анализа, с помощью durationключевого аргумента. Этот аргумент принимает числовое значение в секундах и по умолчанию равен 1. Попробуйте уменьшить это значение до 0,5.>>>

>>> with jackhammer as source:
...     r.adjust_for_ambient_noise(source, duration=0.5)
...     audio = r.record(source)
...
>>> r.recognize_google(audio)
'the snail smell like old Beer Mongers'

Ну, это дало вам «в начале» фразы, но теперь у вас есть новые проблемы! Иногда невозможно устранить влияние шума – сигнал слишком шумный, чтобы с ним можно было справиться. Так обстоит дело с этим файлом.

Если вы часто сталкиваетесь с этими проблемами, вам, возможно, придется прибегнуть к некоторой предварительной обработке аудио. Это можно сделать с помощью программного обеспечения для редактирования аудио или пакета Python (такого как SciPy), который может применять фильтры к файлам. Подробное обсуждение этого вопроса выходит за рамки данного руководства. Если вам интересно, ознакомьтесь с книгой Аллена Дауни « Think DSP» . На данный момент просто помните, что окружающий шум в аудиофайле может вызвать проблемы и должен быть устранен, чтобы максимизировать точность распознавания речи.

При работе с зашумленными файлами может быть полезно увидеть фактический ответ API. Большинство API возвращают строку JSON, содержащую много возможных транскрипций. recognize_google()Метод всегда возвращает наиболее вероятное транскрипцию , если не заставить его дать вам полный ответ.

Вы можете сделать это, установив show_allключевое слово аргумента recognize_google()метода вTrue.>>>

>>> r.recognize_google(audio, show_all=True)
{'alternative': [
  {'transcript': 'the snail smell like old Beer Mongers'}, 
  {'transcript': 'the still smell of old beer vendors'}, 
  {'transcript': 'the snail smell like old beer vendors'},
  {'transcript': 'the stale smell of old beer vendors'}, 
  {'transcript': 'the snail smell like old beermongers'}, 
  {'transcript': 'destihl smell of old beer vendors'}, 
  {'transcript': 'the still smell like old beer vendors'}, 
  {'transcript': 'bastille smell of old beer vendors'}, 
  {'transcript': 'the still smell like old beermongers'}, 
  {'transcript': 'the still smell of old beer venders'}, 
  {'transcript': 'the still smelling old beer vendors'}, 
  {'transcript': 'musty smell of old beer vendors'}, 
  {'transcript': 'the still smell of old beer vendor'}
], 'final': True}

Как видите, recognize_google()возвращает словарь с ключом, 'alternative'который указывает на список возможных расшифровок. Структура этого ответа может варьироваться от API к API и в основном полезна для отладки.

К настоящему времени у вас есть довольно хорошее представление об основах пакета SpeechRecognition. Вы видели, как создать AudioFileэкземпляр из аудиофайла и использовать record()метод для захвата данных из файла. Вы узнали, как записывать сегменты файла, используя аргументы offsetи durationключевые слова record(), и испытали пагубное влияние шума на точность транскрипции.

Теперь самое интересное. Давайте перейдем от расшифровки статических аудиофайлов к интерактивному проекту, приняв ввод с микрофона.

Работа с микрофонами

Чтобы получить доступ к микрофону с помощью SpeechRecognizer, вам необходимо установить пакет PyAudio . Продолжайте и закройте ваш текущий сеанс переводчика, и давайте сделаем это.

Установка PyAudio

Процесс установки PyAudio зависит от вашей операционной системы.

Debian Linux

Если вы используете Linux на основе Debian (например, Ubuntu), вы можете установить PyAudio с apt:

$ sudo apt-get install python-pyaudio python3-pyaudio

После установки может потребоваться запуск pip install pyaudio, особенно если вы работаете в виртуальной среде.

Macos

Для macOS сначала вам нужно установить PortAudio с Homebrew, а затем установить PyAudio с pip:

$ brew install portaudio
$ pip install pyaudio

Windows

В Windows вы можете установить PyAudio с pip:

$ pip install pyaudio

Тестирование установки

После установки PyAudio вы можете проверить установку с консоли.

$ python -m speech_recognition

Убедитесь, что ваш микрофон по умолчанию включен и включен. Если установка сработала, вы должны увидеть что-то вроде этого:

A moment of silence, please...
Set minimum energy threshold to 600.4452854381937
Say something!

Продолжайте и поиграйте с ним немного, поговорив в микрофон и увидев, насколько хорошо SpeechRecognition транскрибирует вашу речь.

Примечание. Если вы работаете в Ubuntu и получаете какой-то прикольный вывод, например «ALSA lib… Unknown PCM», обратитесь к этой странице за советами по подавлению этих сообщений. Этот вывод поступает из пакета ALSA, установленного с Ubuntu, а не из SpeechRecognition или PyAudio. В действительности, эти сообщения могут указывать на проблему с вашей конфигурацией ALSA, но, по моему опыту, они не влияют на функциональность вашего кода. Они в основном неприятность.

MicrophoneКласс

Откройте другой сеанс интерпретатора и создайте экземпляр класса распознавателя.>>>

>>> import speech_recognition as sr
>>> r = sr.Recognizer()

Теперь вместо использования аудиофайла в качестве источника вы будете использовать системный микрофон по умолчанию. Вы можете получить к нему доступ, создав экземпляр Microphoneкласса.>>>

>>> mic = sr.Microphone()

Если в вашей системе отсутствует микрофон по умолчанию (например, на RaspberryPi), или вы хотите использовать микрофон, отличный от стандартного, вам необходимо указать, какой из них использовать, указав индекс устройства. Вы можете получить список имен микрофонов, вызвав list_microphone_names()статический метод Microphoneкласса.>>>

>>> sr.Microphone.list_microphone_names()
['HDA Intel PCH: ALC272 Analog (hw:0,0)',
 'HDA Intel PCH: HDMI 0 (hw:0,3)',
 'sysdefault',
 'front',
 'surround40',
 'surround51',
 'surround71',
 'hdmi',
 'pulse',
 'dmix', 
 'default']

Обратите внимание, что ваш вывод может отличаться от приведенного выше примера.

Индекс устройства микрофона – это индекс его имени в списке, возвращаемом. list_microphone_names().Например, учитывая вышеприведенный вывод, если вы хотите использовать микрофон с именем «front», который имеет индекс 3 в списке, вы должны создать микрофон. например, как это:>>>

>>> # This is just an example; do not run
>>> mic = sr.Microphone(device_index=3)

Тем не менее, для большинства проектов вы, вероятно, захотите использовать системный микрофон по умолчанию.

Использование listen()для захвата входа микрофона

Теперь, когда у вас есть Microphoneготовый экземпляр, пришло время собрать некоторые данные.

Так же, как AudioFileкласс, Microphoneэто менеджер контекста. Вы можете захватить ввод с микрофона, используя listen()метод Recognizerкласса внутри withблока. Этот метод принимает источник звука в качестве первого аргумента и записывает входные данные от источника, пока не будет обнаружена тишина.>>>

>>> with mic as source:
...     audio = r.listen(source)
...

Как только вы выполните withблок, попробуйте сказать «привет» в свой микрофон. Подождите, пока приглашение переводчика не отобразится снова. Как только появится приглашение «>>>», вы готовы распознать речь.>>>

>>> r.recognize_google(audio)
'hello'

Если подсказка не возвращается, ваш микрофон, скорее всего, воспринимает слишком много окружающего шума. Вы можете прервать процесс с помощью + ctrl + c ++, чтобы вернуть ваше приглашение.

Чтобы справиться с окружающим шумом, вам нужно использовать adjust_for_ambient_noise()метод Recognizerкласса, как вы это делали, когда пытались разобраться в зашумленном аудиофайле. Поскольку ввод с микрофона гораздо менее предсказуем, чем ввод из аудиофайла, рекомендуется делать это каждый раз, когда вы слушаете микрофонный вход.>>>

>>> with mic as source:
...     r.adjust_for_ambient_noise(source)
...     audio = r.listen(source)
...

После запуска приведенного выше кода, подождите секунду, adjust_for_ambient_noise()чтобы сделать свое дело, затем попробуйте сказать «привет» в микрофон. Опять же, вам придется немного подождать, пока переводчик предложит вернуться, прежде чем попытаться распознать речь.

Напомним, что adjust_for_ambient_noise()анализируется источник звука в течение одной секунды. Если это кажется вам слишком длинным, не стесняйтесь отрегулировать это с помощью durationключевого аргумента.

Документация SpeechRecognition рекомендует использовать продолжительность не менее 0,5 секунд. В некоторых случаях вы можете обнаружить, что длительность, превышающая значение по умолчанию в одну секунду, дает лучшие результаты. Минимальное значение, которое вам нужно, зависит от окружающей среды микрофона. К сожалению, эта информация обычно неизвестна во время разработки. По моему опыту, длительность по умолчанию в одну секунду подходит для большинства приложений.

Обработка неузнаваемой речи

Попробуйте набрать предыдущий пример кода в интерпретаторе и сделать несколько неразборчивых шумов в микрофон. Вы должны получить что-то вроде этого в ответ:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/david/real_python/speech_recognition_primer/venv/lib/python3.5/site-packages/speech_recognition/__init__.py", line 858, in recognize_google
    if not isinstance(actual_result, dict) or len(actual_result.get("alternative", [])) == 0: raise UnknownValueError()
speech_recognition.UnknownValueError

Аудио, которое не может быть сопоставлено с текстом API, вызывает UnknownValueErrorисключение. Вы всегда должны обернуть вызовы в API с tryи exceptблоки для обработки этого исключения .

Примечание . Возможно, вам придется приложить больше усилий, чем вы ожидаете, чтобы получить исключение. API работает очень усердно, чтобы транскрибировать любые вокальные звуки. Даже короткие ворчания были расшифрованы как слова «как» для меня. Кашель, хлопки в ладоши и щелчки языка постоянно поднимали бы исключение.

Соедини все вместе: игра «Угадай слово»

Теперь, когда вы ознакомились с основами распознавания речи с помощью пакета SpeechRecognition, давайте применим ваши новые знания и напишем небольшую игру, которая выбирает случайное слово из списка и дает пользователю три попытки угадать слово.

Вот полный сценарий:

import random
import time

import speech_recognition as sr


def recognize_speech_from_mic(recognizer, microphone):
    """Transcribe speech from recorded from `microphone`.

    Returns a dictionary with three keys:
    "success": a boolean indicating whether or not the API request was
               successful
    "error":   `None` if no error occured, otherwise a string containing
               an error message if the API could not be reached or
               speech was unrecognizable
    "transcription": `None` if speech could not be transcribed,
               otherwise a string containing the transcribed text
    """
    # check that recognizer and microphone arguments are appropriate type
    if not isinstance(recognizer, sr.Recognizer):
        raise TypeError("`recognizer` must be `Recognizer` instance")

    if not isinstance(microphone, sr.Microphone):
        raise TypeError("`microphone` must be `Microphone` instance")

    # adjust the recognizer sensitivity to ambient noise and record audio
    # from the microphone
    with microphone as source:
        recognizer.adjust_for_ambient_noise(source)
        audio = recognizer.listen(source)

    # set up the response object
    response = {
        "success": True,
        "error": None,
        "transcription": None
    }

    # try recognizing the speech in the recording
    # if a RequestError or UnknownValueError exception is caught,
    #     update the response object accordingly
    try:
        response["transcription"] = recognizer.recognize_google(audio)
    except sr.RequestError:
        # API was unreachable or unresponsive
        response["success"] = False
        response["error"] = "API unavailable"
    except sr.UnknownValueError:
        # speech was unintelligible
        response["error"] = "Unable to recognize speech"

    return response


if __name__ == "__main__":
    # set the list of words, maxnumber of guesses, and prompt limit
    WORDS = ["apple", "banana", "grape", "orange", "mango", "lemon"]
    NUM_GUESSES = 3
    PROMPT_LIMIT = 5

    # create recognizer and mic instances
    recognizer = sr.Recognizer()
    microphone = sr.Microphone()

    # get a random word from the list
    word = random.choice(WORDS)

    # format the instructions string
    instructions = (
        "I'm thinking of one of these words:\n"
        "{words}\n"
        "You have {n} tries to guess which one.\n"
    ).format(words=', '.join(WORDS), n=NUM_GUESSES)

    # show instructions and wait 3 seconds before starting the game
    print(instructions)
    time.sleep(3)

    for i in range(NUM_GUESSES):
        # get the guess from the user
        # if a transcription is returned, break out of the loop and
        #     continue
        # if no transcription returned and API request failed, break
        #     loop and continue
        # if API request succeeded but no transcription was returned,
        #     re-prompt the user to say their guess again. Do this up
        #     to PROMPT_LIMIT times
        for j in range(PROMPT_LIMIT):
            print('Guess {}. Speak!'.format(i+1))
            guess = recognize_speech_from_mic(recognizer, microphone)
            if guess["transcription"]:
                break
            if not guess["success"]:
                break
            print("I didn't catch that. What did you say?\n")

        # if there was an error, stop the game
        if guess["error"]:
            print("ERROR: {}".format(guess["error"]))
            break

        # show the user the transcription
        print("You said: {}".format(guess["transcription"]))

        # determine if guess is correct and if any attempts remain
        guess_is_correct = guess["transcription"].lower() == word.lower()
        user_has_more_attempts = i < NUM_GUESSES - 1

        # determine if the user has won the game
        # if not, repeat the loop if user has more attempts
        # if no attempts left, the user loses the game
        if guess_is_correct:
            print("Correct! You win!".format(word))
            break
        elif user_has_more_attempts:
            print("Incorrect. Try again.\n")
        else:
            print("Sorry, you lose!\nI was thinking of '{}'.".format(word))
            break

Давайте разберемся с этим немного.

recognize_speech_from_mic()Функция принимает Recognizerи Microphoneэкземпляр в качестве аргументов и возвращает словарь с тремя ключами. Первый ключ, "success"это логическое значение, которое указывает, был ли запрос API успешным. Второй ключ, "error"это либо Noneсообщение об ошибке , либо сообщение об ошибке, указывающее, что API недоступен или речь была неразборчивой. Наконец,"transcription" ключ содержит транскрипцию аудио, записанного микрофоном.

Функция сначала проверяет , что recognizerи microphoneаргументы правильного типа, и поднимает TypeErrorесли либо является недействительным:

if not isinstance(recognizer, sr.Recognizer):
    raise TypeError('`recognizer` must be `Recognizer` instance')

if not isinstance(microphone, sr.Microphone):
    raise TypeError('`microphone` must be a `Microphone` instance')

Затем этот listen()метод используется для записи микрофонного входа:

with microphone as source:
    recognizer.adjust_for_ambient_noise(source)
    audio = recognizer.listen(source)

Этот adjust_for_ambient_noise()метод используется для калибровки распознавателя для изменения условий шума при каждом recognize_speech_from_mic()вызове функции.

Далее recognize_google()вызывается для расшифровки любой речи в записи. try...exceptБлок используется , чтобы поймать RequestErrorи UnknownValueErrorисключения и обрабатывать их соответствующим образом . Успех запроса API, любые сообщения об ошибках и транскрибированная речи хранятся в successerrorи transcriptionключи responseсловаря, который возвращается в recognize_speech_from_mic()функции.

response = {
    "success": True,
    "error": None,
    "transcription": None
}

try:
    response["transcription"] = recognizer.recognize_google(audio)
except sr.RequestError:
    # API was unreachable or unresponsive
    response["success"] = False
    response["error"] = "API unavailable"
except sr.UnknownValueError:
    # speech was unintelligible
    response["error"] = "Unable to recognize speech"

return response

Вы можете протестировать recognize_speech_from_mic()функцию, сохранив приведенный выше сценарий в файл с именем «guessing_game.py» и выполнив следующее в сеансе интерпретатора:>>>

>>> import speech_recognition as sr
>>> from guessing_game import recognize_speech_from_mic
>>> r = sr.Recognizer()
>>> m = sr.Microphone()
>>> recognize_speech_from_mic(r, m)
{'success': True, 'error': None, 'transcription': 'hello'}
>>> # Your output will vary depending on what you say

Сама игра довольно проста. Во-первых, объявляется список слов, максимальное количество разрешенных догадок и лимит подсказок:

WORDS = ['apple', 'banana', 'grape', 'orange', 'mango', 'lemon']
NUM_GUESSES = 3
PROMPT_LIMIT = 5

Далее, Recognizerи Microphoneэкземпляр создаются и случайное слово выбрано из WORDS:

recognizer = sr.Recognizer()
microphone = sr.Microphone()
word = random.choice(WORDS)

После распечатки некоторых инструкций и ожидания в течение трех-трех секунд используется forцикл, чтобы управлять каждой попыткой пользователя угадать выбранное слово. Первым делом внутри forцикла является еще один forцикл, который чаще всего запрашивает у пользователя PROMPT_LIMITпредположение, пытаясь каждый раз распознать ввод с помощью recognize_speech_from_mic()функции и сохраняя словарь, возвращенный в локальную переменную.guess .

Если "transcription"ключ guessотсутствует None, то речь пользователя транскрибируется и внутренний цикл завершается с помощью break. Если речь не была расшифрована, а "success"ключ установлен на False, то произошла ошибка API, и цикл снова завершился break. В противном случае запрос API был успешным, но речь была неузнаваема. Пользователь получает предупреждение, и forцикл повторяется, давая ему еще один шанс при текущей попытке.

for j in range(PROMPT_LIMIT):
    print('Guess {}. Speak!'.format(i+1))
    guess = recognize_speech_from_mic(recognizer, microphone)
    if guess["transcription"]:
        break
    if not guess["success"]:
        break
    print("I didn't catch that. What did you say?\n")

Как только внутренний forцикл завершается, guessсловарь проверяется на наличие ошибок. Если что-то произошло, отображается сообщение об ошибке, и внешний forцикл завершается break, что завершает выполнение программы.

if guess['error']:
    print("ERROR: {}".format(guess["error"]))
    break

Если ошибок не было, транскрипция сравнивается со случайно выбранным словом. lower()Метод строковых объектов используются для обеспечения лучшего согласования угадать с выбранным словом. API может возвращать речь, соответствующую слову «яблоко» как «яблоко» или «яблоко», и любой ответ должен считаться правильным ответом.

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

guess_is_correct = guess["transcription"].lower() == word.lower()
user_has_more_attempts = i < NUM_GUESSES - 1

if guess_is_correct:
    print('Correct! You win!'.format(word))
    break
elif user_has_more_attempts:
    print('Incorrect. Try again.\n')
else:
    print("Sorry, you lose!\nI was thinking of '{}'.".format(word))
    break

При запуске вывод будет выглядеть примерно так:

I'm thinking of one of these words:
apple, banana, grape, orange, mango, lemon
You have 3 tries to guess which one.

Guess 1. Speak!
You said: banana
Incorrect. Try again.

Guess 2. Speak!
You said: lemon
Incorrect. Try again.

Guess 3. Speak!
You said: Orange
Correct! You win!

Резюме и дополнительные ресурсы

В этом учебном пособии вы увидели, как установить пакет SpeechRecognition и использовать его Recognizerкласс для простого распознавания речи как из файла – с помощью record()– и ввода с микрофона – с использованием. listen().Вы также увидели, как обрабатывать сегменты аудиофайла, используя аргументы offsetи durationключевое слово от record()метода.

Вы видели, как шум может влиять на точность транскрипции, и узнали, как настроить Recognizerчувствительность экземпляра к окружающему шуму с помощью adjust_for_ambient_noise().Вы также узнали, какие исключения Recognizerможет генерировать экземпляр – RequestErrorдля некорректных запросов API и UnkownValueErrorдля неразборчивой речи – и как справиться с этим с try...exceptблоками.

Распознавание речи – глубокий предмет, и то, что вы узнали здесь, едва царапает поверхность. Если вы заинтересованы в получении дополнительной информации, вот несколько дополнительных ресурсов.

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

Для получения дополнительной информации о пакете SpeechRecognition:

Несколько интересных интернет-ресурсов:

Несколько хороших книг о распознавании речи:

Приложение: Распознавание речи на языках, отличных от английского

На протяжении всего этого урока мы распознавали речь на английском языке, который является языком по умолчанию для каждого recognize_*()метода пакета SpeechRecognition. Тем не менее, это абсолютно возможно для распознавания речи на других языках, и это довольно просто сделать.

Чтобы распознать речь на другом языке, задайте в качестве languageаргумента ключевого слова recognize_*()метода строку, соответствующую нужному языку. Большинство методов принимают языковой тег BCP-47, например, 'en-US'для американского английского или 'fr-FR'французского. Например, следующее распознает французскую речь в аудиофайле:

import speech_recognition as sr

r = sr.Recognizer()

with sr.AudioFile('path/to/audiofile.wav') as source:
    audio = r.record(source)

r.recognize_google(audio, language='fr-FR')

Только следующие методы принимают languageаргумент ключевого слова:

  • recognize_bing()
  • recognize_google()
  • recognize_google_cloud()
  • recognize_ibm()
  • recognize_sphinx()

Чтобы узнать, какие языковые теги поддерживаются используемым вами API, вам нужно обратиться к соответствующей документации . Список принятых тэгов recognize_google()можно найти в ответе на переполнение стека .


Совершенствуй знания каждый день у нас в Телеграм-каналах

Вопросы, реклама — VK | Telegram