Речь обрывается в Firefox, когда страница автоматически обновляется, но не в Google Chrome.

У меня есть проблема, когда в Firefox речь отключается, если страница автоматически обновляется, но в Google Chrome она заканчивает произносить речь, даже если страница автоматически обновляется. Как это исправить, чтобы речь не была обрезана в Firefox, даже когда страница автоматически обновляется?

msg = new SpeechSynthesisUtterance("say something");
window.speechSynthesis.speak(msg);

4 ответа

У меня есть проблема, когда в Firefox речь отключается, если страница автоматически обновляется, но в Google Chrome она заканчивает произносить речь, даже если страница автоматически обновляется.

Описанное поведение для Firefox является разумной ожидаемой реализацией.

Просмотр исходного кода Firefox и Chromium о реализации speechSynthesis.speak() основан на сокетном соединении с локальным речевым сервером. Этот сервер в * nix обычно speech-dispatcher или же speechd (speech-dispatcher). См. Как программно отправить команду сокета unix на системный сервер, автоматически созданный браузером, или преобразовать JavaScript в C++ souce-код для Chromium? за описание попытки реализовать SSML-разбор в Chromium.

В конце концов решили написать собственный код для выполнения этого требования, используя JavaScript в соответствии со спецификацией W3C https://github.com/guest271314/SpeechSynthesisSSMLParser, задав несколько вопросов на сайтах SE, регистрируя проблемы и ошибки и публикуя их в списках рассылки W3C без каких-либо доказательств того, что синтаксический анализ SSML когда-либо будет включен как часть. API веб-речи.

Как только это соединение инициировано, создается очередь для вызовов .speak(), Даже когда соединение закрыто Task Manager может по-прежнему отображать активный процесс, зарегистрированный службой.

Процесс в Chromium/Chrome не без ошибок, наиболее близким к тому, что описано в вопросе, является

.volume имущественные вопросы

Наиболее вопиющей проблемой является Хром / Хром webkitSpeechReconition реализация, которая записывает аудио пользователя и передает эти аудиоданные в удаленную службу, где транскрипт возвращается в браузер - без явного уведомления пользователя, который имеет место, помеченный WONT FIX

Соответствующие проблемы W3C Speech API на GitHub


Таким образом, не будет описывать поведение в Firefox как "проблему", но поведение в Chrome как потенциальную "проблему".

Погружение в реализацию W3C Web Speech API в браузерах не является тривиальной задачей. По нескольким причинам. Включая очевидную направленность или доступный вариант коммерческих услуг TTS/SST и проприетарных реализаций синтеза и распознавания речи с закрытым исходным кодом в "смартфонах"; вместо исправления различных проблем с фактическим развертыванием W3C Web Speech API в современных браузерах.

Сопровождающие speechd (речь-диспетчер) очень полезна в отношении серверной части (локальная speech-dispatcher разъем).

Не могу говорить за сопровождающих Firefox. Предполагается, что маловероятно, что если будет подана ошибка, относящаяся к запросу функции продолжения выполнения аудиовыхода .speak() от перезагрузки window согласуется с последними политиками автозапуска, реализованными браузерами. Хотя вы все равно можете отправить сообщение об ошибке в Firefox, чтобы спросить, будет ли аудио выход (из любого API или интерфейса) продолжаться во время перезагрузки текущего window; и если есть какие-либо предпочтения или политики, которые можно установить для переопределения описанного поведения, как предложено в ответе @zip. И получите ответ от самих разработчиков.

Есть отдельные люди и группы, которые составляют код FOSS, которые активны в домене и готовы помочь в разработке SST/TTS, многие из которых активны в GitHub, что является еще одним вариантом, чтобы задавать вопросы о том, как реализовать то, что вы пытаетесь достичь конкретно в браузере Firefox.

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

Экспериментальная технология, вероятно, не правильно обрабатывается Firefox.

Попробуйте SpeechSynthesis.cancel() перед повторением вашего .speak() вызов.

msg = new SpeechSynthesisUtterance("say something");
window.speechSynthesis.cancel();
window.speechSynthesis.speak(msg);

EDITED: см. Более элегантное решение с обещаниями ниже первоначального ответа!


Ниже фрагмент кода - обходной путь к несоответствиям браузера, обнаруженным в Firefox, проверка synth.speaking в интервале и запускает перезагрузку только в том случае, если false предотвращает преждевременное отключение синтезатором:

(Он НЕ работает должным образом в фрагменте SO, я предполагаю, что ему не нравятся iFrames в iFrames или что-то еще, просто скопируйте и вставьте код в файл и откройте его в Firefox!)

<p>I'm in the body, but will be in an iFrame</p>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
 var synth = window.speechSynthesis;
 msg = new SpeechSynthesisUtterance("please finish saying this entire sentence.");
 synth.speak(msg);
 
 (function ($) {
  'use strict';
  if (window == window.top) {
   var body = $('body').empty();
   var myframe = $('<iframe>')
    .attr({ src: location.href })
    .css({ height: '95vh', width: '100%' })
    .appendTo(body)
    .on('load', function () {
     var interval;
     interval = setInterval(function () {
      if (!synth.speaking) {
       myframe.attr({ src: location.href });
       clearInterval(interval);
      }
     }, 750);
    });
  }
 })(jQuery);
</script>

Более продуманным решением может быть отсутствие каких-либо setTimeout() или setInterval()вообще, но вместо этого используйте обещания. Таким образом, страница будет просто перезагружаться всякий раз, когда сообщение будет синтезировано, независимо от того, насколько оно короткое или длинное. Это также предотвратит "двойную" / перекрывающуюся речь при начальной загрузке страницы. Не уверен, что это поможет в вашем сценарии, но вот вам:

<button id="toggleSpeech">Stop Speaking!</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
 if (window == window.top) {
  window.speech = {
   say: function(msg) {
    return new Promise(function(resolve, reject) {
     if (!SpeechSynthesisUtterance) {
      reject('Web Speech API is not supported');
     }
     
     var utterance = new SpeechSynthesisUtterance(msg);
     
     utterance.addEventListener('end', function() {
      resolve();
     });
     
     utterance.addEventListener('error', function(event) {
      reject('An error has occurred while speaking: ' + event.error);
     });
     
     window.speechSynthesis.speak(utterance);
    });
   },
   speak: true,
  };
 }
 
 
 (function($) {
  'use strict';

  if (window == window.top) {
   var body = $('body').empty();
   var myframe = $('<iframe>')
    .attr({ src: location.href })
    .css({ height: '95vh', width: '100%' })
    .appendTo(body)
    .on('load', function () {
     var $iframe = $(this).contents();

     $iframe.find('#toggleSpeech').on('click', function(e) {
      console.log('speaking will stop when the last sentence is done...');
      window.speech.speak = !window.speech.speak;
     });
     
     window.speech.say('please finish saying this entire sentence.')
      .then(function() {
       if ( window.speech.speak ) {
        console.log('speaking done, reloading iframe!');
        myframe.attr({ src: location.href });
       }
      });
    });
  }
 })(jQuery);
</script>

ПРИМЕЧАНИЕ. Chrome (начиная с версии 70) НЕ позволяет немедленный вызовwindow.speechSynthesis.speak(new SpeechSynthesisUtterance(msg)) больше вы получите сообщение об ошибке speechSynthesis.speak() without user activation is no longer allowed..., подробнее здесь. Так что технически пользователь должен активировать скрипт в Chrome, чтобы он заработал!

Не уверен, почему есть разница в поведении... guest271314 может быть что-то в его ответе. Тем не менее, вы можете быть в состоянии предотвратить FF от остановки tts, перехватывая событие перезагрузки с onbeforeunload обработчик и ждет окончания произнесения:

msg = new SpeechSynthesisUtterance("say something");
window.speechSynthesis.speak(msg);
window.onbeforeunload = function(e) {
  if(window.speechSynthesis.speaking){
    event.preventDefault();
    msg.addEventListener('end', function(event) {
      //logic to continue unload here
    });
  }
};

Fire Fox:

Прежде всего введите и найдите "about: config" в браузере, заполнив его в адресной строке. Это перейдет на другую страницу, где будет всплывающее окно с просьбой принять любой риск, вы должны принять это. Найдите в списке параметр с именем "accessibility.blockautorefresh" и щелкните его правой кнопкой мыши. На экране появятся некоторые параметры в виде списка, выберите параметр "Переключить" и установите для него значение "Истина", а не "Ложь". Это изменение заблокирует автоматическое обновление в браузере Firefox. Помните, что эта опция обратима!

Другие вопросы по тегам