開始使用文字轉換語音

在本快速入門中,您將了解如何使用語音 SDK 進行文字轉換語音合成的常見設計模式。 首先,您會進行基本設定與合成,並繼續處理更多用於自訂應用程式開發的高階範例,包括:

  • 以記憶體內部資料流的形式取得回應
  • 自訂輸出採樣速率和位元速率
  • 使用 SSML 提交合成要求 (語音合成標記語言)
  • 使用神經語音

跳至 GitHub 上的範例

如果要直接跳到範例程式碼,請參閱 GitHub 上的 C# 快速入門範例

必要條件

本文假設您具有 Azure 帳戶和語音服務訂用帳戶。 如果您沒有該帳戶和訂用帳戶,請免費試用語音服務

安裝語音 SDK

您必須先安裝語音 SDK,才能執行動作。 根據您的平台,使用下列指示:

匯入相依性

若要執行本文中的範例,請在指令碼的頂端包含下列 using 陳述式。

using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;

建立語音設定

若要使用語音 SDK 來呼叫語音服務,您必須建立 SpeechConfig。 此類別包含您的訂用帳戶的相關資訊,例如您的語音金鑰以及相關聯的位置/區域、端點、主機或授權權杖。

注意

無論您是執行語音辨識、語音合成、翻譯還是意圖辨識,都一定會建立設定。

您可以透過數種方式將 SpeechConfig 初始化:

  • 使用訂用帳戶:傳入金鑰和相關聯的位置/區域。
  • 使用端點:傳入語音服務端點。 金鑰或授權權杖是選用項目。
  • 使用主機:傳入主機位址。 金鑰或授權權杖是選用項目。
  • 使用授權權杖:傳入授權權杖和相關聯的位置/區域。

在此範例中,您會 SpeechConfig 使用語音金鑰和位置/區域來建立。 請依照免費試用語音服務中的步驟,來取得這些認證。 您也會建立一些基本的重複使用程式碼,用於本文的其餘部分,而您可針對不同的自訂項目進行修改。

public class Program
{
    static async Task Main()
    {
        await SynthesizeAudioAsync();
    }

    static async Task SynthesizeAudioAsync()
    {
        var config = SpeechConfig.FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    }
}

將語音合成至檔案

接下來,您會建立 SpeechSynthesizer 物件,以執行文字轉換語音並輸出至喇叭、檔案或其他輸出串流。 SpeechSynthesizer 接受以下物件作為參數:在上一個步驟中建立的 SpeechConfig 物件,以及可指定應如何處理輸出結果的 AudioConfig 物件。

若要開始,請建立 AudioConfig,以使用 FromWavFileOutput() 函式將輸出自動寫入至 .wav 檔案,然後使用 using 陳述式將其具現化。 此內容中的 using 陳述式會自動處置非受控資源,並在處置後導致物件超出範圍。

static async Task SynthesizeAudioAsync()
{
    var config = SpeechConfig.FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav");
}

接下來,使用另一個 using 陳述式來具現化 SpeechSynthesizer。 以參數形式傳遞 config 物件和 audioConfig 物件。 然後,執行語音合成並寫入檔案,就像使用文字字串執行 SpeakTextAsync() 一樣簡單。

static async Task SynthesizeAudioAsync()
{
    var config = SpeechConfig.FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav");
    using var synthesizer = new SpeechSynthesizer(config, audioConfig);
    await synthesizer.SpeakTextAsync("A simple test to write to a file.");
}

執行程式,而合成的 .wav 檔案會寫入至您指定的位置。 這是最基本用法的絕佳範例,但您接著會探討如何自訂輸出,以及如何將輸出回應當作記憶體內部資料流處理,以便處理自訂案例。

合成為喇叭輸出

在某些情況下,您可以直接將合成的語音輸出至喇叭。 若要這樣做,請在 AudioConfig SpeechSynthesizer 上述範例中建立時省略參數。 這會會合成至目前作用中的輸出裝置。

static async Task SynthesizeAudioAsync()
{
    var config = SpeechConfig.FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    using var synthesizer = new SpeechSynthesizer(config);
    await synthesizer.SpeakTextAsync("Synthesizing directly to speaker output.");
}

以記憶體內部資料流程的形式取得結果

在語音應用程式開發的許多案例中,您可能需要產生的音訊資料作為記憶體內部資料流,而非直接寫入至檔案。 這可讓您建立自訂行為,包括:

  • 將產生的位元組陣列摘要成為自訂下游服務的可搜尋資料流。
  • 將結果與其他 API 或服務整合。
  • 修改音訊資料、撰寫自訂 .wav 標頭等。

從上一個範例進行這項變更很簡單。 首先,移除 AudioConfig 區塊,因為您會從這個時間點開始手動管理輸出行為,以提高掌控權。 然後在 SpeechSynthesizer 建構函式中針對 AudioConfig 傳遞 null

注意

針對 AudioConfig 傳遞 null (而非如同在上述喇叭輸出範例中加以省略),並不會在目前作用中的輸出裝置上依預設播放音訊。

這次,您會將結果儲存至 SpeechSynthesisResult 變數。 AudioData 屬性包含輸出資料的 byte []。 您可以手動處理此 byte [],也可以使用 AudioDataStream 類別來管理記憶體內部資料流。 在此範例中,您會使用 AudioDataStream.FromResult() 靜態函式從結果中取得資料流。

static async Task SynthesizeAudioAsync()
{
    var config = SpeechConfig.FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    using var synthesizer = new SpeechSynthesizer(config, null);

    var result = await synthesizer.SpeakTextAsync("Getting the response as an in-memory stream.");
    using var stream = AudioDataStream.FromResult(result);
}

在此,您可使用所產生的 stream 物件來實作任何自訂行為。

自訂音訊格式

下一節說明如何自訂音訊輸出屬性,包括:

  • 音訊檔案類型
  • 採樣速率
  • 位元深度

若要變更音訊格式,請在 SpeechConfig 物件上使用 SetSpeechSynthesisOutputFormat() 函式。 此函式應該有 SpeechSynthesisOutputFormat 類型的 enum,您可使用此類型來選取輸出格式。 如需可用的音訊格式清單,請參閱參考文件。

根據您的需求而定,有各種選項可供不同的檔案類型使用。 請注意,依照定義,原始格式 (例如 Raw24Khz16BitMonoPcm) 不包含音訊標頭。 只有在您知道下游實作可將原始位元資料流解碼,或者打算根據位元深度、採樣速率、通道數目等手動建立標頭時,才會使用原始格式。

在此範例中,您可藉由在 SpeechConfig 物件上設定 SpeechSynthesisOutputFormat,以指定高精確度的 RIFF 格式 Riff24Khz16BitMonoPcm。 與上一節中的範例類似,您可使用 AudioDataStream 來取得結果的記憶體內部資料流,然後將其寫入至檔案。

static async Task SynthesizeAudioAsync()
{
    var config = SpeechConfig.FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    config.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);

    using var synthesizer = new SpeechSynthesizer(config, null);
    var result = await synthesizer.SpeakTextAsync("Customizing audio output format.");

    using var stream = AudioDataStream.FromResult(result);
    await stream.SaveToWaveFileAsync("path/to/write/file.wav");
}

再次執行您的程式,會將 .wav 檔案寫入至指定的路徑。

使用 SSML 來自訂語音特性

語音合成標記語言 (SSML) 可讓您從 XML 結構描述提交要求,以微調文字轉換語音輸出的音調、發音、說話速度、音量等等。 本節顯示變更聲音的範例,但如需詳細的指南,請參閱 SSML 操作說明文章

若要開始使用 SSML 進行自訂,您可進行簡單變更來切換語音。 首先,在根專案目錄中為 SSML 組態建立新的 XML 檔案,在此範例中為 ssml.xml。 根元素一律為 <speak>,而將文字包裝在 <voice> 元素中,可讓您使用 name 參數來變更語音。 請參閱支援的 神經 語音的 完整清單

<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
  <voice name="en-US-ChristopherNeural">
    When you're on the freeway, it's a good idea to use a GPS.
  </voice>
</speak>

接下來,您需要變更語音合成要求以參考您的 XML 檔案。 要求大多數相同,但您會使用 SpeakSsmlAsync(),而不是使用 SpeakTextAsync() 函式。 此函式應該有 XML 字串,因此您會使用 File.ReadAllText(),先以字串形式載入 SSML 組態。 由此看來,結果物件會與先前的範例完全相同。

注意

如果您使用 Visual Studio,在預設情況下,您的組建組態可能找不到您的 XML 檔案。 若要修正此問題,請以滑鼠右鍵按一下 XML 檔案,然後選取 [屬性] 。 將 [建置動作] 變更為 [內容] ,並將 [複製到輸出目錄] 變更為 [一律複製] 。

public static async Task SynthesizeAudioAsync()
{
    var config = SpeechConfig.FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    using var synthesizer = new SpeechSynthesizer(config, null);

    var ssml = File.ReadAllText("./ssml.xml");
    var result = await synthesizer.SpeakSsmlAsync(ssml);

    using var stream = AudioDataStream.FromResult(result);
    await stream.SaveToWaveFileAsync("path/to/write/file.wav");
}

注意

若要在不使用 SSML 的情況下變更語音,您可以使用,在上設定屬性。 SpeechConfig``SpeechConfig.SpeechSynthesisVoiceName = "en-US-ChristopherNeural";

取得臉部姿勢事件

語音是推動臉部表情動畫的好方法。 通常會使用 visemes 來代表觀察語音中的索引鍵,例如,在產生特定音素時,lip、jaw 和吐的位置。 您可以在語音 SDK 中訂閱 viseme 事件。 然後,您可以套用 viseme 事件,以動畫顯示在語音音訊播放時的字元臉部。 瞭解 如何取得 viseme 事件

在本快速入門中,您將了解如何使用語音 SDK 進行文字轉換語音合成的常見設計模式。 首先,您會進行基本設定與合成,並繼續處理更多用於自訂應用程式開發的高階範例,包括:

  • 以記憶體內部資料流的形式取得回應
  • 自訂輸出採樣速率和位元速率
  • 使用 SSML 提交合成要求 (語音合成標記語言)
  • 使用神經語音

跳至 GitHub 上的範例

如果要直接跳到範例程式碼,請參閱 GitHub 上的 C++ 快速入門範例

必要條件

本文假設您具有 Azure 帳戶和語音服務訂用帳戶。 如果您沒有該帳戶和訂用帳戶,請免費試用語音服務

安裝語音 SDK

您必須先安裝語音 SDK,才能執行動作。 根據您的平台,使用下列指示:

匯入相依性

若要執行本文中的範例,請在指令碼的頂端包含下列 import 和 using 陳述式。

#include <iostream>
#include <fstream>
#include <string>
#include <speechapi_cxx.h>

using namespace std;
using namespace Microsoft::CognitiveServices::Speech;
using namespace Microsoft::CognitiveServices::Speech::Audio;

建立語音設定

若要使用語音 SDK 來呼叫語音服務,您必須建立 SpeechConfig。 此類別包含您的訂用帳戶的相關資訊,例如您的語音金鑰以及相關聯的位置/區域、端點、主機或授權權杖。

注意

無論您是執行語音辨識、語音合成、翻譯還是意圖辨識,都一定會建立設定。

您可以透過數種方式將 SpeechConfig 初始化:

  • 使用訂用帳戶:傳入金鑰和相關聯的位置/區域。
  • 使用端點:傳入語音服務端點。 金鑰或授權權杖是選用項目。
  • 使用主機:傳入主機位址。 金鑰或授權權杖是選用項目。
  • 使用授權權杖:傳入授權權杖和相關聯的位置/區域。

在此範例中,您會使用訂用帳戶金鑰和區域來建立 SpeechConfig。 請依照免費試用語音服務中的步驟,來取得這些認證。 您也會建立一些基本的重複使用程式碼,用於本文的其餘部分,而您可針對不同的自訂項目進行修改。

int wmain()
{
    try
    {
        synthesizeSpeech();
    }
    catch (exception e)
    {
        cout << e.what();
    }
    return 0;
}

void synthesizeSpeech()
{
    auto config = SpeechConfig::FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
}

將語音合成至檔案

接下來,您會建立 SpeechSynthesizer 物件,以執行文字轉換語音並輸出至喇叭、檔案或其他輸出串流。 SpeechSynthesizer 接受以下物件作為參數:在上一個步驟中建立的 SpeechConfig 物件,以及可指定應如何處理輸出結果的 AudioConfig 物件。

若要開始,請建立 AudioConfig,以使用 FromWavFileOutput() 函式將輸出自動寫入至 .wav 檔案。

void synthesizeSpeech()
{
    auto config = SpeechConfig::FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
}

接下來,將 config 物件和 audioConfig 物件當作參數傳遞,以具現化 SpeechSynthesizer。 然後,執行語音合成並寫入檔案,就像使用文字字串執行 SpeakTextAsync() 一樣簡單。

void synthesizeSpeech()
{
    auto config = SpeechConfig::FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
    auto synthesizer = SpeechSynthesizer::FromConfig(config, audioConfig);
    auto result = synthesizer->SpeakTextAsync("A simple test to write to a file.").get();
}

執行程式,而合成的 .wav 檔案會寫入至您指定的位置。 這是最基本用法的絕佳範例,但您接著會探討如何自訂輸出,以及如何將輸出回應當作記憶體內部資料流處理,以便處理自訂案例。

合成為喇叭輸出

在某些情況下,您可以直接將合成的語音輸出至喇叭。 若要這樣做,請在 AudioConfig SpeechSynthesizer 上述範例中建立時省略參數。 這會會合成至目前作用中的輸出裝置。

void synthesizeSpeech()
{
    auto config = SpeechConfig::FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    auto synthesizer = SpeechSynthesizer::FromConfig(config);
    auto result = synthesizer->SpeakTextAsync("Synthesizing directly to speaker output.").get();
}

以記憶體內部資料流程的形式取得結果

在語音應用程式開發的許多案例中,您可能需要產生的音訊資料作為記憶體內部資料流,而非直接寫入至檔案。 這可讓您建立自訂行為,包括:

  • 將產生的位元組陣列摘要成為自訂下游服務的可搜尋資料流。
  • 將結果與其他 API 或服務整合。
  • 修改音訊資料、撰寫自訂 .wav 標頭等。

從上一個範例進行這項變更很簡單。 首先,移除 AudioConfig,因為您會從這個時間點開始手動管理輸出行為,以提高掌控權。 然後在 SpeechSynthesizer 建構函式中針對 AudioConfig 傳遞 NULL

注意

針對 AudioConfig 傳遞 NULL (而非如同在上述喇叭輸出範例中加以省略),並不會在目前作用中的輸出裝置上依預設播放音訊。

這次,您會將結果儲存至 SpeechSynthesisResult 變數。 GetAudioData getter 會傳回輸出資料的 byte []。 您可以手動處理此 byte [],也可以使用 AudioDataStream 類別來管理記憶體內部資料流。 在此範例中,您會使用 AudioDataStream.FromResult() 靜態函式從結果中取得資料流。

void synthesizeSpeech()
{
    auto config = SpeechConfig::FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    auto synthesizer = SpeechSynthesizer::FromConfig(config, NULL);

    auto result = synthesizer->SpeakTextAsync("Getting the response as an in-memory stream.").get();
    auto stream = AudioDataStream::FromResult(result);
}

在此,您可使用所產生的 stream 物件來實作任何自訂行為。

自訂音訊格式

下一節說明如何自訂音訊輸出屬性,包括:

  • 音訊檔案類型
  • 採樣速率
  • 位元深度

若要變更音訊格式,請在 SpeechConfig 物件上使用 SetSpeechSynthesisOutputFormat() 函式。 此函式應該有 SpeechSynthesisOutputFormat 類型的 enum,您可使用此類型來選取輸出格式。 如需可用的音訊格式清單,請參閱參考文件。

根據您的需求而定,有各種選項可供不同的檔案類型使用。 請注意,依照定義,原始格式 (例如 Raw24Khz16BitMonoPcm) 不包含音訊標頭。 只有在您知道下游實作可將原始位元資料流解碼,或者打算根據位元深度、採樣速率、通道數目等手動建立標頭時,才會使用原始格式。

在此範例中,您可藉由在 SpeechConfig 物件上設定 SpeechSynthesisOutputFormat,以指定高精確度的 RIFF 格式 Riff24Khz16BitMonoPcm。 與上一節中的範例類似,您可使用 AudioDataStream 來取得結果的記憶體內部資料流,然後將其寫入至檔案。

void synthesizeSpeech()
{
    auto config = SpeechConfig::FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    config->SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat::Riff24Khz16BitMonoPcm);

    auto synthesizer = SpeechSynthesizer::FromConfig(config, NULL);
    auto result = synthesizer->SpeakTextAsync("A simple test to write to a file.").get();

    auto stream = AudioDataStream::FromResult(result);
    stream->SaveToWavFileAsync("path/to/write/file.wav").get();
}

再次執行您的程式,會將 .wav 檔案寫入至指定的路徑。

使用 SSML 來自訂語音特性

語音合成標記語言 (SSML) 可讓您從 XML 結構描述提交要求,以微調文字轉換語音輸出的音調、發音、說話速度、音量等等。 本節顯示變更聲音的範例,但如需詳細的指南,請參閱 SSML 操作說明文章

若要開始使用 SSML 進行自訂,您可進行簡單變更來切換語音。 首先,在根專案目錄中為 SSML 組態建立新的 XML 檔案,在此範例中為 ssml.xml。 根元素一律為 <speak>,而將文字包裝在 <voice> 元素中,可讓您使用 name 參數來變更語音。 請參閱支援的 神經 語音的 完整清單

<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
  <voice name="en-US-ChristopherNeural">
    When you're on the freeway, it's a good idea to use a GPS.
  </voice>
</speak>

接下來,您需要變更語音合成要求以參考您的 XML 檔案。 要求大多數相同,但您會使用 SpeakSsmlAsync(),而不是使用 SpeakTextAsync() 函式。 此函式應該有 XML 字串,因此您會先以字串形式載入 SSML 組態。 從這裡開始,結果物件會與先前的範例完全相同。

void synthesizeSpeech()
{
    auto config = SpeechConfig::FromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    auto synthesizer = SpeechSynthesizer::FromConfig(config, NULL);

    std::ifstream file("./ssml.xml");
    std::string ssml, line;
    while (std::getline(file, line))
    {
        ssml += line;
        ssml.push_back('\n');
    }
    auto result = synthesizer->SpeakSsmlAsync(ssml).get();

    auto stream = AudioDataStream::FromResult(result);
    stream->SaveToWavFileAsync("path/to/write/file.wav").get();
}

注意

若要在不使用 SSML 的情況下變更語音,您可以使用,在上設定屬性。 SpeechConfig``SpeechConfig.SetSpeechSynthesisVoiceName("en-US-ChristopherNeural")

取得臉部姿勢事件

語音是推動臉部表情動畫的好方法。 通常會使用 visemes 來代表觀察語音中的索引鍵,例如,在產生特定音素時,lip、jaw 和吐的位置。 您可以在語音 SDK 中訂閱 viseme 事件。 然後,您可以套用 viseme 事件,以動畫顯示在語音音訊播放時的字元臉部。 瞭解 如何取得 viseme 事件

在本快速入門中,您將了解如何使用語音 SDK 進行文字轉換語音合成的常見設計模式。

跳至 GitHub 上的範例

如果要直接跳到範例程式碼,請參閱 GitHub 上的 Go 快速入門範例

必要條件

本文假設您具有 Azure 帳戶和語音服務訂用帳戶。 如果您沒有該帳戶和訂用帳戶,請免費試用語音服務

安裝語音 SDK

您必須先安裝適用於 Go 的語音 SDK,才能執行動作。

文字轉換語音到說話者

使用下列程式碼範例,對您的預設音訊輸出裝置執行語音合成。 將變數取代 subscription region 為您的語音金鑰和位置/區域。 執行腳本會將您的輸入文字告知預設喇叭。

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "time"

    "github.com/Microsoft/cognitive-services-speech-sdk-go/audio"
    "github.com/Microsoft/cognitive-services-speech-sdk-go/common"
    "github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)

func synthesizeStartedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("Synthesis started.")
}

func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Printf("Synthesizing, audio chunk size %d.\n", len(event.Result.AudioData))
}

func synthesizedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Printf("Synthesized, audio length %d.\n", len(event.Result.AudioData))
}

func cancelledHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("Received a cancellation.")
}

func main() {
    subscription := "<paste-your-speech-key-here>"
    region := "<paste-your-speech-location/region-here>"

    audioConfig, err := audio.NewAudioConfigFromDefaultSpeakerOutput()
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer audioConfig.Close()
    config, err := speech.NewSpeechConfigFromSubscription(subscription, region)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer config.Close()
    speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(config, audioConfig)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechSynthesizer.Close()

    speechSynthesizer.SynthesisStarted(synthesizeStartedHandler)
    speechSynthesizer.Synthesizing(synthesizingHandler)
    speechSynthesizer.SynthesisCompleted(synthesizedHandler)
    speechSynthesizer.SynthesisCanceled(cancelledHandler)

    for {
        fmt.Printf("Enter some text that you want to speak, or enter empty text to exit.\n> ")
        text, _ := bufio.NewReader(os.Stdin).ReadString('\n')
        text = strings.TrimSuffix(text, "\n")
        if len(text) == 0 {
            break
        }

        task := speechSynthesizer.SpeakTextAsync(text)
        var outcome speech.SpeechSynthesisOutcome
        select {
        case outcome = <-task:
        case <-time.After(60 * time.Second):
            fmt.Println("Timed out")
            return
        }
        defer outcome.Close()
        if outcome.Error != nil {
            fmt.Println("Got an error: ", outcome.Error)
            return
        }

        if outcome.Result.Reason == common.SynthesizingAudioCompleted {
            fmt.Printf("Speech synthesized to speaker for text [%s].\n", text)
        } else {
            cancellation, _ := speech.NewCancellationDetailsFromSpeechSynthesisResult(outcome.Result)
            fmt.Printf("CANCELED: Reason=%d.\n", cancellation.Reason)

            if cancellation.Reason == common.Error {
                fmt.Printf("CANCELED: ErrorCode=%d\nCANCELED: ErrorDetails=[%s]\nCANCELED: Did you update the subscription info?\n",
                    cancellation.ErrorCode,
                    cancellation.ErrorDetails)
            }
        }
    }
}

執行下列命令,以建立 go.mod 連結至 GitHub 上裝載之元件的檔案。

go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go

現在建置並執行程式碼。

go build
go run quickstart

如需 SpeechConfigSpeechSynthesizer 類別的詳細資訊,請參閱參考文件。

文字轉換語音至記憶體內資料流程

在語音應用程式開發的許多案例中,您可能需要產生的音訊資料作為記憶體內部資料流,而非直接寫入至檔案。 這可讓您建立自訂行為,包括:

  • 將產生的位元組陣列摘要成為自訂下游服務的可搜尋資料流。
  • 將結果與其他 API 或服務整合。
  • 修改音訊資料、撰寫自訂 .wav 標頭等。

從上一個範例進行這項變更很簡單。 首先,移除 AudioConfig,因為您會從這個時間點開始手動管理輸出行為,以提高掌控權。 然後在 SpeechSynthesizer 建構函式中針對 AudioConfig 傳遞 nil

注意

針對 AudioConfig 傳遞 nil (而非如同在上述喇叭輸出範例中加以省略),並不會在目前作用中的輸出裝置上依預設播放音訊。

這次,您會將結果儲存至 SpeechSynthesisResult 變數。 屬性會傳回 AudioData []byte 輸出資料的。 您可以手動處理此 []byte,也可以使用 AudioDataStream 類別來管理記憶體內部資料流。 在此範例中,您會使用靜態函式 NewAudioDataStreamFromSpeechSynthesisResult() 從結果中取得資料流程。

將變數取代 subscription region 為您的語音金鑰和位置/區域。

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
    "strings"
    "time"

    "github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)

func main(subscription string, region string) {
    subscription := "<paste-your-speech-key-here>"
    region := "<paste-your-speech-location/region-here>"

    config, err := speech.NewSpeechConfigFromSubscription(subscription, region)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer config.Close()
    speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(config, nil)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechSynthesizer.Close()

    speechSynthesizer.SynthesisStarted(synthesizeStartedHandler)
    speechSynthesizer.Synthesizing(synthesizingHandler)
    speechSynthesizer.SynthesisCompleted(synthesizedHandler)
    speechSynthesizer.SynthesisCanceled(cancelledHandler)

    for {
        fmt.Printf("Enter some text that you want to speak, or enter empty text to exit.\n> ")
        text, _ := bufio.NewReader(os.Stdin).ReadString('\n')
        text = strings.TrimSuffix(text, "\n")
        if len(text) == 0 {
            break
        }

        // StartSpeakingTextAsync sends the result to channel when the synthesis starts.
        task := speechSynthesizer.StartSpeakingTextAsync(text)
        var outcome speech.SpeechSynthesisOutcome
        select {
        case outcome = <-task:
        case <-time.After(60 * time.Second):
            fmt.Println("Timed out")
            return
        }
        defer outcome.Close()
        if outcome.Error != nil {
            fmt.Println("Got an error: ", outcome.Error)
            return
        }

        // in most case we want to streaming receive the audio to lower the latency,
        // we can use AudioDataStream to do so.
        stream, err := speech.NewAudioDataStreamFromSpeechSynthesisResult(outcome.Result)
        defer stream.Close()
        if err != nil {
            fmt.Println("Got an error: ", err)
            return
        }

        var all_audio []byte
        audio_chunk := make([]byte, 2048)
        for {
            n, err := stream.Read(audio_chunk)

            if err == io.EOF {
                break
            }

            all_audio = append(all_audio, audio_chunk[:n]...)
        }

        fmt.Printf("Read [%d] bytes from audio data stream.\n", len(all_audio))
    }
}

執行下列命令,以建立 go.mod 連結至 GitHub 上裝載之元件的檔案。

go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go

現在建置並執行程式碼。

go build
go run quickstart

如需 SpeechConfigSpeechSynthesizer 類別的詳細資訊,請參閱參考文件。

使用 SSML 來自訂語音特性

語音合成標記語言 (SSML) 可讓您從 XML 結構描述提交要求,以微調文字轉換語音輸出的音調、發音、說話速度、音量等等。 本節顯示變更聲音的範例,但如需詳細的指南,請參閱 SSML 操作說明文章

若要開始使用 SSML 進行自訂,您可進行簡單變更來切換語音。 首先,在根專案目錄中為 SSML 組態建立新的 XML 檔案,在此範例中為 ssml.xml。 根元素一律為 <speak>,而將文字包裝在 <voice> 元素中,可讓您使用 name 參數來變更語音。 請參閱支援的 神經 語音的 完整清單

<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
  <voice name="en-US-ChristopherNeural">
    When you're on the freeway, it's a good idea to use a GPS.
  </voice>
</speak>

接下來,您需要變更語音合成要求以參考您的 XML 檔案。 要求大多數相同,但您會使用 SpeakSsmlAsync(),而不是使用 SpeakTextAsync() 函式。 此函式應該有 XML 字串,因此您會先以字串形式載入 SSML 組態。 從這裡開始,結果物件會與先前的範例完全相同。

注意

若要在不使用 SSML 的情況下變更語音,您可以使用,在上設定屬性。 SpeechConfig``speechConfig.SetSpeechSynthesisVoiceName("en-US-ChristopherNeural")

取得臉部姿勢事件

語音是推動臉部表情動畫的好方法。 通常會使用 visemes 來代表觀察語音中的索引鍵,例如,在產生特定音素時,lip、jaw 和吐的位置。 您可以在語音 SDK 中訂閱 viseme 事件。 然後,您可以套用 viseme 事件,以動畫顯示在語音音訊播放時的字元臉部。 瞭解 如何取得 viseme 事件

在本快速入門中,您將了解如何使用語音 SDK 進行文字轉換語音合成的常見設計模式。 首先,您會進行基本設定與合成,並繼續處理更多用於自訂應用程式開發的高階範例,包括:

  • 以記憶體內部資料流的形式取得回應
  • 自訂輸出採樣速率和位元速率
  • 使用 SSML 提交合成要求 (語音合成標記語言)
  • 使用神經語音

跳至 GitHub 上的範例

如果要直接跳到範例程式碼,請參閱 GitHub 上的 Java 快速入門範例

必要條件

本文假設您具有 Azure 帳戶和語音服務訂用帳戶。 如果您沒有該帳戶和訂用帳戶,請免費試用語音服務

安裝語音 SDK

您必須先安裝語音 SDK,才能執行動作。 根據您的平台,使用下列指示:

匯入相依性

若要執行本文中的範例,請在指令碼的頂端包含下列 import 陳述式。

import com.microsoft.cognitiveservices.speech.AudioDataStream;
import com.microsoft.cognitiveservices.speech.SpeechConfig;
import com.microsoft.cognitiveservices.speech.SpeechSynthesizer;
import com.microsoft.cognitiveservices.speech.SpeechSynthesisOutputFormat;
import com.microsoft.cognitiveservices.speech.SpeechSynthesisResult;
import com.microsoft.cognitiveservices.speech.audio.AudioConfig;

import java.io.*;
import java.util.Scanner;

建立語音設定

若要使用語音 SDK 來呼叫語音服務,您必須建立 SpeechConfig。 此類別包含您的訂用帳戶的相關資訊,例如您的語音金鑰以及相關聯的位置/區域、端點、主機或授權權杖。

注意

無論您是執行語音辨識、語音合成、翻譯還是意圖辨識,都一定會建立設定。

您可以透過數種方式將 SpeechConfig 初始化:

  • 使用訂用帳戶:傳入語音金鑰和相關聯的位置/區域。
  • 使用端點:傳入語音服務端點。 語音金鑰或授權權杖是選擇性的。
  • 使用主機:傳入主機位址。 語音金鑰或授權權杖是選擇性的。
  • 使用授權權杖:傳入授權權杖和相關聯的位置/區域。

在此範例中,您會 SpeechConfig 使用語音金鑰和位置/區域來建立。 請依照免費試用語音服務中的步驟,來取得這些認證。 您也會建立一些基本的重複使用程式碼,用於本文的其餘部分,而您可針對不同的自訂項目進行修改。

public class Program
{
    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    }
}

將語音合成至檔案

接下來,您會建立 SpeechSynthesizer 物件,以執行文字轉換語音並輸出至喇叭、檔案或其他輸出串流。 SpeechSynthesizer 接受以下物件作為參數:在上一個步驟中建立的 SpeechConfig 物件,以及可指定應如何處理輸出結果的 AudioConfig 物件。

若要開始,請建立 AudioConfig,以使用 fromWavFileOutput() 靜態函式將輸出自動寫入至 .wav 檔案。

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
}

接下來,將 speechConfig 物件和 audioConfig 物件當作參數傳遞,以具現化 SpeechSynthesizer。 然後,執行語音合成並寫入檔案,就像使用文字字串執行 SpeakText() 一樣簡單。

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");

    SpeechSynthesizer synthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    synthesizer.SpeakText("A simple test to write to a file.");
}

執行程式,而合成的 .wav 檔案會寫入至您指定的位置。 這是最基本用法的絕佳範例,但您接著會探討如何自訂輸出,以及如何將輸出回應當作記憶體內部資料流處理,以便處理自訂案例。

合成為喇叭輸出

在某些情況下,您可以直接將合成的語音輸出至喇叭。 若要這麼做,請使用 fromDefaultSpeakerOutput() 靜態函式來具現化 AudioConfig。 這會輸出到目前作用中的輸出裝置。

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    AudioConfig audioConfig = AudioConfig.fromDefaultSpeakerOutput();

    SpeechSynthesizer synthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    synthesizer.SpeakText("Synthesizing directly to speaker output.");
}

以記憶體內部資料流程的形式取得結果

在語音應用程式開發的許多案例中,您可能需要產生的音訊資料作為記憶體內部資料流,而非直接寫入至檔案。 這可讓您建立自訂行為,包括:

  • 將產生的位元組陣列摘要成為自訂下游服務的可搜尋資料流。
  • 將結果與其他 API 或服務整合。
  • 修改音訊資料、撰寫自訂 .wav 標頭等。

從上一個範例進行這項變更很簡單。 首先,移除 AudioConfig 區塊,因為您會從這個時間點開始手動管理輸出行為,以提高掌控權。 然後在 SpeechSynthesizer 建構函式中針對 AudioConfig 傳遞 null

注意

針對 AudioConfig 傳遞 null (而非如同在上述喇叭輸出範例中加以省略),並不會在目前作用中的輸出裝置上依預設播放音訊。

這次,您會將結果儲存至 SpeechSynthesisResult 變數。 SpeechSynthesisResult.getAudioData() 函式會傳回輸出資料的 byte []。 您可以手動處理此 byte [],也可以使用 AudioDataStream 類別來管理記憶體內部資料流。 在此範例中,您會使用 AudioDataStream.fromResult() 靜態函式從結果中取得資料流。

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    SpeechSynthesizer synthesizer = new SpeechSynthesizer(speechConfig, null);

    SpeechSynthesisResult result = synthesizer.SpeakText("Getting the response as an in-memory stream.");
    AudioDataStream stream = AudioDataStream.fromResult(result);
    System.out.print(stream.getStatus());
}

在此,您可使用所產生的 stream 物件來實作任何自訂行為。

自訂音訊格式

下一節說明如何自訂音訊輸出屬性,包括:

  • 音訊檔案類型
  • 採樣速率
  • 位元深度

若要變更音訊格式,請在 SpeechConfig 物件上使用 setSpeechSynthesisOutputFormat() 函式。 此函式應該有 SpeechSynthesisOutputFormat 類型的 enum,您可使用此類型來選取輸出格式。 如需可用的音訊格式清單,請參閱參考文件。

根據您的需求而定,有各種選項可供不同的檔案類型使用。 請注意,依照定義,原始格式 (例如 Raw24Khz16BitMonoPcm) 不包含音訊標頭。 只有在您知道下游實作可將原始位元資料流解碼,或者打算根據位元深度、採樣速率、通道數目等手動建立標頭時,才會使用原始格式。

在此範例中,您可藉由在 SpeechConfig 物件上設定 SpeechSynthesisOutputFormat,以指定高精確度的 RIFF 格式 Riff24Khz16BitMonoPcm。 與上一節中的範例類似,您可使用 AudioDataStream 來取得結果的記憶體內部資料流,然後將其寫入至檔案。

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");

    // set the output format
    speechConfig.setSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);

    SpeechSynthesizer synthesizer = new SpeechSynthesizer(speechConfig, null);
    SpeechSynthesisResult result = synthesizer.SpeakText("Customizing audio output format.");
    AudioDataStream stream = AudioDataStream.fromResult(result);
    stream.saveToWavFile("path/to/write/file.wav");
}

再次執行您的程式,會將 .wav 檔案寫入至指定的路徑。

使用 SSML 來自訂語音特性

語音合成標記語言 (SSML) 可讓您從 XML 結構描述提交要求,以微調文字轉換語音輸出的音調、發音、說話速度、音量等等。 本節顯示變更聲音的範例,但如需詳細的指南,請參閱 SSML 操作說明文章

若要開始使用 SSML 進行自訂,您可進行簡單變更來切換語音。 首先,在根專案目錄中為 SSML 組態建立新的 XML 檔案,在此範例中為 ssml.xml。 根元素一律為 <speak>,而將文字包裝在 <voice> 元素中,可讓您使用 name 參數來變更語音。 請參閱支援的 神經 語音的 完整清單

<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
  <voice name="en-US-ChristopherNeural">
    When you're on the freeway, it's a good idea to use a GPS.
  </voice>
</speak>

接下來,您需要變更語音合成要求以參考您的 XML 檔案。 要求大多數相同,但您會使用 SpeakSsml(),而不是使用 SpeakText() 函式。 此函式應該有 XML 字串,因此您會先建立函式來載入 XML 檔案並以字串形式將其傳回。

private static String xmlToString(String filePath) {
    File file = new File(filePath);
    StringBuilder fileContents = new StringBuilder((int)file.length());

    try (Scanner scanner = new Scanner(file)) {
        while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + System.lineSeparator());
        }
        return fileContents.toString().trim();
    } catch (FileNotFoundException ex) {
        return "File not found.";
    }
}

由此看來,結果物件會與先前的範例完全相同。

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    SpeechSynthesizer synthesizer = new SpeechSynthesizer(speechConfig, null);

    String ssml = xmlToString("ssml.xml");
    SpeechSynthesisResult result = synthesizer.SpeakSsml(ssml);
    AudioDataStream stream = AudioDataStream.fromResult(result);
    stream.saveToWavFile("path/to/write/file.wav");
}

注意

若要在不使用 SSML 的情況下變更語音,您可以使用,在上設定屬性。 SpeechConfig``SpeechConfig.setSpeechSynthesisVoiceName("en-US-ChristopherNeural");

取得臉部姿勢事件

語音是推動臉部表情動畫的好方法。 通常會使用 visemes 來代表觀察語音中的索引鍵,例如,在產生特定音素時,lip、jaw 和吐的位置。 您可以在語音 SDK 中訂閱 viseme 事件以取得臉部動畫資料,然後將資料套用至臉部動畫期間的字元。 瞭解 如何取得 viseme 事件

在本快速入門中,您將了解如何使用語音 SDK 進行文字轉換語音合成的常見設計模式。 首先,您會進行基本設定與合成,並繼續處理更多用於自訂應用程式開發的高階範例,包括:

  • 以記憶體內部資料流的形式取得回應
  • 自訂輸出採樣速率和位元速率
  • 使用 SSML 提交合成要求 (語音合成標記語言)
  • 使用神經語音

跳至 GitHub 上的範例

如果要直接跳到範例程式碼,請參閱 GitHub 上的 JavaScript 快速入門範例

必要條件

本文假設您已有 Azure 帳戶和語音服務資源。 如果您沒有帳戶和資源,請 免費試用語音服務

安裝語音 SDK

您必須先安裝適用於 JavaScript 的語音 SDK,才能執行動作。 根據您的平台,使用下列指示:

此外,根據目標環境而定,請使用下列其中一項:

下載 適用於 JavaScript 的語音 SDK microsoft.cognitiveservices.speech.sdk.bundle.js 檔案並將其解壓縮,放在您的 HTML 檔案可存取的資料夾中。

<script src="microsoft.cognitiveservices.speech.sdk.bundle.js"></script>;

提示

如果您是以網頁瀏覽器為目標,並使用 <script> 標籤,則不需要 sdk 前置詞。 sdk 前置詞是用來命名 require 模組的別名。

建立語音設定

若要使用語音 SDK 來呼叫語音服務,您必須建立 SpeechConfig。 此類別包含您的資源相關資訊,例如您的語音金鑰以及相關聯的位置/區域、端點、主機或授權權杖。

注意

無論您是執行語音辨識、語音合成、翻譯還是意圖辨識,都一定會建立設定。

您可以透過數種方式將 SpeechConfig 初始化:

  • 使用資源:傳入語音金鑰和相關聯的位置/區域。
  • 使用端點:傳入語音服務端點。 語音金鑰或授權權杖是選擇性的。
  • 使用主機:傳入主機位址。 語音金鑰或授權權杖是選擇性的。
  • 使用授權權杖:傳入授權權杖和相關聯的位置/區域。

在此範例中,您會 SpeechConfig 使用語音金鑰和位置/區域來建立。 請依照免費試用語音服務中的步驟,來取得這些認證。 您也會建立一些基本的重複使用程式碼,用於本文的其餘部分,而您可針對不同的自訂項目進行修改。

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
}

synthesizeSpeech();

將語音合成至檔案

接下來,您會建立 SpeechSynthesizer 物件,以執行文字轉換語音並輸出至喇叭、檔案或其他輸出串流。 SpeechSynthesizer 接受以下物件作為參數:在上一個步驟中建立的 SpeechConfig 物件,以及可指定應如何處理輸出結果的 AudioConfig 物件。

若要開始,請建立 AudioConfig,以使用 fromAudioFileOutput() 靜態函式將輸出自動寫入至 .wav 檔案。

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    const audioConfig = sdk.AudioConfig.fromAudioFileOutput("path/to/file.wav");
}

接下來,將 speechConfig 物件和 audioConfig 物件當作參數傳遞,以具現化 SpeechSynthesizer。 然後,執行語音合成並寫入檔案,就像使用文字字串執行 speakTextAsync() 一樣簡單。 結果回呼是呼叫 synthesizer.close() 的絕佳位置,事實上,為了讓合成正常運作,您需要進行此呼叫。

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    const audioConfig = sdk.AudioConfig.fromAudioFileOutput("path-to-file.wav");

    const synthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    synthesizer.speakTextAsync(
        "A simple test to write to a file.",
        result => {
            synthesizer.close();
            if (result) {
                // return result as stream
                return fs.createReadStream("path-to-file.wav");
            }
        },
        error => {
            console.log(error);
            synthesizer.close();
        });
}

執行程式,而合成的 .wav 檔案會寫入至您指定的位置。 這是最基本用法的絕佳範例,但您接著會探討如何自訂輸出,以及如何將輸出回應當作記憶體內部資料流處理,以便處理自訂案例。

合成至說話者輸出 (瀏覽器)

在某些情況下,您可以直接將合成的語音輸出至喇叭。 若要這麼做,請使用 fromDefaultSpeakerOutput() 靜態函式來具現化 AudioConfig。 這會輸出到目前作用中的輸出裝置。

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    const audioConfig = sdk.AudioConfig.fromDefaultSpeakerOutput();

    const synthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    synthesizer.speakTextAsync(
        "Synthesizing directly to speaker output.",
        result => {
            if (result) {
                synthesizer.close();
                return result.audioData;
            }
        },
        error => {
            console.log(error);
            synthesizer.close();
        });
}

以記憶體內部資料流程的形式取得結果

在語音應用程式開發的許多案例中,您可能需要產生的音訊資料作為記憶體內部資料流,而非直接寫入至檔案。 這可讓您建立自訂行為,包括:

  • 將產生的位元組陣列摘要成為自訂下游服務的可搜尋資料流。
  • 將結果與其他 API 或服務整合。
  • 修改音訊資料、撰寫自訂 .wav 標頭等。

從上一個範例進行這項變更很簡單。 首先,移除 AudioConfig 區塊,因為您會從這個時間點開始手動管理輸出行為,以提高掌控權。 然後在 SpeechSynthesizer 建構函式中針對 AudioConfig 傳遞 undefined

注意

針對 AudioConfig 傳遞 undefined (而非如同在上述喇叭輸出範例中加以省略),並不會在目前作用中的輸出裝置上依預設播放音訊。

這次,您會將結果儲存至 SpeechSynthesisResult 變數。 屬性會傳回 SpeechSynthesisResult.audioData ArrayBuffer 輸出資料的,也就是預設瀏覽器資料流程類型。 針對伺服器程式碼,將 arrayBuffer 轉換為緩衝區資料流程。

下列程式碼適用于用戶端程式代碼。

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    const synthesizer = new sdk.SpeechSynthesizer(speechConfig);

    synthesizer.speakTextAsync(
        "Getting the response as an in-memory stream.",
        result => {
            synthesizer.close();
            return result.audioData;
        },
        error => {
            console.log(error);
            synthesizer.close();
        });
}

在此,您可使用所產生的 ArrayBuffer 物件來實作任何自訂行為。 ArrayBuffer 是要在瀏覽器中接收並從此格式播放的一般類型。

針對任何以伺服器為基礎的程式碼,如果您需要以資料流程(而不是 ArrayBuffer)來處理資料,您需要將物件轉換為數據流。

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    const synthesizer = new sdk.SpeechSynthesizer(speechConfig);

    synthesizer.speakTextAsync(
        "Getting the response as an in-memory stream.",
        result => {
            const { audioData } = result;

            synthesizer.close();

            // convert arrayBuffer to stream
            // return stream
            const bufferStream = new PassThrough();
            bufferStream.end(Buffer.from(audioData));
            return bufferStream;
        },
        error => {
            console.log(error);
            synthesizer.close();
        });
}

自訂音訊格式

下一節說明如何自訂音訊輸出屬性,包括:

  • 音訊檔案類型
  • 採樣速率
  • 位元深度

若要變更音訊格式,請在 SpeechConfig 物件上使用 speechSynthesisOutputFormat 屬性。 此屬性應該有 SpeechSynthesisOutputFormat 類型的 enum,您可使用此類型來選取輸出格式。 如需可用的音訊格式清單,請參閱參考文件。

根據您的需求而定,有各種選項可供不同的檔案類型使用。 請注意,依照定義,原始格式 (例如 Raw24Khz16BitMonoPcm) 不包含音訊標頭。 只有在您知道下游實作可將原始位元資料流解碼,或者打算根據位元深度、採樣速率、通道數目等手動建立標頭時,才會使用原始格式。

在此範例中,您可藉由在 SpeechConfig 物件上設定 speechSynthesisOutputFormat,以指定高精確度的 RIFF 格式 Riff24Khz16BitMonoPcm。 與上一節的範例類似,請取得音訊 ArrayBuffer 資料並與其互動。

function synthesizeSpeech() {
    const speechConfig = SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");

    // Set the output format
    speechConfig.speechSynthesisOutputFormat = SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm;

    const synthesizer = new sdk.SpeechSynthesizer(speechConfig, undefined);
    synthesizer.speakTextAsync(
        "Customizing audio output format.",
        result => {
            // Interact with the audio ArrayBuffer data
            const audioData = result.audioData;
            console.log(`Audio data byte size: ${audioData.byteLength}.`)

            synthesizer.close();
        },
        error => {
            console.log(error);
            synthesizer.close();
        });
}

再次執行您的程式,會將 .wav 檔案寫入至指定的路徑。

使用 SSML 來自訂語音特性

語音合成標記語言 (SSML) 可讓您從 XML 結構描述提交要求,以微調文字轉換語音輸出的音調、發音、說話速度、音量等等。 本節顯示變更聲音的範例,但如需詳細的指南,請參閱 SSML 操作說明文章

若要開始使用 SSML 進行自訂,您可進行簡單變更來切換語音。 首先,在根專案目錄中為 SSML 組態建立新的 XML 檔案,在此範例中為 ssml.xml。 根元素一律為 <speak>,而將文字包裝在 <voice> 元素中,可讓您使用 name 參數來變更語音。 請參閱支援的 神經 語音的 完整清單

<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
  <voice name="en-US-ChristopherNeural">
    When you're on the freeway, it's a good idea to use a GPS.
  </voice>
</speak>

接下來,您需要變更語音合成要求以參考您的 XML 檔案。 要求大多數相同,但您會使用 speakSsmlAsync(),而不是使用 speakTextAsync() 函式。 此函式應該有 XML 字串,因此您會先建立函式來載入 XML 檔案並以字串形式將其傳回。

function xmlToString(filePath) {
    const xml = readFileSync(filePath, "utf8");
    return xml;
}

如需 readFileSync 的詳細資訊,請參閱 Node.js 檔案系統。 由此看來,結果物件會與先前的範例完全相同。

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("<paste-your-speech-key-here>", "<paste-your-speech-location/region-here>");
    const synthesizer = new sdk.SpeechSynthesizer(speechConfig, undefined);

    const ssml = xmlToString("ssml.xml");
    synthesizer.speakSsmlAsync(
        ssml,
        result => {
            if (result.errorDetails) {
                console.error(result.errorDetails);
            } else {
                console.log(JSON.stringify(result));
            }

            synthesizer.close();
        },
        error => {
            console.log(error);
            synthesizer.close();
        });
}

注意

若要在不使用 SSML 的情況下變更語音,您可以使用,在上設定屬性。 SpeechConfig``SpeechConfig.speechSynthesisVoiceName = "en-US-ChristopherNeural";

取得臉部姿勢事件

語音是推動臉部表情動畫的好方法。 通常會使用 visemes 來代表觀察語音中的索引鍵,例如,在產生特定音素時,lip、jaw 和吐的位置。 您可以在語音 SDK 中訂閱 viseme 事件。 然後,您可以套用 viseme 事件,以動畫顯示在語音音訊播放時的字元臉部。 瞭解 如何取得 viseme 事件

您可以使用適用於 Swift 和 Objective-C 的語音 SDK,從文字合成語音。

必要條件

下列範例假設您具有 Azure 帳戶和語音服務訂用帳戶。 如果您沒有該帳戶和訂用帳戶,請免費試用語音服務

安裝語音 SDK 和範例

認知服務語音 SDK 包含以 Swift 和 Objective-C 撰寫的範例,適用於 iOS 和 Mac。 按一下連結可查看每個範例的安裝指示:

我們也會提供適用於 Objective-C 參考的線上語音 SDK

在本快速入門中,您將了解如何使用語音 SDK 進行文字轉換語音合成的常見設計模式。 首先,您會進行基本設定與合成,並繼續處理更多用於自訂應用程式開發的高階範例,包括:

  • 以記憶體內部資料流的形式取得回應
  • 自訂輸出採樣速率和位元速率
  • 使用 SSML 提交合成要求 (語音合成標記語言)
  • 使用神經語音

跳至 GitHub 上的範例

如果要直接跳到範例程式碼,請參閱 GitHub 上的 Python 快速入門範例

必要條件

本文假設您具有 Azure 帳戶和語音服務訂用帳戶。 如果您沒有該帳戶和訂用帳戶,請免費試用語音服務

安裝語音 SDK

您必須先安裝語音 SDK,才能執行動作。

pip install azure-cognitiveservices-speech

如果您在使用 macOS 時遇到安裝問題,您可能需要先執行此命令。

python3 -m pip install --upgrade pip

安裝語音 SDK 之後,請在指令碼的頂端包含下列 import 陳述式。

from azure.cognitiveservices.speech import AudioDataStream, SpeechConfig, SpeechSynthesizer, SpeechSynthesisOutputFormat
from azure.cognitiveservices.speech.audio import AudioOutputConfig

建立語音設定

若要使用語音 SDK 來呼叫語音服務,您必須建立 SpeechConfig。 此類別包含您的訂用帳戶的相關資訊,例如您的語音金鑰以及相關聯的位置/區域、端點、主機或授權權杖。

注意

無論您是執行語音辨識、語音合成、翻譯還是意圖辨識,都一定會建立設定。

您可以透過數種方式將 SpeechConfig 初始化:

  • 使用訂用帳戶:傳入語音金鑰和相關聯的位置/區域。
  • 使用端點:傳入語音服務端點。 語音金鑰或授權權杖是選擇性的。
  • 使用主機:傳入主機位址。 語音金鑰或授權權杖是選擇性的。
  • 使用授權權杖:傳入授權權杖和相關聯的位置/區域。

在此範例中,您會 SpeechConfig 使用語音金鑰和位置/區域來建立。 請依照免費試用語音服務中的步驟,來取得這些認證。

speech_config = SpeechConfig(subscription="<paste-your-speech-key-here>", region="<paste-your-speech-location/region-here>")

將語音合成至檔案

接下來,您會建立 SpeechSynthesizer 物件,以執行文字轉換語音並輸出至喇叭、檔案或其他輸出串流。 SpeechSynthesizer 接受以下物件作為參數:在上一個步驟中建立的 SpeechConfig 物件,以及可指定應如何處理輸出結果的 AudioOutputConfig 物件。

若要開始,請建立 AudioOutputConfig,以使用 filename 建構函式參數,將輸出自動寫入至 .wav 檔案。

audio_config = AudioOutputConfig(filename="path/to/write/file.wav")

接下來,將 speech_config 物件和 audio_config 物件當作參數傳遞,以具現化 SpeechSynthesizer。 然後,執行語音合成並寫入檔案,就像使用文字字串執行 speak_text_async() 一樣簡單。

synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
synthesizer.speak_text_async("A simple test to write to a file.")

執行程式,而合成的 .wav 檔案會寫入至您指定的位置。 這是最基本用法的絕佳範例,但您接著會探討如何自訂輸出,以及如何將輸出回應當作記憶體內部資料流處理,以便處理自訂案例。

合成為喇叭輸出

在某些情況下,您可以直接將合成的語音輸出至喇叭。 若要這麼做,請使用上一節中的範例,但藉由移除 filename 參數來變更 AudioOutputConfig,然後設定 use_default_speaker=True。 這會輸出到目前作用中的輸出裝置。

audio_config = AudioOutputConfig(use_default_speaker=True)

以記憶體內部資料流程的形式取得結果

在語音應用程式開發的許多案例中,您可能需要產生的音訊資料作為記憶體內部資料流,而非直接寫入至檔案。 這可讓您建立自訂行為,包括:

  • 將產生的位元組陣列摘要成為自訂下游服務的可搜尋資料流。
  • 將結果與其他 API 或服務整合。
  • 修改音訊資料、撰寫自訂 .wav 標頭等。

從上一個範例進行這項變更很簡單。 首先,移除 AudioConfig,因為您會從這個時間點開始手動管理輸出行為,以提高掌控權。 然後在 SpeechSynthesizer 建構函式中針對 AudioConfig 傳遞 None

注意

針對 AudioConfig 傳遞 None (而非如同在上述喇叭輸出範例中加以省略),並不會在目前作用中的輸出裝置上依預設播放音訊。

這次,您會將結果儲存至 SpeechSynthesisResult 變數。 audio_data 屬性包含輸出資料的 bytes 物件。 您可以手動處理此物件,也可以使用 AudioDataStream 類別來管理記憶體內部資料流。 在此範例中,您會使用 AudioDataStream 建構函式,從結果中取得資料流。

synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=None)
result = synthesizer.speak_text_async("Getting the response as an in-memory stream.").get()
stream = AudioDataStream(result)

在此,您可使用所產生的 stream 物件來實作任何自訂行為。

自訂音訊格式

下一節說明如何自訂音訊輸出屬性,包括:

  • 音訊檔案類型
  • 採樣速率
  • 位元深度

若要變更音訊格式,請在 SpeechConfig 物件上使用 set_speech_synthesis_output_format() 函式。 此函式應該有 SpeechSynthesisOutputFormat 類型的 enum,您可使用此類型來選取輸出格式。 如需可用的音訊格式清單,請參閱參考文件。

根據您的需求而定,有各種選項可供不同的檔案類型使用。 請注意,依照定義,原始格式 (例如 Raw24Khz16BitMonoPcm) 不包含音訊標頭。 只有在您知道下游實作可將原始位元資料流解碼,或者打算根據位元深度、採樣速率、通道數目等手動建立標頭時,才會使用原始格式。

在此範例中,您可藉由在 SpeechConfig 物件上設定 SpeechSynthesisOutputFormat,以指定高精確度的 RIFF 格式 Riff24Khz16BitMonoPcm。 與上一節中的範例類似,您可使用 AudioDataStream 來取得結果的記憶體內部資料流,然後將其寫入至檔案。

speech_config.set_speech_synthesis_output_format(SpeechSynthesisOutputFormat["Riff24Khz16BitMonoPcm"])
synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=None)

result = synthesizer.speak_text_async("Customizing audio output format.").get()
stream = AudioDataStream(result)
stream.save_to_wav_file("path/to/write/file.wav")

再次執行您的程式,會將自訂的 .wav 檔案寫入至指定的路徑。

使用 SSML 來自訂語音特性

語音合成標記語言 (SSML) 可讓您從 XML 結構描述提交要求,以微調文字轉換語音輸出的音調、發音、說話速度、音量等等。 本節顯示變更聲音的範例,但如需詳細的指南,請參閱 SSML 操作說明文章

若要開始使用 SSML 進行自訂,您可進行簡單變更來切換語音。 首先,在根專案目錄中為 SSML 組態建立新的 XML 檔案,在此範例中為 ssml.xml。 根元素一律為 <speak>,而將文字包裝在 <voice> 元素中,可讓您使用 name 參數來變更語音。 請參閱支援的 神經 語音的 完整清單

<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
  <voice name="en-US-ChristopherNeural">
    When you're on the freeway, it's a good idea to use a GPS.
  </voice>
</speak>

接下來,您需要變更語音合成要求以參考您的 XML 檔案。 要求大多數相同,但您會使用 speak_ssml_async(),而不是使用 speak_text_async() 函式。 此函式應該有 XML 字串,因此您會先以字串形式讀取 SSML 組態。 由此看來,結果物件會與先前的範例完全相同。

注意

如果 ssml_string 在字串開頭包含 ,則必須去除 BOM 格式,否則服務會傳回錯誤。 若要這麼做,請如下所示設定 encoding 參數:open("ssml.xml", "r", encoding="utf-8-sig")

synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=None)

ssml_string = open("ssml.xml", "r").read()
result = synthesizer.speak_ssml_async(ssml_string).get()

stream = AudioDataStream(result)
stream.save_to_wav_file("path/to/write/file.wav")

注意

若要在不使用 SSML 的情況下變更語音,您可以使用,在上設定屬性。 SpeechConfig``SpeechConfig.speech_synthesis_voice_name = "en-US-ChristopherNeural"

取得臉部姿勢事件

語音是推動臉部表情動畫的好方法。 通常會使用 visemes 來代表觀察語音中的索引鍵,例如,在產生特定音素時,lip、jaw 和吐的位置。 您可以在語音 SDK 中訂閱 viseme 事件。 然後,您可以套用 viseme 事件,以動畫顯示在語音音訊播放時的字元臉部。 瞭解 如何取得 viseme 事件

在本快速入門中,您將了解如何使用語音服務和 cURL 將文字轉換成語音。

如需有關文字轉換語音概念的高階探討,請參閱概觀文章。

必要條件

本文假設您具有 Azure 帳戶和語音服務訂用帳戶。 如果您沒有該帳戶和訂用帳戶,請免費試用語音服務

將文字轉換成語音

在命令提示字元中執行下列命令。 您必須將下列值插入命令中。

  • 您的語音服務訂用帳戶金鑰。
  • 您的語音服務區域。

您也可能想要變更下列值。

  • X-Microsoft-OutputFormat 標頭值,可控制音訊輸出格式。 您可以在文字轉換語音 REST API 參考中找到支援的音訊輸出格式清單。
  • 輸出語音。 若要取得語音端點可用的語音清單,請參閱下一節。
  • 輸出檔案。 在此範例中,我們會將伺服器的回應導向至名為 output.wav 的檔案。
curl --location --request POST 'https://INSERT_REGION_HERE.tts.speech.microsoft.com/cognitiveservices/v1' \
--header 'Ocp-Apim-Subscription-Key: INSERT_SUBSCRIPTION_KEY_HERE' \
--header 'Content-Type: application/ssml+xml' \
--header 'X-Microsoft-OutputFormat: audio-16khz-128kbitrate-mono-mp3' \
--header 'User-Agent: curl' \
--data-raw '<speak version='\''1.0'\'' xml:lang='\''en-US'\''>
    <voice xml:lang='\''en-US'\'' xml:gender='\''Female'\'' name='\''en-US-AriaRUS'\''>
        my voice is my passport verify me
    </voice>
</speak>' > output.wav

列出語音端點可用的語音

若要列出語音端點可用的語音,請執行下列命令。

curl --location --request GET 'https://INSERT_ENDPOINT_HERE.tts.speech.microsoft.com/cognitiveservices/voices/list' \
--header 'Ocp-Apim-Subscription-Key: INSERT_SUBSCRIPTION_KEY_HERE'

您應該會收到類似下列的回應。

[
    {
        "Name": "Microsoft Server Speech Text to Speech Voice (ar-EG, Hoda)",
        "DisplayName": "Hoda",
        "LocalName": "هدى",
        "ShortName": "ar-EG-Hoda",
        "Gender": "Female",
        "Locale": "ar-EG",
        "SampleRateHertz": "16000",
        "VoiceType": "Standard"
    },
    {
        "Name": "Microsoft Server Speech Text to Speech Voice (ar-SA, Naayf)",
        "DisplayName": "Naayf",
        "LocalName": "نايف",
        "ShortName": "ar-SA-Naayf",
        "Gender": "Male",
        "Locale": "ar-SA",
        "SampleRateHertz": "16000",
        "VoiceType": "Standard"
    },
    {
        "Name": "Microsoft Server Speech Text to Speech Voice (bg-BG, Ivan)",
        "DisplayName": "Ivan",
        "LocalName": "Иван",
        "ShortName": "bg-BG-Ivan",
        "Gender": "Male",
        "Locale": "bg-BG",
        "SampleRateHertz": "16000",
        "VoiceType": "Standard"
    },
    {
        // This response is truncated. The response will include 
        // a complete list of supported languages and specific 
        // details like short name, gender, etc. 
    }
]

在本快速入門中,您將了解如何使用語音 SDK 進行文字轉換語音合成的常見設計模式。 首先,您會進行基本設定與合成,並繼續處理更多用於自訂應用程式開發的高階範例,包括:

  • 以記憶體內部資料流的形式取得回應
  • 自訂輸出採樣速率和位元速率
  • 使用 SSML 提交合成要求 (語音合成標記語言)
  • 使用神經語音

必要條件

本文假設您具有 Azure 帳戶和語音服務訂用帳戶。 如果您沒有該帳戶和訂用帳戶,請免費試用語音服務

下載並安裝

請遵循下列步驟,在 Windows 上安裝語音 CLI:

  1. 在 Windows 上,您需根據平台來選擇適用於 Visual Studio 2019 的 Microsoft Visual C++ 可轉散發套件。 第一次安裝時可能需要重新開機。

  2. 安裝 .Net Core 3.1 SDK

  3. 輸入此命令,使用 NuGet 安裝語音 CLI:

    dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
    

輸入 spx 以查看語音 CLI 的說明。

注意

NuGet 的替代方案,您可以下載 Windows 的語音 CLI,並將其解壓縮為zip檔案。

字型限制

在 Windows 上,語音 CLI 只能顯示本機電腦上的命令提示字元可用的字型。 Windows 終端機 支援語音 CLI 以互動方式產生的所有字型。

如果您輸出至檔案,像是記事本或網頁瀏覽器 (例如 Microsoft Edge) 的文字編輯器也可以顯示所有字型。

建立訂用帳戶設定

若要開始使用語音 CLI,您必須輸入語音訂用帳戶金鑰和區域識別碼。 請依照免費試用語音服務中的步驟,來取得這些認證。 一旦您擁有訂用帳戶金鑰和區域識別碼 (例如, eastuswestus),請執行下列命令。

spx config @key --set SUBSCRIPTION-KEY
spx config @region --set REGION

現在會儲存您的訂用帳戶驗證以供未來的 SPX 要求之用。 如果您需要移除其中一個儲存的值,請執行 spx config @region --clearspx config @key --clear

將語音合成至喇叭

現在您已準備好執行語音 CLI,從文字合成語音。 從命令列,變更為包含語音 CLI 二進位檔案的目錄。 然後,執行下列命令。

spx synthesize --text "The speech synthesizer greets you!"

語音 CLI 會透過電腦喇叭,以英文產生自然語言。

將語音合成至檔案

執行下列命令,將說話者的輸出變更為 .wav 檔案。

spx synthesize --text "The speech synthesizer greets you!" --audio output greetings.wav

語音 CLI 會以英文產生自然語言成為 greetings.wav 音訊檔案。 在 Windows 中,您可以輸入 start greetings.wav 來播放音訊檔案。

取得位置資訊

您的專案可能需要知道文字轉換語音的單字,讓它可以根據該時間採取特定動作。 例如,如果您想要在說出單字時將其反白顯示,您需要知道要醒目提示的內容、何時將其反白顯示,以及要將它反白的時間長度。

您可以使用中提供的事件來完成此動作 WordBoundary SpeechSynthesizer 。 這個事件是在每個新讀出單字的開頭引發,並且會在語音串流內提供時間位移,並在輸入提示中提供文字位移。

  • AudioOffset 報告合成開頭和下一個單字開頭之間的輸出音訊經過時間。 這是以一百毫微秒的單位來測量, (HNS) ,10000的 HNS 相當於1毫秒。
  • WordOffset 在輸入字串中報告字元位置, (原始文字或 SSML) 緊接在要說出的單字之前。

注意

WordBoundary 事件會在輸出音訊資料變成可用時引發,這會比播放到輸出裝置更快。 將資料流程時間適當地同步處理至「即時」必須由呼叫端完成。

您可以在 WordBoundary GitHub 上找到使用文字轉換語音範例中的範例。

後續步驟