SpeechSynthesis не работает в мобильном Safari, хотя он поддерживается - PullRequest
5 голосов
/ 07 мая 2020

Я пытаюсь использовать SpeechSynthesis API. Он работает в настольных браузерах и мобильных Chrome, но не в мобильном Safari.

  const msg = new SpeechSynthesisUtterance("Hello World");
  window.speechSynthesis.speak(msg);

Я добавил небольшой тест, и кажется, что API поддерживается в Safari, может быть проблема с разрешениями, что он не работает?

  if ("speechSynthesis" in window) {
    alert("yay");
  } else {
    alert("no");
  }

Ответы [ 2 ]

1 голос
/ 27 мая 2020

Это может быть просто вопрос времени получения голосов, поэтому, если мы запросим их при загрузке страницы, они будут готовы до того, как пользователь нажмет кнопку «Говорить».

Я не вставил любой тайм-аут для упрощения примера.

if ( 'speechSynthesis' in window ) {
  speechSynthesis.cancel(); // removes anything 'stuck'
  speechSynthesis.getVoices();
  // Safari loads voices synchronously so now safe to enable
  speakBtn.disabled = false;
}

const speak = () => {
  const utter = new SpeechSynthesisUtterance();
  utter.text = textToSpeak.value || textToSpeak.placeholder;
  speechSynthesis.speak(utter);
};  

speakBtn.addEventListener('click', speak);
<input type="text" id="textToSpeak" placeholder="1, 2, 3">
<button type="button" id="speakBtn" disabled>Speak</button>

Это очень простой пример c, без выбора голоса или любого языка.

Если это не так по работе есть еще одна проблема. Вы проверили, что звук работает на вашем устройстве? Включено ли « мягкое отключение звука »?

0 голосов
/ 22 мая 2020

С моей стороны, проблема была связана с правильным загрузкой синтеза речи на мобильном Safari.

Есть некоторые вещи, которые нужно проверить по порядку:

  • загружены ли голоса?
  • установлены ли голоса в вашей системе?
  • выражение настроено правильно?
  • вызывается ли функция речи из события взаимодействия с пользователем?

В следующем примере суммируются эти проверки и они работают в настольных браузерах MacOS плюс iOS Safari:

let _speechSynth
let _voices
const _cache = {}

/**
 * retries until there have been voices loaded. No stopper flag included in this example. 
 * Note that this function assumes, that there are voices installed on the host system.
 */

function loadVoicesWhenAvailable (onComplete = () => {}) {
  _speechSynth = window.speechSynthesis
  const voices = _speechSynth.getVoices()

  if (voices.length !== 0) {
    _voices = voices
    onComplete()
  } else {
    return setTimeout(function () { loadVoicesWhenAvailable(onComplete) }, 100)
  }
}

/**
 * Returns the first found voice for a given language code.
 */

function getVoices (locale) {
  if (!_speechSynth) {
    throw new Error('Browser does not support speech synthesis')
  }
  if (_cache[locale]) return _cache[locale]

  _cache[locale] = _voices.filter(voice => voice.lang === locale)
  return _cache[locale]
}

/**
 * Speak a certain text 
 * @param locale the locale this voice requires
 * @param text the text to speak
 * @param onEnd callback if tts is finished
 */

function playByText (locale, text, onEnd) {
  const voices = getVoices(locale)

  // TODO load preference here, e.g. male / female etc.
  // TODO but for now we just use the first occurrence
  const utterance = new window.SpeechSynthesisUtterance()
  utterance.voice = voices[0]
  utterance.pitch = 1
  utterance.rate = 1
  utterance.voiceURI = 'native'
  utterance.volume = 1
  utterance.rate = 1
  utterance.pitch = 0.8
  utterance.text = text
  utterance.lang = locale

  if (onEnd) {
    utterance.onend = onEnd
  }

  _speechSynth.cancel() // cancel current speak, if any is running
  _speechSynth.speak(utterance)
}

// on document ready
loadVoicesWhenAvailable(function () {
 console.log("loaded") 
})

function speak () {
  setTimeout(() => playByText("en-US", "Hello, world"), 300)
}
<button onclick="speak()">speak</button>

Подробная информация о коде добавляется в виде комментариев во фрагменте.

...