Всем привет.

В статье Звуковые игры: невидимый рынок ждёт героев были рассмотрены звуковые игры с крутым объемным звуком, и библиотеки для его создания.

Ну а я решил начать с малого, и для начала организовать озвучивание синтезатором действий в пошаговых играх на pygame.

Конечно не для всех игр подходит такой прием, но в некоторых очень даже.



Создадим модуль speech.

В нем организуем два варианта работы:

  • подключение к экранному диктору NVDA через его Controller dll;
  • напрямую на синтезатор windows через SAPI5;



Сначала импортируем все необходимые модули.
Для подключения nvdaControllerClient32.dll нам нужен ctypes.

import ctypes

А при отсутствии NVDA на компьютере, работаем напрямую с синтезатором SAPI через win32api.

import win32com.client


Создаем класс для нашей говорилки.

class Speech:

    def __init__(self, config):
        """Initialize speech class."""
        self.config = config

Здесь наверно надо пояснить про config. В общем классе Game, который занимается инициализацией всех модулей игры и крутит основной цикл, идет загрузка настроек игры.

Настройки можно загружать откуда удобнее: ini файлы, json, sqlite, или любой другой удобный вариант.


Но продолжим инициализацию нашего Speech.

        # подключаем синтезатор как COM объект.
        self.speaker = win32com.client.Dispatch("Sapi.SpVoice")
        # Получаем все доступные синтезаторы в системе и сохраняем в списке
        self.voices = self.speaker.GetVoices()
        # Создаем список имен полученных голосов
        self.voices_names = [voice.GetDescription() for voice in self.voices]

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

Скорость голоса устанавливается в диапозоне от -10 до +10. Но не думаю, что кто-то захочет слушать голос со скоростью ниже 5. Можете самостоятельно поэкспериментировать, меняя значение в настройках.

Ну и конечно громкость голоса. Тут стандартно от 0 до 100.

        self.set_voice(self.config.voice)
        self.speaker.Rate = self.config.rate
        self.speaker.Volume = self.config.volume

Ну и наконец инициализируем nvda.

        self.nvda = self.config.nvda
        self.nvda_error = False
        self.sLib = ctypes.windll.LoadLibrary('./nvdaControllerClient32.dll')

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

        nvda_error = self.sLib.nvdaController_testIfRunning()
        errorMessage = str(ctypes.WinError(nvda_error))
        if 0 != nvda_error:
            print('NVDA error: ' + errorMessage)
            self.nvda_error = True

После того как проинициализировали и синтезатор SAPI, и nvda dll можно запустить функцию выбора аудио вывода речи.
        self.set_speak_out()
        


Добавим функцию установки голоса из списка доступных по индексу.

    def set_voice(self, index):
        """Set voice for speak."""
        try:
            self.speaker.Voice = self.voices[index]
            self.speak_sapi(self.voices_names[index])
        except:
            print('error: do not set voice')


А теперь функция по выбору аудио вывода речи. Тут мы собственно и выбираем, что будем использовать для работы: nvda или синтезатор напрямую.

Выбор заключается в двух параметрах:

  • Флаг в настройках, хочет ли пользователь вообще чтоб игра использовала NVDA;
  • Возможные ошибки при подключении к NVDA;

    def set_speak_out(self):
        """Set speak out: nvda or sapi."""
        if self.nvda and not self.nvda_error:
            self.speak = self.speak_nvda
        else:
            self.speak = self.speak_sapi


Ну и конечно пропишем функции произношения.

Для NVDA:

    def speak_nvda(self, phrase):
        self.sLib.nvdaController_speakText(phrase)

А это функция для произношения напрямую на синтезатор:
    def speak_sapi(self, phrase):
        self.speaker.Speak(phrase)


Вот и все. Теперь в любом месте игровой логики отправляем нужную информацию на speech.speak().

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

Комментарии (5)


  1. skymal4ik
    26.09.2018 16:45

    Хорошее дело делаете! Пока не прочитаешь о таком, даже не задумаешься что кому-то необходимо что-то такое.

    Только вот заголовок слегка вводит в заблуждение — я открывал статью чтобы посмотреть список игр на pygame и их успешности на рынке.


    1. DollaR84 Автор
      26.09.2018 20:49

      Спасибо большое за ваше мнение.
      А насчет заголовка. Я тоже думал сменить pygame на что-то более подходящее, но не смог подобрать более подходящее определение. хотелось указать отношение к python, и игры на pygame просто оказались самым подходящим для данного модуля. Может кто-то предложит другое удачное применение, буду только рад.


  1. Tseikovets
    27.09.2018 18:30

    Я бы советовал для всего этого использовать библиотеку Tolk, которая реализует общую обёртку API речевого вывода. Она автоматически проверяет наличие программы экранного доступа (в порядке: JAWS, Window-Eyes, NVDA, SuperNova, System Access, ZoomText) и при обнаружении запущенного экземпляра программы отправляет текст на вывод через её API, ну а если ни одной из поддерживаемых программ не обнаружено, то может выполнить речевой вывод через Microsoft Speech API 5.

    В отличие от вашей реализации, с Tolk вы получите более универсальное решение с поддержкой существенно большего числа программ экранного доступа, а также с поддержкой брайлевского вывода (где это возможно). Ну и всё это без необходимости собственноручно реализовывать и унифицировать поддержку всех API программ через их специальные dll и com-объекты, а просто одним вызовом.


    1. DollaR84 Автор
      27.09.2018 21:02

      Спасибо за информацию, не знал о такой библиотеки. Просто тут есть два момента:
      1. Данный модуль я писал в целях попробовать работу с windows SAPI5;
      2. данная библиотека хороша для больших проектов, а для тех простеньких логических игр, что я писал, необходимость ее компиляции как-то слишком сложна, по сравнению с десятком несложных строк кода.
      Да и поддержкой брайлевского вывода для игр как-то сомнительно, но может быть конечно где-то наверно.
      Как говорится: простое лучше сложного :)
      Но библиотека конечно интересная, спасибо, обязательно посмотрю.


      1. Tseikovets
        28.09.2018 00:23

        Тут следует учитывать, что NVDA всё же не единственная программа экранного доступа и даже не являющаяся по распространённости абсолютным лидером, поэтому поддержка других программ довольно актуальна. Вывод через SAPI5 для самоозвучивающихся интерфейсов является альтернативой, но не равноценной, потому что, например, фразу, произносимую через API самого screenreader'а, пользователь при необходимости может прервать, поставить на паузу, перечитать в истории произнесённых фраз и так далее, а речевой вывод через SAPI5 не такой гибкий в этом отношении, там, в частности, без специальной нетривиальной доработки всего механизма чтения придётся дослушивать до конца все фразы, даже если хочется прервать. Поэтому если есть такая возможность, то предпочтительнее использовать API программы экранного доступа. Tolk поможет с минимальными трудозатратами получить поддержку наиболее распространённых программ и в итоге обеспечить наиболее удобное решение для конечного пользователя. Впрочем, некоторые интерфейсные доработки в самой игре также не помешают, в частности, клавиатурная команда для повторного произнесения фразы с описанием.

        В качестве примеров использования вывода через Tolk, а также ещё ряда других технических приёмов обеспечения невизуальной доступности, можно посмотреть на интерпретаторы текстовых игр TadsWrapper и PlainInsteat. Там реализованы и дополнительные вещи, типа фокусируемого с клавиатуры поля текстового вывода, но что касается быстрого озвучивания, то это реализовано как раз так, как лучше всего делать: при изменении описания автоматический вывод через Tolk с поддержкой большого числа программ, плюс по горячей клавиши прочтение можно повторить.

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