Год назад для собственных нужд я написал обертку Yandex SpeechKit на Python, она получилась настолько простая и универсальная, что грех не поделиться : )
Кстати, вот она: Yandex SpeechKit Python SDK!
Для того, чтобы начать распознавать и синтезировать речь нам понадобится Python 3.6 или выше. Установить модуль можно из PyPI:
pip install speechkit
Разбираемся с консолью яндекса
Прежде чем писать код, стоит сказать пару слов про то, как устроена платформа Yandex Cloud. Первым делом, Вам нужно зайти в консоль cloud.yandex.ru c помощью акаунта яндекса или создать такой. Затем, создать платежный аккаунт, активировав пробный период. В итоге получится что-то такое:

Получить идентификатор каталога можно из URL страницы каталога в консоли управления:
https://console.cloud.yandex.ru/folders/b1gd129pp9ha0vnvf5g7 , где b1gd129pp9ha0vnvf5g7 — это идентификатор каталога. Он нам скоро понадобиться.
Для запроса к API SpeechKit нужно получить IAM-токен, Вам об этом беспокоиться не нужно, это уже "вшито" в библиотеку, нужно лишь передать исходные данные для создания сессии. Проще всего получить IAM-токен из OAuth-токена, Вашего аккаунта на яндексе, для этого перейдите по ссылке, нажмите Разрешить и скопируйте полученный OAuth-токен. В серьезных проектах лучше использовать авторизацию по JWT-токену или API-ключу для сервисного аккаунта.
Синтез речи
Итак, у нас есть все, чтобы программа обрела голос, осталось лишь написать несколько строчек:
from speechkit import Session, SpeechSynthesis oauth_token = "AQAAAAAsHJkgAAhjwXshft5QgUuRkX0Wubhjlk" catalog_id = "b1gd129pp9ha0vnvf5g7" # Экземпляр класса `Session` можно получать из разных данных session = Session.from_yandex_passport_oauth_token(oauth_token, catalog_id) # Создаем экземляр класса `SpeechSynthesis`, передавая `session`, # который уже содержит нужный нам IAM-токен # и другие необходимые для API реквизиты для входа synthesizeAudio = SpeechSynthesis(session) # Метод `.synthesize()` позволяет синтезировать речь и сохранять ее в файл synthesizeAudio.synthesize( 'out.wav', text='Привет мир!', voice='oksana', format='lpcm', sampleRateHertz='16000' ) # `.synthesize_stream()` возвращает объект типа `io.BytesIO()` с аудиофайлом audio_data = synthesizeAudio.synthesize_stream( text='Привет мир, снова!', voice='oksana', format='lpcm', sampleRateHertz='16000' )
Вот так просто! Значение и полный список параметров можно посмотреть в документации яндекса или в документации библиотеки.
Теперь этот аудиофайл можно проиграть с помощью плеера или, например, с помощью библиотеки PyAudio. Кстати, в этом случае разумнее будет передавать объект с данными, а не сохранять их в файл, вот так:
import pyaudio def pyaudio_play_audio_function(audio_data, num_channels=1, sample_rate=16000, chunk_size=4000) -> None: """ Воспроизводит бинарный объект с аудио данными в формате lpcm (WAV) :param bytes audio_data: данные сгенерированные спичкитом :param integer num_channels: количество каналов, спичкит генерирует моно дорожку, поэтому стоит оставить значение `1` :param integer sample_rate: частота дискретизации, такая же какую вы указали в параметре sampleRateHertz :param integer chunk_size: размер семпла воспроизведения, можно отрегулировать если появится потрескивание """ p = pyaudio.PyAudio() stream = p.open( format=pyaudio.paInt16, channels=num_channels, rate=sample_rate, output=True, frames_per_buffer=chunk_size ) try: for i in range(0, len(audio_data), chunk_size): stream.write(audio_data[i:i + chunk_size]) finally: stream.stop_stream() stream.close() p.terminate() sample_rate = 16000 # частота дискретизации должна # совпадать при синтезе и воспроизведении audio_data = synthesizeAudio.synthesize_stream( text='Привет мир, снова и снова!', voice='oksana', format='lpcm', sampleRateHertz=sample_rate ) # Воспроизводим синтезированный файл pyaudio_play_audio_function(audio_data, sample_rate=sample_rate)
Теперь мы можем проговорить голосом яндекса что-нибудь прямо из программы, осталось научиться распознавать команды и можно прикручивать голосовое управление к чайнику, кофеварке, утюгу и пылесосу!
Распознавание речи
Яндекс предоставляет три способа распознавания: потоковое распознавание, синхронное распознавание и асинхронное распознавание. О том чем они отличаются и зачем нужны можно почитать на официальной страничке.
Если вкратце, потоковое распознавание нужно для того, чтобы получать текст прямо во время записи и стриминга аудио, и обрабатывать результаты на лету. Например, умная колонка может начать задумываться как ей ответить, в то время, как пользователь еще не закончил фразу. Пример использования потокового распознавания в гитхабе библиотеки, еще подробнее можно почитать в документации.
Асинхронное распознавание нужно для пере��ода в текстовый формат очень длинных аудиозаписей, оно дешевле остальных методов, но для получения результата придется немного подождать. Вот пример использования и описание класса.
Мы же будем использовать самый простой способ — синхронное распознавание. Для этого запишем сообщение в файл и сохраним в формате WAV.
from speechkit import ShortAudioRecognition # Читаем файл with open('voice.wav', 'rb') as f: data = f.read() # Создаем экземпляр класса с помощью `session` полученного ранее recognizeShortAudio = ShortAudioRecognition(session) # Передаем файл и его формат в метод `.recognize()`, # который возвращает строку с текстом text = recognizeShortAudio.recognize( data, format='lpcm', sampleRateHertz='48000') print(text)
Ура! Теперь можно прикрутить голосовые команды к чему угодно. Вот ссылка на полное описание метода, если Вы хотите передавать файл в формате, отличном от WAV, например.
Напоследок покажу, как с помощью PyAudio записать голос, который можно будет потом передать в спичкит для распознавания:
import io import wave import pyaudio def record_audio(seconds, sample_rate, chunk_size=4000, num_channels=1) -> bytes: """ Записывает аудио данной продолжительности и возвращает бинарный объект с данными :param integer seconds: Время записи в секундах :param integer sample_rate: частота дискретизации, такая же какую вы указали в параметре sampleRateHertz :param integer chunk_size: размер семпла записи :param integer num_channels: количество каналов, в режимер синхронного распознавания спичкит принимает моно дорожку, поэтому стоит оставить значение `1` :return: Возвращает объект BytesIO с аудио данными в формате WAV :rtype: bytes """ p = pyaudio.PyAudio() stream = p.open( format=pyaudio.paInt16, channels=num_channels, rate=sample_rate, input=True, frames_per_buffer=chunk_size ) frames = [] try: for i in range(0, int(sample_rate / chunk_size * seconds)): data = stream.read(chunk_size) frames.append(data) finally: stream.stop_stream() stream.close() p.terminate() container = io.BytesIO() wf = wave.open(container, 'wb') wf.setnchannels(num_channels) wf.setsampwidth(p.get_sample_size(pyaudio.paInt16)) wf.setframerate(sample_rate) wf.writeframes(b''.join(frames)) container.seek(0) return container sample_rate = 16000 # частота дискретизации должна # совпадать при записи и распознавании # Записываем аудио продолжительностью 3 секунды data = record_audio(3, sample_rate) # Отправляем на распознавание text = recognizeShortAudio.recognize( data, format='lpcm', sampleRateHertz=sample_rate) print(text)
На этом все. Надеюсь, вам пригодилась библиотека : ) Буду рад пул-реквестам!
Спасибо за внимание!
