ä½¿ç¨ Web Speech API
Web Speech API æä¾äºä¸¤ä¸ªä¸åé¢åçåè½ââè¯é³è¯å«åè¯é³åæï¼ä¹è¢«ç§°ä¸ºææ¬è½¬ä¸ºè¯é³ï¼æ ttsï¼ââè¿ä¸ºæ éç¢åæ§å¶æºå¶å¼å¯äºæ°çæè¶£çå¯è½ãè¿ç¯æç« æä¾äºè¿ä¸¤ä¸ªæ¹åçç®åä»ç»ï¼å¹¶ä¸é½å¸¦æä¾åã
è¯é³è¯å«
è¯é³è¯å«æ¶åï¼éè¿è®¾å¤ç麦å 飿¥æ¶è¯é³ï¼ç¶åè¯é³è¯å«æå¡ä¼æ ¹æ®è¯æ³å表ï¼åºæ¬ä¸å°±æ¯ä½ 叿å¨å ·ä½çåºç¨ä¸è½å¤è¯å«åºæ¥çè¯æ±ï¼æ¥æ£æ¥è¿æ®µè¯é³ã彿åè¯å«åè¯æçè¯åï¼ç»æï¼æç»æå表ï¼ä¼ä»¥ææ¬å符串çå½¢å¼è¿åï¼å¹¶ä¸å¯ä»¥æ ¹æ®ç»æè¿è¡ä¸ä¸æ¥çæä½ã
Web Speech API æä¸ä¸ªä¸»è¦çæ§å¶å¨æ¥å£ââSpeechRecognitionï¼å¤å ä¸äºä¸è¡¨ç¤ºè¯æ³ãç»æçç亲å¯ç¸å
³çæ¥å£ãé常ï¼è®¾å¤é½æå¯ä½¿ç¨çé»è®¤è¯é³è¯å«ç³»ç»ï¼å¤§é¨åç°ä»£æä½ç³»ç»é½æç¨äºååºè¯é³å½ä»¤çè¯é³è¯å«ç³»ç»ï¼æ¯å¦ Mac OS X ä¸ç DictationãiOS ä¸ç SiriãWin10 ä¸ç CortanaãAndroid Speech ççã
夿³¨ï¼å¨ä¸äºæµè§å¨ä¸ï¼æ¯å¦ Chromeï¼å¨ä¸ä¸ªç½é¡µä¸ä½¿ç¨ Web è¯é³è¯å«æ¶åå°ä¸ä¸ªåºäºæå¡å¨çè¯å«å¼æãä½ çé³é¢ä¼è¢«åéå°ä¸ä¸ª web æå¡ä»¥è¿è¡è¯å«å¤çï¼æä»¥å®ä¸è½å¨ç¦»çº¿ç¶æä¸å·¥ä½ã
æ¼ç¤º
为äºå±ç¤º Web è¯é³è¯å«çç®åç¨æ³ï¼æä»¬ç¼åäºä¸ä¸ªæ¼ç¤ºââSpeech color changerãç¹å»å±å¹ä¹åï¼è¯´åº HTML é¢è²å ³é®åï¼æ¥ä¸æ¥åºç¨çèæ¯é¢è²å°±ä¼åæä½ 说çé¢è²ã

è¦è¿è¡è¿ä¸ªæ¼ç¤ºï¼è¯·å¨æ¯æçç§»å¨ç«¯æµè§å¨ï¼æ¯å¦ Chromeï¼ä¸æå¼å¨çº¿æ¼ç¤º URLã
HTML å CSS
对äºè¿ä¸ªåºç¨æ¥è¯´ï¼HTML å CSS é¨åæ¯æ 足轻éçãä» ä» åªæä¸ä¸ªæ é¢ãä¸ä¸ªä»ç»æ®µè½åä¸ä¸ªç¨æ¥è¾åºè¯æä¿¡æ¯ç divã
<h1>Speech color changer</h1>
<p>Tap/click then say a color to change the background color of the app.</p>
<div>
<p class="output"><em>...diagnostic messages</em></p>
</div>
CSS ä¹åªæ¯æä¾äºç®åçååºå¼æ ·å¼ï¼è·¨è®¾å¤çä¸å»ä¹æ¯ ok çã
JavaScript
JavaScript é¨åä¼ä»ç»æ´å¤ç»èã
带åç¼ç屿§
æµè§å¨ç®åéè¿å¸¦æåç¼ç屿§æä¾è¯é³è¯å«çæ¯æãå æ¤å¨ä»£ç å¼å§é¨åæä»¬æ·»å äºä»¥ä¸ä»£ç ï¼ä»¥ä¾¿åæ¶æ¯æå¸¦åç¼ç屿§åæªæ¥å¯è½æ¯æçä¸å¸¦åç¼ç屿§ï¼
const SpeechRecognition =
window.SpeechRecognition || window.webkitSpeechRecognition;
const SpeechGrammarList =
window.SpeechGrammarList || window.webkitSpeechGrammarList;
const SpeechRecognitionEvent =
window.SpeechRecognitionEvent || window.webkitSpeechRecognitionEvent;
è¯æ³
代ç çä¸ä¸é¨åå®ä¹äºæä»¬å¸æåºç¨ç¨åºè¯å«çè¯æ³ãå®ä¹äºä»¥ä¸åé以ä¿åæä»¬çè¯æ³ï¼
const colors = [
"aqua",
"azure",
"beige",
"bisque",
"black",
"blue",
"brown",
"chocolate",
"coral" /* ⦠*/,
];
const grammar = `#JSGF V1.0; grammar colors; public <color> = ${colors.join(
" | ",
)};`;
è¯æ³æ ¼å¼ä½¿ç¨çæ¯ JSpeech Grammar Formatï¼JSGFï¼ââä½ å¯ä»¥å¨åé¢ç龿¥ä¸äºè§£æ´å¤å ³äºè¯æ³æ ¼å¼çè§èãä¸è¿ç°å¨ï¼è®©æä»¬å¿«éå°æµè§å®ï¼
- æ¯ä¸è¡ç¨åå·åéï¼å JavaScript ä¸ä¸æ ·
- 第ä¸è¡ââ
#JSGF V1.0ââè¯´çæ¯è¯æ³ä½¿ç¨çæ ¼å¼åçæ¬ãè¿æ»æ¯éè¦é¦å å æ¬å¨å - 第äºè¡è¡¨ç¤ºæä»¬æ³è¦è¯å«çæ¯è¯ç±»åã
public声æè¿æ¯ä¸æ¡å ¬å ±è§åï¼å°æ¬å·ä¸çå符串å®ä¹éè¦è¯å«æ¯è¯çååï¼colorï¼ï¼çå·åé¢çæ¯è¿ä¸ªæ¯è¯å¯ä»¥è¢«è¯å«åæ¥åçå ·ä½å¼ã徿³¨ææ¯ä¸ä¸ªå¼å¦ä½è¢«ä¸ä¸ªç®¡é符å·åå²å¼ç - ä½ å¯ä»¥æç §ä¸é¢çç»æï¼å¨å¤è¡ä¸ï¼æ³å®ä¹å¤å°å°±å®ä¹å¤å°æ¯è¯ï¼ä¹å¯ä»¥å æ¬ç¸å½å¤æçè¯æ³å®ä¹ãå¯¹äºæä»¬è¿ä¸ªç®åçæ¼ç¤ºï¼å°±æè¯æ³å®ä¹çç®åäºã
å°è¯æ³æå ¥è¯é³è¯å«
æ¥ä¸æ¥æ¯ä½¿ç¨ SpeechRecognition() æé 彿°ï¼å®ä¹ä¸ä¸ªè¯é³è¯å«å®ä¾ï¼æ§å¶å¯¹äºè¿ä¸ªåºç¨çè¯å«ãè¿éè¦ä½¿ç¨ SpeechGrammarList() æé 彿°ï¼å建ä¸ä¸ªè¯é³è¯æ³å表对象æ¥å
嫿们çè¯æ³ã
const recognition = new SpeechRecognition();
const speechRecognitionList = new SpeechGrammarList();
ä½¿ç¨ SpeechGrammarList.addFromString() æè¯æ³æ·»å å°å表 (list)ï¼è¿ä¸ªæ¹æ³æ¥æ¶ä¸¤ä¸ªåæ°ï¼ç¬¬ä¸ä¸ªæ¯æä»¬æ³è¦æ·»å çå
å«è¯æ³å
容çå符串ï¼ç¬¬äºä¸ªæ¯å¯¹æ·»å çè¿æ¡è¯æ³çæé (æéå¼èå´æ¯ 0~1)ï¼æéå
¶å®æ¯ç¸å¯¹äºå
¶ä»è¯æ³ï¼è¿ä¸æ¡è¯æ³çéè¦ç¨åº¦ãæ·»å å°å表çè¯æ³å°±æ¯å¯ç¨çï¼å¹¶ä¸æ¯ä¸ä¸ªSpeechGrammar å®ä¾ã
speechRecognitionList.addFromString(grammar, 1);
æä»¬ç¶åéè¿è®¾ç½® SpeechRecognition.grammars 屿§å¼ï¼ææä»¬çSpeechGrammarList æ·»å å° speech recognition å®ä¾ãå¨ç»§ç»å¾åèµ°ä¹åï¼æä»¬è¿éè¦è®¾ç½® recognition å®ä¾å
¶ä»çä¸äºå±æ§ï¼
SpeechRecognition.langï¼è®¾ç½®è¯å«çæ¯ä»ä¹è¯è¨ãè¿ä¸ªè®¾å®æ¯è¯å¥½çå好ï¼å æ¤å¢è£æ¨è~SpeechRecognition.interimResultsï¼å®ä¹ speech recognition ç³»ç»è¦ä¸è¦è¿å临æ¶ç»æ (interim results)ï¼è¿æ¯åªè¿åæç»ç»æã对äºè¿ä¸ªç®å demoï¼åªè¿åæç»ç»æå°±å¤äºãSpeechRecognition.maxAlternativesï¼å®ä¹æ¯æ¬¡ç»æè¿åçå¯è½å¹é å¼çæ°éãè¿ææ¶æç¨ï¼æ¯å¦è¦çç»æä¸æç¡®ï¼ä½ æ³è¦ç¨ä¸ä¸ªå表å±ç¤ºææå¯è½å¼ï¼è®©ç¨æ·èªå·±ä»ä¸éæ©ä¸ä¸ªæ£ç¡®çãä½è¿éè¿ä¸ªç®å demo å°±ä¸ç¨äºï¼å æ¤æä»¬è®¾ç½®ä¸º 1(1 ä¹å°±æ¯é»è®¤å¼)ã
recognition.grammars = speechRecognitionList;
recognition.continuous = false;
recognition.lang = "en-US";
recognition.interimResults = false;
recognition.maxAlternatives = 1;
å¼å§è¯é³è¯å«
å¨è·åè¾åºç<div> å html å
ç´ å¼ç¨ä¹å (è¿äºæä»¬å¯ä»¥ç¨æ¥å¾
ä¼è¾åºè¯é³è¯å«è¯æçç»æï¼æ´æ°åºç¨çèæ¯é¢è²)ï¼æä»¬æ·»å äºä¸ä¸ªonclick äºä»¶å¤çï¼ä½ç¨æ¯å½å±å¹è¢«ç¹å»åï¼è¯é³è¯å«æå¡å°å¼å¯ââè¿éè¿è°ç¨ SpeechRecognition.start() å®ç°ãforEach() æ¹æ³å
é¨ç工使¯ï¼ä¸ºæ¯ä¸ªé¢è²å
³é®åæ·»å ä¸ä¸ªè¿ä¸ªé¢è²çèæ¯è²ï¼è¿æ ·å°±ç´è§ç¥éäºè¿ä¸ªé¢è²å
³é®åæåä»ä¹é¢è²ã
const diagnostic = document.querySelector(".output");
const bg = document.querySelector("html");
const hints = document.querySelector(".hints");
let colorHTML = "";
colors.forEach((color, i) => {
console.log(color, i);
colorHTML += `<span style="background-color:${color};"> ${color} </span>`;
});
hints.innerHTML = `Tap or click then say a color to change the background color of the app. Try ${colorHTML}.`;
document.body.onclick = () => {
recognition.start();
console.log("Ready to receive a color command.");
};
æ¥æ¶ãå¤çç»æ
䏿¦è¯é³è¯å«å¼å§ï¼æè®¸å¤ event handlers å¯ä»¥ç¨äºåç»æè¿åçåç»æä½ï¼é¤äºè¯å«çç»æå¤è¿æäºé¶ç¢çç¸å
³ä¿¡æ¯å¯ä¾æä½ (坿¥ç SpeechRecognition event handlers list )ãæå¸¸è§ä¼ä½¿ç¨çä¸ä¸ªæ¯ SpeechRecognition.onresult ï¼è¿å¨æ¶å°ä¸ä¸ªæåçç»ææ¶å触åã
recognition.onresult = (event) => {
const color = event.results[0][0].transcript;
diagnostic.textContent = `Result received: ${color}.`;
bg.style.backgroundColor = color;
console.log(`Confidence: ${event.results[0][0].confidence}`);
};
代ç ä¸ç¬¬ä¸è¡çä¸å»æä¸ç¹å¤æï¼è®©æä»¬ä¸æ¥ä¸æ¥è§£é以ä¸ãSpeechRecognitionEvent.results 屿§è¿åçæ¯ä¸ä¸ªSpeechRecognitionResultList 对象 (è¿ä¸ªå¯¹è±¡ä¼å
å«SpeechRecognitionResult 对象们)ï¼å®æä¸ä¸ª getterï¼æä»¥å®å
å«çè¿äºå¯¹è±¡å¯ä»¥åä¸ä¸ªæ°ç»è¢«è®¿é®å°ââæä»¥[last] è¿åçæ¯æå¨æåä½ç½® (ææ°) çSpeechRecognitionResultå¯¹è±¡ãæ¯ä¸ªSpeechRecognitionResult 对象å
å«ç SpeechRecognitionAlternative å¯¹è±¡å«æä¸ä¸ªè¢«è¯å«çåè¯ãè¿äºSpeechRecognitionResult å¯¹è±¡ä¹æä¸ä¸ª getterï¼æä»¥[0] è¿åçæ¯å
¶ä¸å
å«ç第ä¸ä¸ªSpeechRecognitionAlternative 对象ãæåè¿åçtranscript屿§å°±æ¯è¢«è¯å«åè¯çåç¬¦ä¸²ï¼æèæ¯é¢è²è®¾ç½®ä¸ºè¿ä¸ªé¢è²ï¼å¹¶å¨ UI 䏿¥ååºè¿ä¸ªç»æä¿¡æ¯ã
ä¹ä½¿ç¨äº SpeechRecognition.onspeechend è¿ä¸ª handle 忢è¯é³è¯å«æå¡ (å
·ä½å·¥ä½å¨SpeechRecognition.stop()) ï¼ä¸æ¦ä¸ä¸ªåè¯è¢«è¯å«å°±ä¸è½åè¯´å¯ (å¿
é¡»åç¹å»å±å¹å次å¼å¯è¯é³è¯å«)
recognition.onspeechend = () => {
recognition.stop();
};
å¤çéè¯¯åæªè½è¯å«çè¯é³
æå两个å¤çå¨å¤ççä¸¤ç§æ åµï¼ä¸ç§æ¯ä½ 说çå 容ä¸å¨å®ä¹çè¯æ³ä¸æä»¥è¯å«ä¸äºï¼å¦ä¸ç§æ¯åºç°äº errorã
SpeechRecognition.onnomatch æ¯æçå°±æ¯ç¬¬ä¸ç§ï¼ä½æ¯å¾æ³¨æå®ä¼¼ä¹å¨ Firefox æè
Chrome ä¸è§¦å伿é®é¢ï¼å®åªæ¯è¿åä»»ä½è¢«è¯å«çå
容ï¼
recognition.onnomatch = (event) => {
diagnostic.textContent = "I didn't recognize that color.";
};
SpeechRecognition.onerror å¤ççæ¯ç¬¬äºç§æ
åµï¼è¯å«æåäºä½æ¯æ error åºç°ââSpeechRecognitionError.error 屿§å
å«çä¿¡æ¯å°±æ¯è¿åçç¡®åç error æ¯ä»ä¹ã
recognition.onerror = (event) => {
diagnostic.textContent = `Error occurred in recognition: ${event.error}`;
};
è¯é³åæ
è¯é³åæï¼ä¹è¢«ç§°ä½ææ¬è½¬è¯é³æ TTSï¼å æ¬æ¥æ¶ app ä¸éè¦è¯é³åæçææ¬ï¼åå¨è®¾å¤æ¬å£°å¨æé³é¢è¾åºè¿æ¥ä¸ææ¾åºæ¥è¿ä¸¤ä¸ªè¿ç¨ã
Web Speech API å¯¹æ¤æä¸ä¸ªä¸»è¦æ§å¶æ¥å£ââSpeechSynthesis ï¼å¤å ä¸äºå¤çå¦ä½è¡¨ç¤ºè¦è¢«åæçææ¬ (ä¹è¢«ç§°ä¸º utterances)ï¼ç¨ä»ä¹å£°é³æ¥æåº utterances çå·¥ä½çç¸å
³æ¥å£ãåæ ·çï¼è®¸å¤æä½ç³»ç»é½æèªå·±çæç§è¯é³åæç³»ç»ï¼å¨è¿ä¸ªä»»å¡ä¸æä»¬è°ç¨å¯ç¨ç API æ¥ä½¿ç¨è¯é³åæç³»ç»ã
æ¼ç¤º
为äºå±ç¤º Web è¯é³åæçç®å使ç¨ï¼æä»¬æä¾äºä¸ä¸ªä¾åââSpeak easy synthesisãå ¶å å«ä¸å¥ç¨äºè¾å ¥è¦åæçææ¬ï¼ä»¥å设置æè¯»ææ¬æ¶ä½¿ç¨çé³è°ãè¯éå声é³çè¡¨åæ§ä»¶ãå¨è¾å ¥ææ¬ä¹åï¼æä¸ Enter/Return é®ä½¿å®ææ¾ã

æ³è·è¿ä¸ªä¾åï¼ä½ å¯ä»¥ git clone Github ä»åºä¸çé¨å (æè ç´æ¥ä¸è½½)ï¼å¨æ¡é¢çæ¯æçæµè§å¨æå¼ index.html æä»¶ï¼æè å¨ç§»å¨ç«¯æµè§å¨ç´æ¥å¯¼å live demo URL ï¼å Chrome å Firefox OSã
HTML å CSS
HTML å CSS è¿æ¯æ 足轻éï¼åªæ¯ç®åå
å«ä¸ä¸ªæ é¢ï¼ä¸æ®µä»ç»æåï¼ä»¥åä¸ä¸ªè¡¨æ ¼å¸¦æä¸äºç®åæ§å¶åè½ã<select> å
ç´ åå§æ¯ç©ºçï¼ä¹åä¼éè¿ JavaScript ä½¿ç¨ <option> å¡«å
ã
<h1>Speech synthesizer</h1>
<p>
Enter some text in the input below and press return to hear it. change voices
using the dropdown menu.
</p>
<form>
<input type="text" class="txt" />
<div>
<label for="rate">Rate</label
><input type="range" min="0.5" max="2" value="1" step="0.1" id="rate" />
<div class="rate-value">1</div>
<div class="clearfix"></div>
</div>
<div>
<label for="pitch">Pitch</label
><input type="range" min="0" max="2" value="1" step="0.1" id="pitch" />
<div class="pitch-value">1</div>
<div class="clearfix"></div>
</div>
<select></select>
</form>
JavaScript
让æä»¬çç JavaScript å¨è¿ä¸ª app ä¸ç强大表ç°ã
设置åé
é¦å
æä»¬è·å¾ UI 䏿¶åç DOM å
ç´ çå¼ç¨ï¼ä½æ´æè¶£çæ¯ï¼æä»¬è·å¾äº Window.speechSynthesis çå¼ç¨ãè¿æ¯ API çå
¥å£ç¹ââå®è¿åäº SpeechSynthesis çä¸ä¸ªå®ä¾ï¼è¿æ¯ web è¯é³åæçæ§å¶æ¥å£ã
const synth = window.speechSynthesis;
const inputForm = document.querySelector("form");
const inputTxt = document.querySelector(".txt");
const voiceSelect = document.querySelector("select");
const pitch = document.querySelector("#pitch");
const pitchValue = document.querySelector(".pitch-value");
const rate = document.querySelector("#rate");
const rateValue = document.querySelector(".rate-value");
const voices = [];
å¡«å select å ç´
为使ç¨è®¾å¤ä¸å¯ç¨çä¸åçè¯é³é项填å
<select> å
ç´ ï¼æä»¬åäºä¸ä¸ª populateVoiceList() 彿°ãé¦å
è°ç¨ SpeechSynthesis.getVoices()ï¼è¿ä¸ªå½æ°è¿åå
嫿æå¯ç¨è¯é³ï¼ç± SpeechSynthesisVoice 对象表示ï¼çåè¡¨ãæ¥ä¸æ¥å¾ªç¯è¿ä¸ªåè¡¨ï¼æ¯æ¬¡å建ä¸ä¸ª <option> å
ç´ ï¼è®¾ç½®å®çææ¬å
容以æ¾ç¤ºå£°é³çåç§°ï¼ä» SpeechSynthesisVoice.name è·åï¼ãè¯é³çè¯è¨ï¼ä» SpeechSynthesisVoice.lang è·åï¼ï¼å¦ææä¸ªè¯é³æ¯åæå¼æé»è®¤çï¼æ£æ¥ SpeechSynthesisVoice.default 为 true ç屿§ï¼å¨ææ¬å
容å颿·»å -- DEFAULTã
å¯¹äºæ¯ä¸ª option å
ç´ ï¼æä»¬ä¹åå»ºäº data- 屿§ï¼å±æ§å¼æ¯è¯é³çåååè¯è¨ï¼è¿æ ·å¨ä¹åæä»¬å¯ä»¥è½»æ¾è·åè¿ä¸ªä¿¡æ¯ãä¹åæææç option å
ç´ ä½ä¸ºå©åæ·»å å° select å
ç´ å
ã
function populateVoiceList() {
voices = synth.getVoices();
for (const voice of voices) {
const option = document.createElement("option");
option.textContent = `${voice.name} (${voice.lang})`;
if (voice.default) {
option.textContent += " â DEFAULT";
}
option.setAttribute("data-lang", voice.lang);
option.setAttribute("data-name", voice.name);
voiceSelect.appendChild(option);
}
}
æ©æçæ¬çæµè§å¨ä¸æ¯æ voiceschanged äºä»¶ï¼åªæå½ SpeechSynthesis.getVoices() è¢«è§¦åæ¶æè¿åè¯é³å表ãèå
¶ä»æµè§å¨ï¼æ¯å¦ Chrome ä¸ï¼ä½ å¿
é¡»çå¾
voiceschanged äºä»¶è§¦ååæè½è·å¾å¯ç¨è¯é³å表ã为äºå
¼å®¹è¿ä¸¤ç§æ
åµï¼æä»¬è¿è¡å¦ä¸ä»£ç ï¼
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
说åºè¾å ¥çææ¬
æ¥ä¸æ¥æä»¬å建ä¸ä¸ªäºä»¶å¤çå¨ï¼event handlerï¼ï¼å¼å§è¯´åºå¨ææ¬æ¡ä¸è¾å
¥çææ¬ãæä»¬æ onsubmit å¤ç卿å¨è¡¨åä¸ï¼å½ Enter/Return 被æä¸ï¼å¯¹åºè¡ä¸ºå°±ä¼åçãæä»¬é¦å
éè¿æé 彿°å建ä¸ä¸ªæ°ç SpeechSynthesisUtterance() å®ä¾ââæææ¬è¾å
¥æ¡ä¸çå¼ä½ä¸ºåæ°ä¼ éã
æ¥ä¸æ¥ï¼æä»¬éè¦å¼æ¸
æ¥ä½¿ç¨åªç§è¯é³ãä½¿ç¨ HTMLSelectElement selectedOptions 屿§è¿åå½åéä¸ç <option> å
ç´ ãç¶å使ç¨å
ç´ ç data-name 屿§ï¼æ¾å° name å¹é
è¯¥å±æ§å¼ç SpeechSynthesisVoice 对象ãæå¹é
çè¯é³å¯¹è±¡è®¾ç½®ä¸ºSpeechSynthesisUtterance.voice ç屿§å¼ã
æåï¼æä»¬è®¾ç½® SpeechSynthesisUtterance.pitch åSpeechSynthesisUtterance.rate 屿§å¼ä¸ºå¯¹åºèå´è¡¨åå
ç´ ä¸çå¼ãååææåå¤å·¥ä½å°±ç»ªï¼è°ç¨ SpeechSynthesis.speak() å¼å§è¯´è¯ãæ SpeechSynthesisUtterance å®ä¾ä½ä¸ºåæ°ä¼ éã
inputForm.onsubmit = (event) => {
event.preventDefault();
const utterThis = new SpeechSynthesisUtterance(inputTxt.value);
const selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for (const voice of voices) {
if (voice.name === selectedOption) {
utterThis.voice = voice;
}
}
utterThis.pitch = pitch.value;
utterThis.rate = rate.value;
synth.speak(utterThis);
å¨äºä»¶å¤çå¨çæåé¨åï¼æä»¬å å
¥äºä¸ä¸ª SpeechSynthesisUtterance.onpause å¤çå¨ï¼æ¥å±ç¤ºSpeechSynthesisEvent å¦ä½å¯ä»¥å¾å¥½å°ä½¿ç¨ãå½ SpeechSynthesis.pause() 被è°ç¨ï¼è¿å°è¿å䏿¡æ¶æ¯ï¼æ¥å该è¯é³æåæ¶çå符ç¼å·ååç§°ã
utterThis.onpause = (event) => {
const char = event.utterance.text.charAt(event.charIndex);
console.log(
`Speech paused at character ${event.charIndex} of "${event.utterance.text}", which is "${char}".`,
);
};
æåï¼æä»¬å¨ææ¬è¾å ¥æ¡æ·»å äº blur() æ¹æ³ãè¿ä¸»è¦æ¯å¨ Firefox æä½ç³»ç»ä¸éèé®ç
inputTxt.blur();
}
æ´æ° pitch å rate çæ¾ç¤ºæ°å¼
代ç çæåé¨åï¼å¨æ¯æ¬¡æ»å¨æ¡ç§»å¨æ¶ï¼æ´æ° pitch/rate å¨ UI ä¸å±ç¤ºçå¼ã
pitch.onchange = () => {
pitchValue.textContent = pitch.value;
};
rate.onchange = () => {
rateValue.textContent = rate.value;
};