Как сделать ю спик

Добавил пользователь Morpheus
Обновлено: 16.09.2024



В этой статье я хочу поделиться с вами результатами изучения основных возможностей Web Speech API (далее — WSA ).

Введение

WSA — это экспериментальная технология, состоящая из двух интерфейсов: SpeechSynthesis (интерфейс для перевода текста в речь) и SpeechRecognition (интерфейс для распознавания речи).

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

Что касается поддержки, то вот что об этом говорит Can I use:






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

Мы с вами реализуем 4 простых приложения, по 2 на каждый интерфейс:

Если вам это интересно, то прошу следовать за мной.

Плеер для озвучивания текста

Наша разметка будет выглядеть следующим образом:

У нас имеется поле для ввода текста ( textarea ), который мы будем озвучивать; выпадающий список ( select ) для выбора голоса, которым будет озвучиваться текст; инпуты-диапазоны для установки громкости ( volume ), скорости ( rate ) воспроизведения и высоты голоса ( pitch ), а также кнопки для запуска ( speak ), отмены ( cancel ), приостановления ( pause ) и продолжения ( resume ) воспроизведения. В общем, ничего особенного.

Обратите внимание на атрибуты инпутов min , max , step и value . Значения данных атрибутов взяты из черновика спецификации, но некоторые из них отданы на откуп производителям браузеров, т.е. зависят от конкретной реализации. Также обратите внимание на наличие почти у всех элементов идентификаторов. Мы будем использовать эти id для прямого доступа к элементам в скрипте в целях сокращения кода, однако в реальных приложениях так лучше не делать во избежание загрязнения глобального пространства имен.

Переходим к JavaScript . Создаем экземпляр SpeechSynthesisUtterance ("utterance" можно перевести как "выражение текста словами"):

Пытаемся получить доступные голоса (именно "пытаемся", поскольку в первый раз, по крайней мере, в Chrome возвращается пустой массив):

При вызове метода getVoices() возникает событие voiceschanged . Обрабатываем это событие для "настоящего" получения голосов и формирования выпадающего списка:

Объект голоса (назовем его так) выглядит следующим образом:

Реализуем функцию формирования выпадающего списка:

Функция инициализации обработчиков событий выглядит так:

Обработка изменения настроек:

Функция преобразования текста в речь:

После установки всех настроек наш экземпляр SpeechSynthesisUtterance выглядит следующим образом:

Уже в процессе написания статьи я решил добавить управление с помощью клавиатуры:

Поиграть с кодом можно здесь:

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

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

Наша разметка будет выглядеть так:

У нас имеется три блока ( div ) с кнопками для озвучивания текста ( play ) и, собственно, текстом, который будет озвучиваться (первые три абзаца статьи по JavaScript из Википедии). Обратите внимание, что я добавил кнопкам атрибут tabindex , чтобы переключаться между ними с помощью tab и нажимать с помощью space . Однако, имейте ввиду, что использовать атрибут tabindex не рекомендуется по причине того, что браузер использует переключение фокуса с помощью tab для повышения доступности.

С вашего позволения, я приведу код скрипта целиком:

Тонкий момент в приведенном коде — это преобразование озвучиваемого текста в массив предложений (разделителем является точка ( . )), перебор массива, и воспроизведение каждого предложения по отдельности (точнее, помещение всех предложений одного за другим в очередь на озвучивание) — textContent.split('.').forEach(. ) . Причина такого решения заключается в том, что озвучивание длинного текста тихо обрывается примерно на 220 символе (в Chrome). Черновик спецификации для такого случае предусматривает специальную ошибку text-to-long (текст слишком длинный), но данной ошибки не возникает, озвучивание просто резко прекращается, причем, для восстановления работы SpeechSynthesis зачастую приходится перезагружать вкладку (при запущенном сервере для разработки даже это не всегда срабатывает). Возможно, вам удастся найти другое решение.

Поиграть с кодом можно здесь:

"Диктофон" для распознавания речи

После того, как мы обстоятельно рассмотрели SpeechSynthesis , можно переходить ко второму, немного более сложному, но, вместе с тем, и более интересному интерфейсу, входящему в состав WSA — SpeechRecoginition .

Вот наша начальная разметка:

У нас имеется поле для вставки финального (распознанного) текста ( final_text ) и поле для вставки промежуточного (находящегося в процессе распознавания) текста ( interim_text ), а также панель управления ( buttons ). Выбор элементов textarea и input для хранения текста обусловлен как вариативностью промежуточных результатов, которые меняются на лету, так и необходимостью внесения небольших правок в распознанный текст, что связано с естественным несовершенством перевода устной речи в текст. Стоит отметить, что, в целом, Chrome очень неплохо справляется с задачей распознавания речи и автоматическим форматированием распознанного текста.

Кроме кнопок для управления распознаванием речи ( start , stop и abort ), мы реализуем возможность копирования распознанного текста в буфер обмена с помощью Clipboard API и очистки соответствующего поля.

Начнем с определения переменных для финального текста и индикатора распознавания:

Далее, создаем и настраиваем экземпляр SpeechRecognition :

Добавляем обработчики событий запуска, ошибки и окончания распознавания речи:

SpeechRecognition хорошо справляется с распознаванием слов, фраз и целых предложений, он даже выполняет вполне уместную "капитализацию" строки. Но он не "понимает" знаков препинания. Для того, чтобы помочь ему в этом определим словарь в виде объекта:

Предполагается, что для решение задач, связанных с форматированием, будут использоваться специальные объекты SpeechGrammar и SpeechGrammarList , а также специальный синтаксис JSpeech Grammar Format , однако, в данной статье мы ограничимся обычным объектом.

Вы можете добавить в словарь любые пары ключ/значение, которые посчитаете нужными. Обратите внимание на то, что все ключи в нашем словаре представлены одним словом. Дело в том, что рассматриваемый интерфейс плохо справляется с ключами, которые состоят более чем из одного слова, например, "вопросительный знак", "восклицательный знак" и т.п. Я понимаю, что пара вопрос: '?' не лучшее решение, но для примера сойдет.

Также нам потребуются две функции для редактирования промежуточного и финального результатов:

Функция editInterim() разбивает фразу на массив слов, перебирает слова, удаляет пробелы в начале и конце слова и заменяет символом из словаря при совпадении. Обратите внимание, что мы приводим слово в нижний регистр только при поиске совпадения. Если мы сделаем это в строке word = word.trim() , то нивелируем автоматическую "капитализацию" строки, выполняемую браузером.

Функция editFinal() удаляет пробел перед каждым из указанных символов — мы разделяем слова пробелами при объединении в функции editInterim() . Следует отметить, что по умолчанию каждое распознанное слово с двух сторон обрамляется пробелами.

Итак, событие, которое интересует нас больше всего — это result . Реализуем его обработку:

Событие распознавания выглядит следующим образом:

Результаты (SpeechRecognitionResultList) выглядят так:

Вот почему для получения результата мы обращаемся к e.results[i][0].transcript . На самом деле, поскольку мы указали maxAlternatives = 3 , во всех результатах будет представлено по три SpeechRecognitionAlternative . Первым (с индексом 0 ) всегда будет наиболее подходящий результат с точки зрения браузера.

Все, что нам осталось сделать, это реализовать обработку нажатия кнопок:

Тестируем. Нажимаем на кнопку "Старт", дожидаемся, когда красная точка рядом с фавиконкой перестанет мигать (о готовности к распознаванию можно сообщать пользователю через обработку события speechstart ), произносим фразу (произношение должно быть максимально четким и ясным), например, "привет точка как дела вопрос". В input на какое-то время появляется "Привет точка Как дела вопрос", затем этот промежуточный результат редактируется и переносится в textarea в виде "Привет. Как дела?". Отлично, наша машина нас понимает.

Поиграть с кодом можно здесь:

Подумал о том, что было бы неплохо реализовать функцию для удаления последнего распознанного слова на тот случай, если результат распознавания получился некорректным. Для этого потребуется пара удалить: () => removeLastWord() (если добавить эту пару в словарь, то потребуется дополнительная проверка typeof DICTIONARY[word] === 'function' ) и примерно такая операция:

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

Одностраничное приложение с голосовым управлением

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

Мы будем генерировать страницы программным способом, поэтому разметка нам не потребуется.

Создаем директорию pages с тремя файлами:

Основной скрипт начинается с импорта страниц и генерации домашней страницы:

Нам потребуются константы для прокрутки страницы и объект с операциями:

Далее следуют настройки SpeechRecognition и обработчики событий начала, ошибки и окончания распознавания, аналогичные рассмотренным в предыдущем разделе (кроме настройки языка — для управления страницей мы будем использовать американский английский: recognition.lang = 'en-US' ).

Обработка события result :

Функция для выполнения прокрутки выглядит следующим образом:

Наконец, добавляем обработку нажатия клавиш клавиатуры:

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

  • home , product , about — переключение страниц
  • dark , light — переключение цветовой темы
  • down , up , left , right — выполнение прокрутки к соответствующему разделу страницы (имеет видимый эффект только на домашней странице, иногда приходится добавлять слово scroll , например, scroll down )

Поиграть с кодом можно здесь:

Заключение

Как мы видим, WSA существенно расширяет арсенал JavaScript , связанный с добавлением динамики, "оживлением" веб-страниц. Сложно сказать, насколько широкое распространение получит данная технология и насколько активно она будет использоваться. Несмотря на то, что WSA — это технология общего назначения, очевидно, что она внесет серьезный вклад, в первую очередь, в развитие так называемого доступного Интернета.

Мы с вами рассмотрели все основные возможности, предоставляемые WSA . Единственное, что мы не сделали, это не реализовали совместное использование SpeechSynthesis и SpeechRecognition . Первое, что приходит на ум — это голосовой помощник, который реагирует на ключевые слова, встречающиеся во фразе, произнесенной пользователем, отвечая определенными шаблонами и задавая уточняющие вопросы, при необходимости. Более простой вариант: волшебный шар — задаешь любой вопрос, предполагающий однозначный ответ, программа какое-то время "думает" и отвечает да , нет или, например, не знаю, спросите позже . Пусть это будет вашим домашним заданием, все необходимые знания для этого у вас имеются. Обязательно поделитесь результатом в комментариях.

Облачные серверы от Маклауд быстрые и безопасные.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Авторизуясь в LiveJournal с помощью стороннего сервиса вы принимаете условия Пользовательского соглашения LiveJournal

Самый сок!

всё то интересное в сети, что попало в мои сети

Ду ю спик инглиш?


Говорят, что у нас в Америке полиция чуть-что начинает стрелять. Я не согласен. И вот почему.

У меня есть друг Петя. И у него есть жена Мила, которую все называют Мила-Пила. Когда этот Петя со своей Пилой приехал в Америку, то машину он купил раньше, чем выучил английский язык. И вот как-то я приглашаю их к себе на дачу в Поконо.

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

Петя не столько по словам, сколько по жестам, понимает, что с ним не шутят и возвращается в свою машину.

Мент – в полной растерянности, потому что никаких других языков кроме английского он не знает.

Я честно отвечаю, что Петя мне хорошо известен, причем с детства.

И тогда мент становится перед Петиной машиной и везёт его с мигалкой сто миль до 284-го экзита, где передаёт его мне, как говорится, с рук на руки.

Уже на даче я объясняю Пете, что у нас в Америке с ментами надо быть поосторожней, потому что таки да могут застрелить на месте.

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