文字轉語音 - 樹莓派
在本課程中,你將編寫代碼,使用語音服務將文字轉換為語音。
使用語音服務將文字轉換為語音
可以使用 REST API 將文字發送到語音服務,以獲取可以在你的物聯網設備上播放的音頻文件。請求語音時,你需要提供要使用的語音,因為可以使用各種不同的語音生成語音。
每種語言都支持一系列不同的語音,你可以對語音服務發出 REST 請求,以獲取每種語言支持的語音列表。
任務 - 獲取語音
-
在 VS Code 中打開
smart-timer
項目。 -
在
say
函數上方添加以下代碼,以請求語言的語音列表:def get_voice():
url = f'https://{location}.tts.speech.microsoft.com/cognitiveservices/voices/list'
headers = {
'Authorization': 'Bearer ' + get_access_token()
}
response = requests.get(url, headers=headers)
voices_json = json.loads(response.text)
first_voice = next(x for x in voices_json if x['Locale'].lower() == language.lower() and x['VoiceType'] == 'Neural')
return first_voice['ShortName']
voice = get_voice()
print(f'Using voice {voice}')此代碼定義了一個名為
get_voice
的函數,該函數使用語音服務獲取語音列表。然後,它找到與正在使用的語言匹配的第一個語音。然後調用此函數以存儲第一個語音,並將語音名稱打印到控制台。此語音可以請求一次,並在每次調用將文字轉換為語音時使用該值。
💁 你可以從 Microsoft Docs 上的語言和語音支持文檔 獲取支持語音的完整列表。如果你想使用特定的語音,則可以刪除此函數並將語音名稱硬編碼為此文檔中的語音名稱。例如:
voice = 'hi-IN-SwaraNeural'
任務 - 將文字轉換為語音
-
在此之下,定義一個常量,用於從語音服務檢索音頻格式。請求音頻時,可以使用多種不同的格式。
playback_format = 'riff-48khz-16bit-mono-pcm'
你可以使用的格式取決於你的硬件。如果在播放音頻時出現
Invalid sample rate
錯誤,請將其更改為其他值。你可以在 Microsoft Docs 上的文字轉語音 REST API 文檔 中找到支持的值列表。你需要使用riff
格式音頻,可以嘗試的值有riff-16khz-16bit-mono-pcm
、riff-24khz-16bit-mono-pcm
和riff-48khz-16bit-mono-pcm
。 -
在此之下,聲明一個名為
get_speech
的函數,該函數將使用語音服務 REST API 將文字轉換為語音:def get_speech(text):
-
在
get_speech
函數中,定義要調用的 URL 和要傳遞的標頭:url = f'https://{location}.tts.speech.microsoft.com/cognitiveservices/v1'
headers = {
'Authorization': 'Bearer ' + get_access_token(),
'Content-Type': 'application/ssml+xml',
'X-Microsoft-OutputFormat': playback_format
}這設置了使用生成的訪問令牌的標頭,將內容設置為 SSML,並定義所需的音頻格式。
-
在此之下,定義要發送到 REST API 的 SSML:
ssml = f'<speak version=\'1.0\' xml:lang=\'{language}\'>'
ssml += f'<voice xml:lang=\'{language}\' name=\'{voice}\'>'
ssml += text
ssml += '</voice>'
ssml += '</speak>'此 SSML 設置要使用的語言和語音,以及要轉換的文字。
-
最後,在此函數中添加代碼以發出 REST 請求並返回二進制音頻數據:
response = requests.post(url, headers=headers, data=ssml.encode('utf-8'))
return io.BytesIO(response.content)
任務 - 播放音頻
-
在
get_speech
函數下方,定義一個新函數以播放 REST API 調用返回的音頻:def play_speech(speech):
-
傳遞給此函數的
speech
將是從 REST API 返回的二進制音頻數據。使用以下代碼將其作為波形文件打開並傳遞給 PyAudio 以播放音頻:def play_speech(speech):
with wave.open(speech, 'rb') as wave_file:
stream = audio.open(format=audio.get_format_from_width(wave_file.getsampwidth()),
channels=wave_file.getnchannels(),
rate=wave_file.getframerate(),
output_device_index=speaker_card_number,
output=True)
data = wave_file.readframes(4096)
while len(data) > 0:
stream.write(data)
data = wave_file.readframes(4096)
stream.stop_stream()
stream.close()此代碼使用 PyAudio 流,與捕獲音頻相同。這裡的區別是流設置為輸出流,並從音頻數據中 讀取數據並推送到流中。
而不是硬編碼流的詳細信息,例如採樣率,它是從音頻數據中讀取的。
-
將
say
函數的內容替換為以下內容:speech = get_speech(text)
play_speech(speech)此代碼將文字轉換為二進制音頻數據,並播放音頻。
-
運行應用程序,並確保函數應用程序也在運行。設置一些計時器,你會聽到語音響應,告訴你計時器已設置,然後在計時器完成時會有另一個語音響應。
如果出現
Invalid sample rate
錯誤,請按照上述說明更改playback_format
。
💁 你可以在 code-spoken-response/pi 文件夾中找到此代碼。
😀 你的計時器程序成功了!