SpeechSynthesisUtterance 脚本,带有播放、暂停、停止按钮以及语言和语音选择

ale*_*bal 5 javascript text-to-speech

我想使用 SpeechSynthesisUtterance 阅读我的页面文本。

\n\n

我找到了这个脚本:https://www.hongkiat.com/blog/text-to-speech/

\n\n

几乎完美,但暂停按钮似乎没有多大作用,我希望我能够设置语言,也许还可以选择声音。

\n\n

我在这里找到了参考: https: //developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance,但我对 JavaScript 不是很了解。

\n\n

对于语言,据我了解,应该使用html标签中设置的lang参数。

\n\n

对于语音我完全不知道如何在代码中实现它。

\n\n

这很重要,因为我有英语、西班牙语、法语和意大利语的文本,而没有语音和语言设置的结果有时听起来很奇怪。

\n\n

更新

\n\n

这些天我摆弄了一下,我设法(或多或少)组合了两个不同的脚本/示例。

\n\n

这个:https: //www.hongkiat.com/blog/text-to-speech/

\n\n

这是: https: //developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis#Examples

\n\n

出来的代码是这样的:

\n\n

超文本标记语言

\n\n
<html>\n<head>\n<link rel="stylesheet" href="style.css">\n<script src="text-to-speech.js"></script>\n</head>\n<body>\n<div class=buttons>\n    <button id=play></button> &nbsp;\n    <button id=pause></button> &nbsp;\n    <button id=stop></button>\n</div>\n    <select id="voices">\n\n    </select>\n<div id="description">\nThe SpeechSynthesis interface of the Web Speech API is the controller interface for the speech service; this can be used to retrieve information about the synthesis voices available on the device, start and pause speech, and other commands besides. \nQuesto \xc3\xa8 in italiano come viene?\n</div>\n\n</body>\n</html>\n
Run Code Online (Sandbox Code Playgroud)\n\n

CSS

\n\n
@import url(\'https://fonts.googleapis.com/css?family=Crimson+Text\');\n\n.buttons {\n    margin-top: 25px;\n}\n\nbutton {\n    background: none;\n    border: none;\n    cursor: pointer;\n    height: 48px;\n    outline: none;\n    padding: 0;\n    width: 48px;\n}\n\n#play {\n    background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/play.svg);\n}\n\n#play.played {\n    background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/play1.svg);\n}\n\n#pause {\n    background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/pause.svg);\n}\n\n#pause.paused {\n    background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/pause1.svg);\n}\n\n#stop {\n    background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/stop.svg);\n}\n\n#stop.stopped {\n    background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/stop1.svg);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

脚本语言

\n\n
onload = function() {\n    if (\'speechSynthesis\' in window) with(speechSynthesis) {\n\n// select voices////\nvar synth = window.speechSynthesis;\n\nvar voiceSelect = document.querySelector(\'#voices\');\n\nvar voices = [];\n\nfunction populateVoiceList() {\n  voices = synth.getVoices().sort(function (a, b) {\n      const aname = a.name.toUpperCase(), bname = b.name.toUpperCase();\n      if ( aname < bname ) return -1;\n      else if ( aname == bname ) return 0;\n      else return +1;\n  });\n  var selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;\n  voiceSelect.innerHTML = \'\';\n  for(i = 0; i < voices.length ; i++) {\n    var option = document.createElement(\'option\');\n    option.textContent = voices[i].name + \' (\' + voices[i].lang + \')\';\n\n    if(voices[i].default) {\n      option.textContent += \' -- DEFAULT\';\n    }\n\n    option.setAttribute(\'data-lang\', voices[i].lang);\n    option.setAttribute(\'data-name\', voices[i].name);\n    voiceSelect.appendChild(option);\n  }\n  voiceSelect.selectedIndex = selectedIndex;\n}\n\npopulateVoiceList();\nif (speechSynthesis.onvoiceschanged !== undefined) {\n  speechSynthesis.onvoiceschanged = populateVoiceList;\n}\n//end select voices\n\n        var playEle = document.querySelector(\'#play\');\n        var pauseEle = document.querySelector(\'#pause\');\n        var stopEle = document.querySelector(\'#stop\');\n        var flag = false;\n\n        playEle.addEventListener(\'click\', onClickPlay);\n        pauseEle.addEventListener(\'click\', onClickPause);\n        stopEle.addEventListener(\'click\', onClickStop);\n\n        function onClickPlay() {\n            if (!flag) {\n                flag = true;\n                utterance = new SpeechSynthesisUtterance(document.querySelector(\'#description\').textContent);\n                //utterance.voice = getVoices()[0];\n\n                //add voice//\n                var selectedOption = voiceSelect.selectedOptions[0].getAttribute(\'data-name\');\n                    for(i = 0; i < voices.length ; i++) {\n                      //if(voices[i].name === \'Google UK English Female\') {\n                      if(voices[i].name === selectedOption) {\n                        utterance.voice = voices[i];\n                        break;\n                      }\n                    }\n\n\n                voiceSelect.onchange = function(){\n                    onClickStop();\n                    stopEle.className = \'\';\n                    onClickPlay();\n                    playEle.className = \'played\';\n                }\n                //and add voice\n\n                utterance.onend = function() {\n                    flag = false;\n                    playEle.className = pauseEle.className = \'\';\n                    stopEle.className = \'stopped\';\n                };\n                playEle.className = \'played\';\n                stopEle.className = \'\';\n                speak(utterance);\n            }\n            if (paused) { /* unpause/resume narration */\n                playEle.className = \'played\';\n                pauseEle.className = \'\';\n                resume();\n            }\n        }\n\n        function onClickPause() {\n            if (speaking && !paused) { /* pause narration */\n                pauseEle.className = \'paused\';\n                playEle.className = \'\';\n                pause();\n            }\n        }\n\n        function onClickStop() {\n            if (speaking) { /* stop narration */\n                /* for safari */\n                stopEle.className = \'stopped\';\n                playEle.className = pauseEle.className = \'\';\n                flag = false;\n                cancel();\n\n            }\n        }\n\n    }\n\n    else { /* speech synthesis not supported */\n        msg = document.createElement(\'h5\');\n        msg.textContent = "Detected no support for Speech Synthesis";\n        msg.style.textAlign = \'center\';\n        msg.style.backgroundColor = \'red\';\n        msg.style.color = \'white\';\n        msg.style.marginTop = msg.style.marginBottom = 0;\n        document.body.insertBefore(msg, document.querySelector(\'div\'));\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我有了播放、停止和暂停按钮(暂停仍然不起作用),我可以从设备中可用的声音中选择一种声音。

\n\n

似乎在 Chrome 上工作得很好,在 Firefox 上可能工作得不好一些,(但我正在使用 Linux LMDE,也许这是我的错)。过了一会儿,Chrome 就停止说话了。我不知道为什么,但在我看来,我似乎看到有人可能理解为什么在我这些天打开的数千个网页中的一些网页中,我必须重新打开它们。

\n\n

如果所选的语音保存在 cookie 中,那就太好了,所以如果我打开另一个页面,脚本将从我选择的最后一个语音开始(我不知道如何在 JavaScript 中执行此操作)

\n\n

更新2

\n\n

我向前迈出了一些小步骤并进行了简化。

\n\n

它几乎似乎工作,并不总是暂停按钮,我现在最大的疑问是,使用 chrome,当我更新或更改页面时,它似乎不会停止,而且当你更改页面时,他继续阅读上一个页面,这真的很糟糕页。

\n\n

超文本标记语言

\n\n
<div id="SpeechSynthesis">\n    <div>\n        <button id=play>play</button>\n        <button id=pause>pause</button>\n        <button id=stop>stop</button>\n    </div>\n        <select id="voices">\n\n        </select>\n    </div>\n<p id="texttospeech">\nThe SpeechSynthesis interface of the Web Speech API is the controller interface for the speech service; this can be used to retrieve information about the synthesis voices available on the device, start and pause speech, and other commands besides. \nQuesto \xc3\xa8 in italiano come viene?\n</p>\n
Run Code Online (Sandbox Code Playgroud)\n\n

脚本语言

\n\n
onload = function() {\n    if (\'speechSynthesis\' in window){\n        var synth = speechSynthesis;\n        var flag = false;\n\n        //stop when change page ???(not sure)\n            if(synth.speaking){ /* stop narration */\n                /* for safari */\n                flag = false;\n                synth.cancel();\n            }\n\n        /* references to the buttons */\n        var playEle = document.querySelector(\'#play\');\n        var pauseEle = document.querySelector(\'#pause\');\n        var stopEle = document.querySelector(\'#stop\');\n\n        /* click event handlers for the buttons */\n        playEle.addEventListener(\'click\', onClickPlay);\n        pauseEle.addEventListener(\'click\', onClickPause);\n        stopEle.addEventListener(\'click\', onClickStop);\n\n// select voices////\n//var synth = window.speechSynthesis;\n\nvar voiceSelect = document.querySelector(\'#voices\');\n\nvar voices = [];\n\nfunction populateVoiceList() {\n  voices = synth.getVoices().sort(function (a, b) {\n      const aname = a.name.toUpperCase(), bname = b.name.toUpperCase();\n      if ( aname < bname ) return -1;\n      else if ( aname == bname ) return 0;\n      else return +1;\n  });\n  var selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;\n  voiceSelect.innerHTML = \'\';\n  for(i = 0; i < voices.length ; i++) {\n    var option = document.createElement(\'option\');\n    option.textContent = voices[i].name + \' (\' + voices[i].lang + \')\';\n\n    if(voices[i].default) {\n      option.textContent += \' -- DEFAULT\';\n    }\n\n    option.setAttribute(\'data-lang\', voices[i].lang);\n    option.setAttribute(\'data-name\', voices[i].name);\n    voiceSelect.appendChild(option);\n  }\n  voiceSelect.selectedIndex = selectedIndex;\n}\n\npopulateVoiceList();\nif (speechSynthesis.onvoiceschanged !== undefined) {\n  speechSynthesis.onvoiceschanged = populateVoiceList;\n}\n//end select voices\n\n        function onClickPlay() {\n            if(!flag){\n                flag = true;\n                utterance = new SpeechSynthesisUtterance(document.querySelector(\'#texttospeech\').textContent);\n                //utterance.voice = synth.getVoices()[0];\n\n                //add voice//\n                var selectedOption = voiceSelect.selectedOptions[0].getAttribute(\'data-name\');\n                    for(i = 0; i < voices.length ; i++) {\n                      //if(voices[i].name === \'Google UK English Female\') {\n                      if(voices[i].name === selectedOption) {\n                        utterance.voice = voices[i];\n                        break;\n                      }\n                    }\n\n                voiceSelect.onchange = function(){\n                    onClickStop();\n                    onClickPlay();\n                }\n                //and add voice\n\n                utterance.onend = function(){\n                    flag = false;\n                };\n                synth.speak(utterance);\n\n                //fix stop after a while bug\n                let r = setInterval(() => {\n                  console.log(speechSynthesis.speaking);\n                  if (!speechSynthesis.speaking) {\n                    clearInterval(r);\n                  } else {\n                    speechSynthesis.resume();\n                  }\n                }, 14000);\n                //end fix stop after a while bug\n            }\n            if(synth.paused) { /* unpause/resume narration */\n                synth.resume();\n            }\n        }\n        function onClickPause() {\n            if(synth.speaking && !synth.paused){ /* pause narration */\n                synth.pause();\n            }\n        }\n        function onClickStop() {\n           if(synth.speaking){ /* stop narration */\n                /* for safari */\n                flag = false;\n                synth.cancel();\n            }\n        }\n    }\n  else {\n        msg = document.createElement(\'h5\');\n        msg.textContent = "Detected no support for Speech Synthesis";\n        msg.style.textAlign = \'center\';\n        msg.style.backgroundColor = \'red\';\n        msg.style.color = \'white\';\n        msg.style.marginTop = msg.style.marginBottom = 0;\n        document.body.insertBefore(msg, document.querySelector(\'#SpeechSynthesis\'));\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

更新3

\n\n

我尝试添加带有最后选择的声音的 cookie。我添加了几个函数来管理 cookie,并在 onClickPlay() 函数中设置 cookie。

\n\n
//add voice//\n                var selectedOption = voiceSelect.selectedOptions[0].getAttribute(\'data-name\');\n                    for(i = 0; i < voices.length ; i++) {\n                      //if(voices[i].name === \'Google UK English Female\') {\n                      if(voices[i].name === selectedOption) {\n                        utterance.voice = voices[i];\n                        setCookie(\'SpeechSynthesisVoice\',voices[i].name,30);\n                        break;\n                      }\n                    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

Firefox 设置 cookie 没有问题,chrome 没有(即使文件位于在线服务器上)。

\n\n

然后我尝试在 populateVoiceList() 函数中将 cookie 中保存的语音设置为“选定”:

\n\n
//get cookie voice\n    var cookievoice = getCookie(\'SpeechSynthesisVoice\');\n\n//add selcted to option if if cookievoice\n    if (cookievoice === voices[i].name) {\n        option.setAttribute(\'selected\', \'selected\');\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

它有效,我在代码中找到了“选定”,但似乎没有考虑到它,它总是开始与列表中的第一个声音或默认声音交谈,我不确定,而不是与具有“选定”的那个。

\n\n

我使用的cookie函数:

\n\n
//cookie functions\nfunction setCookie(name, value, days) {\n    var expires = \'\',\n        date = new Date();\n    if (days) {\n        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));\n        expires = \'; expires=\' + date.toGMTString();\n    }\n    document.cookie = name + \'=\' + value + expires + \'; path=/\';\n}\n\nfunction getCookie(name) {\n    var cookies = document.cookie.split(\';\'),\n        length = cookies.length,\n        i,\n        cookie,\n        nameEQ = name + \'=\';\n    for (i = 0; i < length; i += 1) {\n        cookie = cookies[i];\n        while (cookie.charAt(0) === \' \') {\n            cookie = cookie.substring(1, cookie.length);\n        }\n        if (cookie.indexOf(nameEQ) === 0) {\n            return cookie.substring(nameEQ.length, cookie.length);\n        }\n    }\n    return null;\n}\n\nfunction eraseCookie(name) {\n    createCookie(name, \'\', -1);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

ale*_*bal 4

我没有得到太多帮助,但不知何故,我设法设置了一个读取网页文本的小型播放器。

我做了一个小教程和演示,解释了我做了什么以及它是如何工作的。

https://www.alebalweb-blog.com/85-text-to-speech-player-with-buttons-play-pause-stop-and-voice-choice.html