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

Sim*_*tha 5 javascript text-to-speech

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

因为我在我的 speak() 函数中构造了我的 speakText 对象,所以我无法让 pause 函数访问 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;
});
Run Code Online (Sandbox Code Playgroud)

tra*_*r53 6

[..How..] 通过将按钮链接到 synth.pause(speakText) 来添加暂停按钮;

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

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

你在这里触及了这个问题:

因为我在我的 speak() 函数中构造了我的 speakText 对象,所以我无法让 pause 函数访问 speakText。

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

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

"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);
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

引用的 MDN 页面的链接是https://mdn.github.io/web-speech-api/speak-easy-synthesis/