JS實現將文字轉換為語音並自動播放

十方發表於2022-06-22

在開發業務系統時,有時候可能需要使用語音播報一段文字,比如下面的場景:

當顧客付款成功後,需要系統自動播報收款的金額,其中付款金額是不固定的,比如1元、2元、3.2元等等

如果是相對固定的場景,並且語音有限的情況下,可以採用錄製的方式,即先錄製好所有的音訊資源,然後根據業務場景播放相應的音訊即可;但是如果場景不固定,需要的語音也不一樣時,採用錄製的方式的話,音訊資源將會非常多,而且還可能會出現不全的問題,那麼這個時候利用語音合成技術是一個較好的辦法,即實時將文字轉換成語音。

目前文字轉語音即語音合成技術現在已經很成熟了,像百度、訊飛等都提供了相關的服務,支援將文字轉換成各種形式的語音,通常這些服務都需要付費使用,如果對語音要求不高,並且又想節約成本,那麼可以直接使用瀏覽器的語音合成功能。

有些瀏覽器已經支援將文字轉換為語音的功能,下面來看看官方的介紹:

語音合成是通過 SpeechSynthesis 介面進行訪問,它提供了文字到語音(TTS)的能力,這使得程式能夠讀出它們的文字內容(通常使用裝置預設的語音合成器)。不同的聲音類型別通過 SpeechSynthesisVoice 物件進行表示,不同部分的文字則由 SpeechSynthesisUtterance 物件來表示,最後可以通過 SpeechSynthesis.speak() 方法來產生語音。

語音合成主要涉及到上面的三個物件:SpeechSynthesisSpeechSynthesisVoiceSpeechSynthesisUtterance

1、SpeechSynthesis

SpeechSynthesis 是語音合成服務的控制器介面,可用於獲取裝置上可用的合成語音,開始、暫停以及其它相關命令的資訊,可以使用 window.speechSynthesis 屬性來訪問 SpeechSynthesis 控制器,從而獲取語音合成功能的入口。

或者省略 window,直接使用 speechSynthesis 也是可以的

它有 pausedpendingspeaking 三個屬性,都是隻讀屬性,不可修改。

它擁有的方法如下:

  • SpeechSynthesis.cancel():取消語音播放
  • SpeechSynthesis.getVoices():獲取當前裝置所有可用聲音的 SpeechSynthesisVoice 列表。
  • SpeechSynthesis.pause() :暫停語音播放
  • SpeechSynthesis.resume() :恢復播放
  • SpeechSynthesis.speak() :新增語音到播放列隊,將會在其他語音播放完後自動播放

2、SpeechSynthesisVoice

SpeechSynthesisVoice 表示當前系統支援的語音資源,每一個 SpeechSynthesisVoice 都對應相關的語音服務,可以通過 SpeechSynthesis.getVoices() 獲取語音列表,如下:

它有5個只讀的屬性,分別為 defaultlangnamelocalServicevoiceURI.

3、SpeechSynthesisUtterance

SpeechSynthesisUtterance 表示一次發音請求,其中包含了將由語音服務朗讀的內容,以及如何朗讀它(例如:語種、音高、音量)。

它有6個屬性,分別如下:

  • lang:讀取時的語言
  • pitch:聲音的音高,取值0~2 ,正常音高為1
  • rate:讀取的語速,取值0.1~10 ,正常語速值為1
  • text:要合成語音的文字內容
  • voice:讀取文字的語音服務,預設為 SpeechSynthesisVoice 的屬性值為 default 的那個
  • volume:讀取時聲音的音量,取值0~1,正常音量為1

除了上面的屬性外,還有7個事件方法,分別如下:

  • onboundary:當播放至一個詞或句子結尾時觸發
  • onend:語音播放結束時觸發
  • onerror:語音播放錯誤時觸發
  • onmark:當語音播放至 mark 標記時觸發
  • onpause:暫停語音播放時觸發
  • onresume:恢復語音播放時觸發
  • onstart:開始語音播放時觸發

關於SpeechSynthesisVoice 的屬性和方法,可以直接在 console 中檢視,如下:

4、語音合成程式碼

在瞭解了語音合成的相關物件後,下面來簡單測試一下

let synth = window.speechSynthesis;
let utterThis = new SpeechSynthesisUtterance('支付寶到賬7.5元');
synth.speak(utterThis);

執行後,就可以聽到語音了,這裡使用 Chrome 瀏覽器測試的,語音聽起來還可以。

下面給出一個比較通用的方法,具體實現的程式碼:

/**
 * @description 文字轉語音方法
 * @public
 * @param { text, rate, lang, volume, pitch } object
 * @param  text 要合成的文字內容,字串
 * @param  rate 讀取文字的語速 0.1~10  正常1
 * @param  lang 讀取文字時的語言
 * @param  volume  讀取時聲音的音量 0~1  正常1
 * @param  pitch  讀取時聲音的音高 0~2  正常1
 * @returns SpeechSynthesisUtterance
 */
function speak({ text, speechRate, lang, volume, pitch }, endEvent, startEvent) {
    if (!window.SpeechSynthesisUtterance) {
        console.warn('當前瀏覽器不支援文字轉語音服務')
        return;
    }

    if (!text) {
        return;
    }

    const speechUtterance = new SpeechSynthesisUtterance();
    speechUtterance.text = text;
    speechUtterance.rate = speechRate || 1;
    speechUtterance.lang = lang || 'zh-CN';
    speechUtterance.volume = volume || 1;
    speechUtterance.pitch = pitch || 1;
    speechUtterance.onend = function() {
        endEvent && endEvent();
    };
    speechUtterance.onstart = function() {
        startEvent && startEvent();
    };
    speechSynthesis.speak(speechUtterance);
    
    return speechUtterance;
}

測試一下

speak({
    text: '微信到賬100元'
}, function() {
    console.log('語音播放結束');
}, function() {
    console.log('語音開始播放');
});

執行後,可以看到此時的 speechUtterance 例項如下:

同時控制檯會依次輸出下面的資訊

語音開始播放
語音播放結束

參考資料

相關文章