向语音合成API添加暂停和播放功能

时间:2019-01-03 00:19:59

标签: javascript text-to-speech

我是JavaScript的新手,我想通过将按钮链接到synth.pause(speakText);(其中const synth = window.speechSynthesis;const speakText = new SpeechSynthesisUtterance(textInput.value);)来添加暂停按钮。

因为我在我的say()函数中构造了自己的sayText对象,所以我无法使pauseText可以访问speakText。我试图通过在函数外部调用其构造函数来使speakText成为全局变量,但这会导致speak()抛出错误。

关于如何实现这一目标的任何想法吗?

JS代码:

//Speak
const speak = () => {
  //Check to see if already speaking
  if (synth.speaking && state === "play") {
    console.error("Already speaking");
    state = "paused";
    console.log("state: " + state);
    return;
  }
  //Make sure there is some input
  if (textInput.value !== "" && state === "stop") {
    const speakText = new SpeechSynthesisUtterance(textInput.value);
    state = "play";

    //Speak error
    speakText.onerror = e => {
      console.log("Something went wrong!");
    };

    //Selected voice
    const selectedVoice = voiceSelect.selectedOptions[0].getAttribute(
      "data-name"
    );

    //Loop through voices to set the correct voice
    voices.forEach(voice => {
      if (selectedVoice === voice.name) {
        speakText.voice = voice;
      }
    });

    //Set the rate and pitch
    speakText.rate = rate.value;
    speakText.pitch = pitch.value;

    //Speak end
    speakText.onend = e => {
      console.log("Done Speaking");
      state = "stop";
    };

    speakController(speakText);
  }
};

const speakController = speakText => {
  console.log("state: " + state);
  if (state === "play") {
    synth.speak(speakText);
  } else if (state === "pause") {
    synth.pause(speakText);
  } else if (state === "stop") {
    synth.cancel(speakText);
  }
};

//----------EVENT LISTENERS----------
var state = "stop";

// Text form submit
textForm.addEventListener("submit", e => {
  e.preventDefault();
  speak();
  textInput.blur();
});

//Pause button
pauseButton.addEventListener("onClick", e => {
  e.preventDefault();
  speakController;
});

1 个答案:

答案 0 :(得分:2)

  

[.. how ..]通过将按钮链接到synth.pause(speakText);

便宜的答案是进行按钮调用speechSynthesis.pause()(不带参数)-因为synth只是全局window.speechSynthesis属性的副本。

一个更好的解决方案是创建一个控制器,该控制器向外部调用者公开方法和属性的接口,并封装其自身的内部工作原理。

您在这里谈到了这个问题:

  

由于我在我的say()函数中构造了自己的sayText对象,因此我无法使pauseText可以访问talkText。

这意味着存在代码结构设计问题。但是还有另一个问题:语音合成器没有“播放”,“暂停”和“停止”状态。它具有“播放”和“暂停”两个互斥的状态,以及“队列为空”的完全独立的条件。

尽管我确实尝试过,但我不建议修复发布的代码。这就是我最终确定正在发生什么的原因-它是实验性代码,但希望播客会有所帮助!

"use strict";
const tr = {
	queue: null,
	pause: null,
	play:  null,
	cancel:  null,
	defaultRate: 1.1,
	defaultPitch: 1,
	// voice selection to do;
};
function createTextReader( tr) {
	let synth = window.speechSynthesis; // abbreviation
	let Utter = SpeechSynthesisUtterance; // abbreviation
	// queue
	tr.queue = (text, rate, pitch, voiceIndex) => {
		let utter = new Utter();
		utter.text = text;
		utter.rate = rate || tr.defaultRate || 1;
		utter.pitch = pitch || tr.defaultPitch || 1;
		// voice selection to do
		// if( voiceParam) ....
		synth.speak( utter);
	};
	tr.pause = () => synth.pause();
	tr.play = () => synth.resume();
	tr.cancel = () => synth.cancel();
}
window.addEventListener( "DOMContentLoaded", function (e) {
createTextReader( tr)}, false);
window.addEventListener("unload", e=>tr.cancel(), false);
<textarea cols=40 rows=4 id="queueText">
Press "queue text" to add text area content to the text reader. Press it multiple times to add text more than once.

Press "pause" to pause reading.

Press "play" to start or resume reading queued text from the speech synthesizer's fifo queue. Play mode is in effect at startup - but you could pause the reader before queuing text.

Press "cancel" to stop reading and empty the queue. It does not change pause versus play mode. If the reader is paused when cancel is clicked, it remains so afterwards.

This voice is the default voice in this browser, and may be different in another. More code is needed for voice selection. If you visit MDN's speech synthesis example on git hub, view page source and click on the link to "script.js" you can see how they do it.

Oh, and don't forget to cancel speech synthesis on window unload.

Thanks for listening!
</textarea><br>
<button type="button" onclick="tr.queue(queueText.value)">queue text</button>
<p>
<button type="button" onclick="tr.pause()">pause</button>
<button type="button" onclick="tr.play()">play</button>
<button type="button" onclick="tr.cancel()">cancel</button>
<p>

所指向的MDN页面的链接为https://mdn.github.io/web-speech-api/speak-easy-synthesis/