Speech Recognition - распознавание речи

Включение распознавания речи в ваше приложение Python обеспечивает интерактивность.

Вы узнаете:

  • Как работает распознавание речи,
  • Какие Библиотеки необходимы
  • Как установить и использовать пакет SpeechRecognition - полнофункциональную и простую в использовании библиотеку распознавания речи Python.

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

Современные системы распознавания речи могут распознавать речь от нескольких носителей и имеют огромный словарный запас на разных языках.

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

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

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

  • apiai
  • assemblyai
  • google-cloud-speech
  • pocketsphinx
  • SpeechRecognition
  • watson-developer-cloud
  • wit

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

SpeechRecognition: - пакет, позволяет создавать сценарии для доступа к микрофонам и обработки аудиофайлов с нуля.

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

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

Установка SpeechRecognition

SpeechRecognition совместим с Python 3.3+.

Установить SpeechRecognition из терминала с помощью pip:

$ pip install SpeechRecognition
1

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

>>> import speech_recognition as sr
>>> sr.__version__
'3.8.1'
1
2
3

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

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

The Recognizer Class

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

Создать экземпляр Recognizer очень просто:

r = sr.Recognizer ()
1

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

  • recognize_bing(): Microsoft Bing Speech
  • recognize_google(): Google Web Speech API
  • recognize_google_cloud(): Google Cloud Speech - требует установки пакета google-cloud-speech package
  • recognize_houndify(): Houndify by SoundHound
  • recognize_ibm(): IBM Speech to Text
  • recognize_sphinx(): CMU Sphinx - требует установки PocketSphinx
  • recognize_wit(): Wit.ai

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

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

ВНИМАНИЕ.

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

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

Попробуйте вызвать recognize_google():

r.recognize_google()
1

Получили что-то похожее на это:

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

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

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

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

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

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

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

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

Если вы работаете на Linux, MacOS или Windows на основе x-86, вы сможете без проблем работать с файлами FLAC.

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

Введите в следующую команду для обработки содержимого файла:

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

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

print(type(audio))     # <class 'speech_recognition.AudioData'>
1

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

print(r.recognize_google(audio))
1
'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'
1

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

Захват сегментов со смещением и продолжительностью

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

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

with harvard as source:
     audio = r.record(source, duration=4)

print(r.recognize_google(audio))        # 'the stale smell of old beer lingers'

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

```py
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'
1
2
3
4
5
6
7
8
9
10
11
12
13
14

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

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

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

with harvard as source:
    audio = r.record(source, offset=4, duration=3)

print(recognizer.recognize_google(audio))       # 'it takes heat to bring out the odor'
1
2
3
4

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

with harvard as source:
    audio = r.record(source, offset=4.7, duration=2.8)

print(recognizer.recognize_google(audio))       # 'Mesquite to bring out the odor Aiko'
1
2
3
4

Начав запись через 4.7 секунды, вы пропускаете часть «it t» в начале фразы «it takes heat to bring out the odor», поэтому API получил только «akes heat», что соответствует «Mesquite.»

Точно так же, в конце записи вы записали «co», которое является началом третьей фразы «a cold dip restores health and zest». Это было сопоставлено с «Aiko» API.

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

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

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

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

В этом файле есть фраза «нthe stale smell of old beer lingers», на котором громкий отбойный молоток на заднем плане.

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

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

print(r.recognize_google(audio))    # 'the snail smell of old gear vendors'
1
2
3
4
5

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

with jackhammer as source:
    r.adjust_for_ambient_noise(source)
    audio = r.record(source)

print(r.recognize_google(audio))    # 'still smell of old beer vendors'
1
2
3
4
5

Это немного приблизило вас к настоящей фразе, но она все еще не идеальна. Кроме того, «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)

print(r.recognize_google(audio))    # 'the snail smell like old Beer Mongers'
1
2
3
4
5

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

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

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

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

print(r.recognize_google(audio, show_all=True))
1

Результат вывода:

{'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}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

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

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

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

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

Установка PyAudio в Windows

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

$ pip install pyaudio
1

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

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

$ python -m speech_recognition
1

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

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

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

Класс микрофона

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

import speech_recognition as sr
r = sr.Recognizer()
mic = sr.Microphone()
1
2
3

Если в вашей системе нет микрофона по умолчанию, или вы хотите использовать микрофон, отличный от стандартного, вам нужно будет указать, какой из них использовать, указав индекс устройства. Вы можете получить список имен микрофонов, вызвав статический метод 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']
1
2
3
4
5
6
7
8
9
10
11
12

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

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

# Это всего лишь пример
mic = sr.Microphone(device_index = 3)
1
2

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

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

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

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

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

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

print(r.recognize_google (аудио))   # 'Привет'
1

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

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

with mic as source:
    r.adjust_for_ambient_noise(source)
    audio = r.listen(source)
1
2
3

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

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

Документация 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
1
2
3
4
5

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

ПРИМЕЧАНИЕ

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

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

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

Чтобы распознавать речь на другом языке, задайте в качестве аргумента ключевого слова языка метода распознавания строку, соответствующую нужному языку. Большинство методов принимают языковой, например, «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')
1
2
3
4
5
6
7

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

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

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

Упражнения

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