跳至主要内容

文字轉語音 - 樹莓派

在本課程中,你將編寫代碼,使用語音服務將文字轉換為語音。

使用語音服務將文字轉換為語音

可以使用 REST API 將文字發送到語音服務,以獲取可以在你的物聯網設備上播放的音頻文件。請求語音時,你需要提供要使用的語音,因為可以使用各種不同的語音生成語音。

每種語言都支持一系列不同的語音,你可以對語音服務發出 REST 請求,以獲取每種語言支持的語音列表。

任務 - 獲取語音

  1. 在 VS Code 中打開 smart-timer 項目。

  2. 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'

任務 - 將文字轉換為語音

  1. 在此之下,定義一個常量,用於從語音服務檢索音頻格式。請求音頻時,可以使用多種不同的格式。

    playback_format = 'riff-48khz-16bit-mono-pcm'

    你可以使用的格式取決於你的硬件。如果在播放音頻時出現 Invalid sample rate 錯誤,請將其更改為其他值。你可以在 Microsoft Docs 上的文字轉語音 REST API 文檔 中找到支持的值列表。你需要使用 riff 格式音頻,可以嘗試的值有 riff-16khz-16bit-mono-pcmriff-24khz-16bit-mono-pcmriff-48khz-16bit-mono-pcm

  2. 在此之下,聲明一個名為 get_speech 的函數,該函數將使用語音服務 REST API 將文字轉換為語音:

    def get_speech(text):
  3. 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,並定義所需的音頻格式。

  4. 在此之下,定義要發送到 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 設置要使用的語言和語音,以及要轉換的文字。

  5. 最後,在此函數中添加代碼以發出 REST 請求並返回二進制音頻數據:

    response = requests.post(url, headers=headers, data=ssml.encode('utf-8'))
    return io.BytesIO(response.content)

任務 - 播放音頻

  1. get_speech 函數下方,定義一個新函數以播放 REST API 調用返回的音頻:

    def play_speech(speech):
  2. 傳遞給此函數的 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 流,與捕獲音頻相同。這裡的區別是流設置為輸出流,並從音頻數據中讀取數據並推送到流中。

    而不是硬編碼流的詳細信息,例如採樣率,它是從音頻數據中讀取的。

  3. say 函數的內容替換為以下內容:

    speech = get_speech(text)
    play_speech(speech)

    此代碼將文字轉換為二進制音頻數據,並播放音頻。

  4. 運行應用程序,並確保函數應用程序也在運行。設置一些計時器,你會聽到語音響應,告訴你計時器已設置,然後在計時器完成時會有另一個語音響應。

    如果出現 Invalid sample rate 錯誤,請按照上述說明更改 playback_format

💁 你可以在 code-spoken-response/pi 文件夾中找到此代碼。

😀 你的計時器程序成功了!