Использование синтеза речи для произнесения массива строк с паузами между ними.

Я пытаюсь найти надежный способ передать массив строк в API синтеза речи с паузами между произнесением каждого элемента массива. Например. произнести пункт 1, сделать паузу на x секунд, произнести пункт 2 и т. д.

Я попытался использовать метод/событие onend API, но он работает только несколько раз, прежде чем перестает работать полностью, считывая остальные элементы массива подряд с этого момента и далее.

Предложения?

var dropdown = $('#item-select'),
  interval = $('#item-interval').val() * 1000,
  itemBtn = $('#item-btn'),
  stopBtn = $('#item-stop'),
  items = {
    'first': ['hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine', 'hello, sunshine'],
    'second': ['hello, world', 'hello, world', 'hello, world', 'hello, world', 'hello, world', 'hello, world', 'hello, world', 'hello, world', 'hello, world', 'hello, world', 'hello, world', 'hello, world', 'hello, world']
  };

if ('speechSynthesis' in window) {
  function speak(text) {
    var msg = new SpeechSynthesisUtterance();
    msg.text = text;

    speechSynthesis.speak(msg);
    
    msg.addEventListener('end', function(e) {
      speechSynthesis.pause();
      window.setTimeout(function() {
        speechSynthesis.resume();
      }, interval);
    });
  }
  
  itemBtn.on('click', function(evt) {
    currItem = items[dropdown.val()];
    for (var phrase in currItem) {
      speak(currItem[phrase]);
    }
  });
  stopBtn.on('click', function(evt) {
    speechSynthesis.cancel();
  });
} else {
  console.log('Voice synthesis isn\'t supported in your browser.');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<select id='item-select'>
  <option selected value='first'>First Item</option>
  <option value='second'>Second Item</option>
</select>
<label for='item-interval'>Interval (seconds)</label>
<input id='item-interval' max='10' name='item-interval' type='range' value='2'>
<button id='item-btn'>Speak!</button>
<button id='item-stop'>CEASE FIRE</button>


person Jesse Dupuy    schedule 14.05.2016    source источник


Ответы (1)


Как насчет рекурсивного путешествия с задержкой по тайм-ауту через массив элементов:

function speak(list) {
    if (list.length) {
      var msg = new SpeechSynthesisUtterance();
      msg.text = list[0];

      speechSynthesis.speak(msg);

      msg.addEventListener('end', function(e) {
        window.setTimeout(() => {
            speak(list.slice(1));
        }, interval);
      });
    }
  }

  itemBtn.on('click', function(evt) {
    const list = items[dropdown.val()];  
    speak(list);
  });

Это сработало для меня, но затем я столкнулся с некоторой странностью. Время от времени SpeechSynthesis просто ПРЕКРАТИЛ запуск события «конец»:

Эта скрипка добавляет несколько журналов, чтобы показать, когда высказывание начинается/заканчивается; наблюдайте, не прекращается ли событие 'end' просто без причины.

https://jsfiddle.net/cak4bju9/2/

Этот пост стека о ошибочном поведении был полезен:

обратный вызов SpeechSynthesis API не работает

person uncleoptimus    schedule 16.09.2016
comment
Интересная идея - обязательно попробую, вдруг поможет! В то же время, чтобы исправить конечное событие, которое не срабатывает, этот ответ в сообщении, на которое вы ссылаетесь, был для меня наиболее полезным: stackoverflow.com/a /35935851/1505423. Спасибо, что нашли время, чтобы изучить это! - person Jesse Dupuy; 19.09.2016