Jak syntetizovat řeč z textu

Referenční dokumentace | – balíček (NuGet) | Další ukázky na GitHubu

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Výběr jazyka syntézy a hlasu

Funkce převodu textu na řeč ve službě Speech podporuje více než 400 hlasů a více než 140 jazyků a variant. Můžete získat úplný seznam nebo je vyzkoušet v Galerii hlasu.

Zadejte jazyk nebo hlas, u SpeechConfig které chcete zadat vstupní text, a použijte zadaný hlas. Následující fragment kódu ukazuje, jak tato technika funguje:

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    // Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
    speechConfig.SpeechSynthesisLanguage = "en-US"; 
    speechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
}

Všechny neurální hlasy jsou vícejazyčné a fluentní ve svém vlastním jazyce a angličtině. Pokud je například vstupní text v angličtině "Jsem nadšený z pokusu o převod textu na řeč", a vyberete es-ES-ElviraNeural, text se mluví v angličtině se španělským zvýrazněním.

Pokud hlas nemluví jazykem vstupního textu, služba Speech nevytváří syntetizovaný zvuk. Úplný seznam podporovaných neurálních hlasů najdete v tématu Podpora jazyka a hlasu pro službu Speech.

Poznámka:

Výchozí hlas je první hlas vrácený pro každé národní prostředí z rozhraní API seznamu hlasu.

Hlas, který mluví, je určen v pořadí podle priority následujícím způsobem:

  • Pokud ho nenastavíte SpeechSynthesisVoiceName nebo SpeechSynthesisLanguage, výchozí hlas pro en-US mluvený hlas.
  • Pokud nastavíte SpeechSynthesisLanguagepouze , výchozí hlas pro zadané národní prostředí mluví.
  • Pokud jsou obě SpeechSynthesisVoiceName i SpeechSynthesisLanguage nastavené, SpeechSynthesisLanguage nastavení se ignoruje. Hlas, který určíte pomocí SpeechSynthesisVoiceName mluvených mluvčích.
  • Pokud je hlasový prvek nastaven pomocí jazyka SSML (Speech Synthesis Markup Language), budou ignorovány SpeechSynthesisVoiceName a SpeechSynthesisLanguage nastavení.

Syntetizace řeči do souboru

Vytvořte objekt SpeechSynthesizer . Tento objekt zobrazený v následujících fragmentech kódu spouští převody řeči a výstupy do mluvčích, souborů nebo jiných výstupních datových proudů. SpeechSynthesizer přijímá jako parametry:

  • Objekt SpeechConfig , který jste vytvořili v předchozím kroku.
  • Objekt AudioConfig , který určuje, jak se mají zpracovat výstupní výsledky.
  1. AudioConfig Vytvořte instanci, která automaticky zapíše výstup do souboru .wav pomocí FromWavFileOutput() funkce. Vytvořte instanci příkazem using .

    static async Task SynthesizeAudioAsync()
    {
        var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
        using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav");
    }
    

    Příkaz using v tomto kontextu automaticky odstraní nespravované prostředky a způsobí, že objekt po vyřazení z rozsahu nevypadne.

  2. Vytvořte instanci pomocí jiného SpeechSynthesizerusing příkazu. Předejte objekt speechConfig a audioConfig objekt jako parametry. Pokud chcete syntetizovat řeč a zapisovat do souboru, spusťte SpeakTextAsync() řetězec textu.

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav");
    using var speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
}

Když program spustíte, vytvoří syntetizovaný .wav soubor, který se zapíše do zadaného umístění. Tento výsledek je dobrým příkladem nejzákladnějšího použití. Dále můžete přizpůsobit výstup a zpracovat výstupní odpověď jako datový proud v paměti pro práci s vlastními scénáři.

Syntetizování výstupu reproduktoru

Pokud chcete výstupem syntetizované řeči do aktuálního aktivního výstupního zařízení, jako je například reproduktor, při vytváření SpeechSynthesizer instance parametr vynecháteAudioConfig. Tady je příklad:

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    using var speechSynthesizer = new SpeechSynthesizer(speechConfig);
    await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
}

Získání výsledku jako datového proudu v paměti

Výsledná zvuková data můžete použít jako datový proud v paměti místo přímého zápisu do souboru. Pomocí datového proudu v paměti můžete vytvářet vlastní chování:

  • Abstrahujte výsledné bajtové pole jako vyhledatelný datový proud pro vlastní podřízené služby.
  • Integrujte výsledek s jinými rozhraními API nebo službami.
  • Upravte zvuková data, zapište vlastní záhlaví .wav a proveďte související úlohy.

Tuto změnu můžete provést v předchozím příkladu. Nejprve blok odeberte, protože chování výstupu AudioConfig spravujete ručně od tohoto okamžiku, aby se zvýšila kontrola. AudioConfig Předejte null konstruktoruSpeechSynthesizer.

Poznámka:

AudioConfigKdyž ho předáte null , místo abyste ho vynechali jako v předchozím příkladu výstupu reproduktoru, ve výchozím nastavení se na aktuálním aktivním výstupním zařízení nepřehraje zvuk.

Uložte výsledek do proměnné SpeechSynthesisResult . Vlastnost AudioData obsahuje byte [] instanci pro výstupní data. S touto byte [] instancí můžete pracovat ručně nebo můžete ke správě datového proudu v paměti použít třídu AudioDataStream .

V tomto příkladu AudioDataStream.FromResult() použijete statickou funkci k získání datového proudu z výsledku:

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);

    var result = await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
    using var stream = AudioDataStream.FromResult(result);
}

V tomto okamžiku můžete implementovat jakékoli vlastní chování pomocí výsledného stream objektu.

Přizpůsobení formátu zvuku

Můžete přizpůsobit atributy zvukového výstupu, včetně:

  • Typ zvukového souboru
  • Vzorkovací frekvence
  • Hloubka bitu

Pokud chcete změnit formát zvuku SetSpeechSynthesisOutputFormat() , použijte funkci na objektu SpeechConfig . Tato funkce očekává enum instanci typu SpeechSynthesisOutputFormat. Pomocí příkazu enum vyberte výstupní formát. Dostupné formáty najdete v seznamu zvukových formátů.

Existují různé možnosti pro různé typy souborů v závislosti na vašich požadavcích. Podle definice nezpracované formáty, jako Raw24Khz16BitMonoPcm například neobsahují záhlaví zvuku. V jedné z těchto situací používejte nezpracované formáty:

  • Víte, že vaše podřízená implementace může dekódovat nezpracovaný bitstream.
  • Plánujete ručně vytvářet hlavičky na základě faktorů, jako je hloubka bitu, vzorkovací frekvence a počet kanálů.

Tento příklad určuje formát Riff24Khz16BitMonoPcm RIFF s vysokou věrností nastavením SpeechSynthesisOutputFormat objektu SpeechConfig . Podobně jako v příkladu v předchozí části použijete AudioDataStream k získání datového proudu výsledku v paměti a jeho následnému zápisu do souboru.

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    speechConfig.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);

    using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
    var result = await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");

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

Když program spustíte, zapíše .wav soubor do zadané cesty.

Přizpůsobení charakteristik řeči pomocí SSML

SSML můžete použít k vyladění tónu, výslovnosti, míry mluvení, hlasitosti a dalších aspektů v textu na výstup řeči odesláním požadavků ze schématu XML. Tato část ukazuje příklad změny hlasu. Další informace naleznete v tématu Přehled jazyka Speech Synthesis Markup Language.

Pokud chcete začít používat SSML k přizpůsobení, provedete menší změnu, která přepne hlas.

  1. Vytvořte nový soubor XML pro konfiguraci SSML v kořenovém adresáři projektu.

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

    V tomto příkladu je soubor ssml.xml. Kořenový prvek je vždy <speak>. Obtékání textu do elementu <voice> umožňuje změnit hlas pomocí parametru name . Úplný seznam podporovaných neurálních hlasů najdete v tématu Podporované jazyky.

  2. Změňte požadavek na syntézu řeči tak, aby odkaz na váš soubor XML. Požadavek je většinou stejný, ale místo použití SpeakTextAsync() funkce použijete SpeakSsmlAsync(). Tato funkce očekává řetězec XML. Nejprve načtěte konfiguraci SSML jako řetězec pomocí .File.ReadAllText() Z tohoto okamžiku je výsledný objekt přesně stejný jako předchozí příklady.

    Poznámka:

    Pokud používáte Visual Studio, konfigurace sestavení pravděpodobně ve výchozím nastavení nenajde váš soubor XML. Klikněte pravým tlačítkem myši na soubor XML a vyberte Vlastnosti. Změňte akci sestavení na obsah. Změňte možnost Kopírovat do výstupního adresáře tak, aby se vždy zkopírovala.

    public static async Task SynthesizeAudioAsync()
    {
        var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
        using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
    
        var ssml = File.ReadAllText("./ssml.xml");
        var result = await speechSynthesizer.SpeakSsmlAsync(ssml);
    
        using var stream = AudioDataStream.FromResult(result);
        await stream.SaveToWaveFileAsync("path/to/write/file.wav");
    }
    

Poznámka:

Pokud chcete změnit hlas bez použití SSML, můžete vlastnost SpeechConfig nastavit pomocí .SpeechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";

Přihlášení k odběru událostí syntetizátoru

Možná budete chtít získat další přehledy o zpracování textu a výsledcích řeči. Můžete například chtít vědět, kdy syntetizátor začíná a zastavuje, nebo můžete chtít vědět o jiných událostech, ke kterým došlo během syntézy.

Při použití speechSynthesizer pro převod textu na řeč můžete přihlásit k odběru událostí v této tabulce:

Událost Popis Případ použití
BookmarkReached Signály, že byla dosažena záložka. K aktivaci události bookmark dosažení záložky se v SSML vyžaduje prvek. Tato událost hlásí uplynulý čas výstupu zvuku mezi začátkem syntézy a prvkem bookmark . Vlastnost události Text je řetězcová hodnota, kterou jste nastavili v atributu záložky mark . Prvky bookmark nejsou mluvené. Pomocí elementu bookmark můžete vložit vlastní značky do SSML, abyste získali posun každé značky ve zvukovém streamu. Tento bookmark prvek lze použít k odkazování na konkrétní umístění v textu nebo sekvenci značek.
SynthesisCanceled Signály, že syntéza řeči byla zrušena. Můžete ověřit, kdy je syntéza zrušena.
SynthesisCompleted Signály, že syntéza řeči je kompletní. Po dokončení syntézy můžete potvrdit.
SynthesisStarted Signály, které syntéza řeči začala. Po spuštění syntézy můžete potvrdit.
Synthesizing Signály, že syntéza řeči probíhá. Tato událost se aktivuje pokaždé, když sada SDK obdrží zvukový blok dat ze služby Speech. Můžete ověřit, kdy probíhá syntéza.
VisemeReceived Signály, že byla přijata událost viseme. Viseme se často používají k reprezentaci klíčových pozic v pozorované řeči. Klíčové pozice zahrnují pozici rtů, jawa a jazyk při výrobě konkrétního fonemu. Pomocí visem můžete animovat tvář znaku při přehrávání hlasového zvuku.
WordBoundary Signály, že byla přijata hranice slova. Tato událost se vyvolá na začátku každého nového mluveného slova, interpunkce a věty. Událost hlásí posun času aktuálního slova od začátku výstupního zvuku. Tato událost také hlásí pozici znaku ve vstupním textu nebo SSML bezprostředně před slovem, které se chystáte vyslovit. Tato událost se běžně používá k získání relativní pozice textu a odpovídajícího zvuku. Možná budete chtít vědět o novém slově a pak provést akci na základě načasování. Můžete například získat informace, které vám pomůžou rozhodnout, kdy a jak dlouho se mají slova zvýrazňovat při mluveném slově.

Poznámka:

Události se aktivují, jakmile budou k dispozici výstupní zvuková data, což je rychlejší než přehrávání do výstupního zařízení. Volající musí odpovídajícím způsobem synchronizovat streamování a v reálném čase.

Tady je příklad, který ukazuje, jak se přihlásit k odběru událostí pro syntézu řeči. Postupujte podle pokynů v rychlém startu, ale obsah tohoto souboru Program.cs nahraďte následujícím kódem jazyka C#:

using Microsoft.CognitiveServices.Speech;

class Program 
{
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    static string speechKey = Environment.GetEnvironmentVariable("SPEECH_KEY");
    static string speechRegion = Environment.GetEnvironmentVariable("SPEECH_REGION");

    async static Task Main(string[] args)
    {
        var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);
         
        var speechSynthesisVoiceName  = "en-US-AvaMultilingualNeural";  
        var ssml = @$"<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
            <voice name='{speechSynthesisVoiceName}'>
                <mstts:viseme type='redlips_front'/>
                The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
            </voice>
        </speak>";

        // Required for sentence-level WordBoundary events
        speechConfig.SetProperty(PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");

        using (var speechSynthesizer = new SpeechSynthesizer(speechConfig))
        {
            // Subscribe to events

            speechSynthesizer.BookmarkReached += (s, e) =>
            {
                Console.WriteLine($"BookmarkReached event:" +
                    $"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
                    $"\r\n\tText: \"{e.Text}\".");
            };

            speechSynthesizer.SynthesisCanceled += (s, e) =>
            {
                Console.WriteLine("SynthesisCanceled event");
            };

            speechSynthesizer.SynthesisCompleted += (s, e) =>
            {                
                Console.WriteLine($"SynthesisCompleted event:" +
                    $"\r\n\tAudioData: {e.Result.AudioData.Length} bytes" +
                    $"\r\n\tAudioDuration: {e.Result.AudioDuration}");
            };

            speechSynthesizer.SynthesisStarted += (s, e) =>
            {
                Console.WriteLine("SynthesisStarted event");
            };

            speechSynthesizer.Synthesizing += (s, e) =>
            {
                Console.WriteLine($"Synthesizing event:" +
                    $"\r\n\tAudioData: {e.Result.AudioData.Length} bytes");
            };

            speechSynthesizer.VisemeReceived += (s, e) =>
            {
                Console.WriteLine($"VisemeReceived event:" +
                    $"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
                    $"\r\n\tVisemeId: {e.VisemeId}");
            };

            speechSynthesizer.WordBoundary += (s, e) =>
            {
                Console.WriteLine($"WordBoundary event:" +
                    // Word, Punctuation, or Sentence
                    $"\r\n\tBoundaryType: {e.BoundaryType}" +
                    $"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
                    $"\r\n\tDuration: {e.Duration}" +
                    $"\r\n\tText: \"{e.Text}\"" +
                    $"\r\n\tTextOffset: {e.TextOffset}" +
                    $"\r\n\tWordLength: {e.WordLength}");
            };

            // Synthesize the SSML
            Console.WriteLine($"SSML to synthesize: \r\n{ssml}");
            var speechSynthesisResult = await speechSynthesizer.SpeakSsmlAsync(ssml);

            // Output the results
            switch (speechSynthesisResult.Reason)
            {
                case ResultReason.SynthesizingAudioCompleted:
                    Console.WriteLine("SynthesizingAudioCompleted result");
                    break;
                case ResultReason.Canceled:
                    var cancellation = SpeechSynthesisCancellationDetails.FromResult(speechSynthesisResult);
                    Console.WriteLine($"CANCELED: Reason={cancellation.Reason}");

                    if (cancellation.Reason == CancellationReason.Error)
                    {
                        Console.WriteLine($"CANCELED: ErrorCode={cancellation.ErrorCode}");
                        Console.WriteLine($"CANCELED: ErrorDetails=[{cancellation.ErrorDetails}]");
                        Console.WriteLine($"CANCELED: Did you set the speech resource key and region values?");
                    }
                    break;
                default:
                    break;
            }
        }

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }
}

Další texty pro ukázky řeči najdete na GitHubu.

Použití vlastního koncového bodu

Vlastní koncový bod je funkčně identický se standardním koncovým bodem používaným pro požadavky na převod textu na řeč.

Jedním z rozdílů je to, že EndpointId je nutné zadat, aby se váš vlastní hlas používal prostřednictvím sady Speech SDK. Můžete začít s textem na řeč rychlý start a pak aktualizovat kód pomocí operátoru EndpointId a SpeechSynthesisVoiceName.

var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);     
speechConfig.SpeechSynthesisVoiceName = "YourCustomVoiceName";
speechConfig.EndpointId = "YourEndpointId";

Pokud chcete použít vlastní hlas prostřednictvím jazyka SSML (Speech Synthesis Markup Language), zadejte název modelu jako hlasový název. Tento příklad používá YourCustomVoiceName hlas.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Spuštění a použití kontejneru

Kontejnery služby Speech poskytují rozhraní API koncových bodů dotazů založených na websocketu, ke kterým se přistupuje prostřednictvím sady Speech SDK a rozhraní příkazového řádku služby Speech. Sada Speech SDK a Rozhraní příkazového řádku služby Speech ve výchozím nastavení používají veřejnou službu Speech. Pokud chcete kontejner použít, musíte změnit inicializační metodu. Místo klíče a oblasti použijte adresu URL hostitele kontejneru.

Další informace o kontejnerech najdete v tématu Instalace a spouštění kontejnerů služby Speech pomocí Dockeru.

Referenční dokumentace | – balíček (NuGet) | Další ukázky na GitHubu

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Výběr jazyka syntézy a hlasu

Funkce převodu textu na řeč ve službě Speech podporuje více než 400 hlasů a více než 140 jazyků a variant. Podívejte se na úplný seznam podporovaných textů na národní prostředí řeči nebo si je vyzkoušejte v Galerii hlasu.

Zadejte jazyk nebo hlas třídy SpeechConfig tak, aby odpovídal vašemu vstupnímu textu, a použijte zadaný hlas. Následující fragment kódu ukazuje, jak tato technika funguje:

void synthesizeSpeech()
{
    auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
    // Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
    speechConfig->SetSpeechSynthesisLanguage("en-US"); 
    speechConfig->SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
}

Všechny neurální hlasy jsou vícejazyčné a fluentní ve svém vlastním jazyce a angličtině. Pokud je například vstupní text v angličtině", "Jsem nadšený z pokusu o převod textu na řeč", a vyberete es-ES-ElviraNeural, text se mluví v angličtině se španělským zvýrazněním.

Pokud hlas nemluví jazykem vstupního textu, služba Speech nevytváří syntetizovaný zvuk. Úplný seznam podporovaných neurálních hlasů najdete v tématu Podpora jazyka a hlasu pro službu Speech.

Poznámka:

Výchozí hlas je první hlas vrácený pro každé národní prostředí z rozhraní API seznamu hlasu.

Hlas, který mluví, je určen v pořadí podle priority následujícím způsobem:

  • Pokud ho nenastavíte SpeechSynthesisVoiceName nebo SpeechSynthesisLanguage, výchozí hlas pro en-US mluvený hlas.
  • Pokud nastavíte SpeechSynthesisLanguagepouze , výchozí hlas pro zadané národní prostředí mluví.
  • Pokud jsou obě SpeechSynthesisVoiceName i SpeechSynthesisLanguage nastavené, SpeechSynthesisLanguage nastavení se ignoruje. Hlas, který určíte pomocí SpeechSynthesisVoiceName mluvených mluvčích.
  • Pokud je hlasový prvek nastaven pomocí jazyka SSML (Speech Synthesis Markup Language), budou ignorovány SpeechSynthesisVoiceName a SpeechSynthesisLanguage nastavení.

Syntetizace řeči do souboru

Vytvořte objekt SpeechSynthesizer . Tento objekt zobrazený v následujících fragmentech kódu spouští převody řeči a výstupy do mluvčích, souborů nebo jiných výstupních datových proudů. SpeechSynthesizer přijímá jako parametry:

  • Objekt SpeechConfig , který jste vytvořili v předchozím kroku.
  • Objekt AudioConfig , který určuje, jak se mají zpracovat výstupní výsledky.
  1. AudioConfig Vytvořte instanci, která automaticky zapíše výstup do souboru .wav pomocí FromWavFileOutput() funkce:

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
    }
    
  2. SpeechSynthesizer Vytvoření instance Předejte objekt speechConfig a audioConfig objekt jako parametry. Pokud chcete syntetizovat řeč a zapisovat do souboru, spusťte SpeakTextAsync() řetězec textu.

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
        auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig, audioConfig);
        auto result = speechSynthesizer->SpeakTextAsync("A simple test to write to a file.").get();
    }
    

Když program spustíte, vytvoří syntetizovaný .wav soubor, který se zapíše do zadaného umístění. Tento výsledek je dobrým příkladem nejzákladnějšího použití. Dále můžete přizpůsobit výstup a zpracovat výstupní odpověď jako datový proud v paměti pro práci s vlastními scénáři.

Syntetizování výstupu reproduktoru

Pokud chcete výstupem syntetizované řeči do aktuálního aktivního výstupního zařízení, jako je například reproduktor, při vytváření SpeechSynthesizer instance parametr vynecháteAudioConfig. Tady je příklad:

void synthesizeSpeech()
{
    auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
    auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
    auto result = speechSynthesizer->SpeakTextAsync("I'm excited to try text to speech").get();
}

Získání výsledku jako datového proudu v paměti

Výsledná zvuková data můžete použít jako datový proud v paměti místo přímého zápisu do souboru. Pomocí datového proudu v paměti můžete vytvářet vlastní chování:

  • Abstrahujte výsledné bajtové pole jako vyhledatelný datový proud pro vlastní podřízené služby.
  • Integrujte výsledek s jinými rozhraními API nebo službami.
  • Upravte zvuková data, zapište vlastní záhlaví .wav a proveďte související úlohy.

Tuto změnu můžete provést v předchozím příkladu. Nejprve blok odeberte, protože chování výstupu AudioConfig spravujete ručně od tohoto okamžiku, aby se zvýšila kontrola. AudioConfig Předejte NULL konstruktoruSpeechSynthesizer.

Poznámka:

AudioConfigKdyž ho předáte NULL , místo abyste ho vynechali jako v předchozím příkladu výstupu reproduktoru, ve výchozím nastavení se na aktuálním aktivním výstupním zařízení nepřehraje zvuk.

Uložte výsledek do proměnné SpeechSynthesisResult . Getter GetAudioData vrátí byte [] instanci pro výstupní data. S touto byte [] instancí můžete pracovat ručně nebo můžete ke správě datového proudu v paměti použít třídu AudioDataStream .

V tomto příkladu AudioDataStream.FromResult() použijte statickou funkci k získání datového proudu z výsledku:

void synthesizeSpeech()
{
    auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
    auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);

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

V tomto okamžiku můžete implementovat jakékoli vlastní chování pomocí výsledného stream objektu.

Přizpůsobení formátu zvuku

Můžete přizpůsobit atributy zvukového výstupu, včetně:

  • Typ zvukového souboru
  • Vzorkovací frekvence
  • Hloubka bitu

Pokud chcete změnit formát zvuku SetSpeechSynthesisOutputFormat() , použijte funkci objektu SpeechConfig . Tato funkce očekává enum instanci typu SpeechSynthesisOutputFormat. Pomocí příkazu enum vyberte výstupní formát. Dostupné formáty najdete v seznamu zvukových formátů.

Existují různé možnosti pro různé typy souborů v závislosti na vašich požadavcích. Podle definice nezpracované formáty, jako Raw24Khz16BitMonoPcm například neobsahují záhlaví zvuku. V jedné z těchto situací používejte nezpracované formáty:

  • Víte, že vaše podřízená implementace může dekódovat nezpracovaný bitstream.
  • Plánujete ručně vytvářet hlavičky na základě faktorů, jako je hloubka bitu, vzorkovací frekvence a počet kanálů.

Tento příklad určuje formát Riff24Khz16BitMonoPcm RIFF s vysokou věrností nastavením SpeechSynthesisOutputFormat objektu SpeechConfig . Podobně jako v příkladu v předchozí části AudioDataStream získáte datový proud v paměti výsledku a pak ho zapíšete do souboru.

void synthesizeSpeech()
{
    auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
    speechConfig->SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat::Riff24Khz16BitMonoPcm);

    auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
    auto result = speechSynthesizer->SpeakTextAsync("A simple test to write to a file.").get();

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

Když program spustíte, zapíše .wav soubor do zadané cesty.

Přizpůsobení charakteristik řeči pomocí SSML

SSML můžete použít k vyladění tónu, výslovnosti, míry mluvení, hlasitosti a dalších aspektů v textu na výstup řeči odesláním požadavků ze schématu XML. Tato část ukazuje příklad změny hlasu. Další informace naleznete v tématu Přehled jazyka Speech Synthesis Markup Language.

Pokud chcete začít používat SSML k přizpůsobení, proveďte menší změnu, která přepne hlas.

  1. Vytvořte nový soubor XML pro konfiguraci SSML v kořenovém adresáři projektu.

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

    V tomto příkladu je soubor ssml.xml. Kořenový prvek je vždy <speak>. Obtékání textu do elementu <voice> umožňuje změnit hlas pomocí parametru name . Úplný seznam podporovaných neurálních hlasů najdete v tématu Podporované jazyky.

  2. Změňte požadavek na syntézu řeči tak, aby odkaz na váš soubor XML. Požadavek je většinou stejný. Místo použití SpeakTextAsync() funkce použijete SpeakSsmlAsync(). Tato funkce očekává řetězec XML. Nejprve načtěte konfiguraci SSML jako řetězec. Z tohoto okamžiku je výsledný objekt přesně stejný jako předchozí příklady.

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
    
        std::ifstream file("./ssml.xml");
        std::string ssml, line;
        while (std::getline(file, line))
        {
            ssml += line;
            ssml.push_back('\n');
        }
        auto result = speechSynthesizer->SpeakSsmlAsync(ssml).get();
    
        auto stream = AudioDataStream::FromResult(result);
        stream->SaveToWavFileAsync("path/to/write/file.wav").get();
    }
    

Poznámka:

Pokud chcete změnit hlas bez použití SSML, můžete vlastnost SpeechConfig nastavit pomocí .SpeechConfig.SetSpeechSynthesisVoiceName("en-US-AndrewMultilingualNeural")

Přihlášení k odběru událostí syntetizátoru

Možná budete chtít získat další přehledy o zpracování textu a výsledcích řeči. Můžete například chtít vědět, kdy syntetizátor začíná a zastavuje, nebo můžete chtít vědět o jiných událostech, ke kterým došlo během syntézy.

Při použití speechSynthesizer pro převod textu na řeč můžete přihlásit k odběru událostí v této tabulce:

Událost Popis Případ použití
BookmarkReached Signály, že byla dosažena záložka. K aktivaci události bookmark dosažení záložky se v SSML vyžaduje prvek. Tato událost hlásí uplynulý čas výstupu zvuku mezi začátkem syntézy a prvkem bookmark . Vlastnost události Text je řetězcová hodnota, kterou jste nastavili v atributu záložky mark . Prvky bookmark nejsou mluvené. Pomocí elementu bookmark můžete vložit vlastní značky do SSML, abyste získali posun každé značky ve zvukovém streamu. Tento bookmark prvek lze použít k odkazování na konkrétní umístění v textu nebo sekvenci značek.
SynthesisCanceled Signály, že syntéza řeči byla zrušena. Můžete ověřit, kdy je syntéza zrušena.
SynthesisCompleted Signály, že syntéza řeči je kompletní. Po dokončení syntézy můžete potvrdit.
SynthesisStarted Signály, které syntéza řeči začala. Po spuštění syntézy můžete potvrdit.
Synthesizing Signály, že syntéza řeči probíhá. Tato událost se aktivuje pokaždé, když sada SDK obdrží zvukový blok dat ze služby Speech. Můžete ověřit, kdy probíhá syntéza.
VisemeReceived Signály, že byla přijata událost viseme. Viseme se často používají k reprezentaci klíčových pozic v pozorované řeči. Klíčové pozice zahrnují pozici rtů, jawa a jazyk při výrobě konkrétního fonemu. Pomocí visem můžete animovat tvář znaku při přehrávání hlasového zvuku.
WordBoundary Signály, že byla přijata hranice slova. Tato událost se vyvolá na začátku každého nového mluveného slova, interpunkce a věty. Událost hlásí posun času aktuálního slova od začátku výstupního zvuku. Tato událost také hlásí pozici znaku ve vstupním textu nebo SSML bezprostředně před slovem, které se chystáte vyslovit. Tato událost se běžně používá k získání relativní pozice textu a odpovídajícího zvuku. Možná budete chtít vědět o novém slově a pak provést akci na základě načasování. Můžete například získat informace, které vám pomůžou rozhodnout, kdy a jak dlouho se mají slova zvýrazňovat při mluveném slově.

Poznámka:

Události se aktivují, jakmile budou k dispozici výstupní zvuková data, což je rychlejší než přehrávání do výstupního zařízení. Volající musí odpovídajícím způsobem synchronizovat streamování a v reálném čase.

Tady je příklad, který ukazuje, jak se přihlásit k odběru událostí pro syntézu řeči. Můžete postupovat podle pokynů v rychlém startu, ale nahradit obsah tohoto souboru main.cpp následujícím kódem:

#include <iostream> 
#include <stdlib.h>
#include <speechapi_cxx.h>

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

std::string getEnvironmentVariable(const char* name);

int main()
{
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    auto speechKey = getEnvironmentVariable("SPEECH_KEY");
    auto speechRegion = getEnvironmentVariable("SPEECH_REGION");

    if ((size(speechKey) == 0) || (size(speechRegion) == 0)) {
        std::cout << "Please set both SPEECH_KEY and SPEECH_REGION environment variables." << std::endl;
        return -1;
    }

    auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);

    // Required for WordBoundary event sentences.
    speechConfig->SetProperty(PropertyId::SpeechServiceResponse_RequestSentenceBoundary, "true");

    const auto ssml = R"(<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
        <voice name = 'en-US-AvaMultilingualNeural'>
            <mstts:viseme type = 'redlips_front' />
            The rainbow has seven colors : <bookmark mark = 'colors_list_begin' />Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark = 'colors_list_end' />.
        </voice>
        </speak>)";

    auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);

    // Subscribe to events

    speechSynthesizer->BookmarkReached += [](const SpeechSynthesisBookmarkEventArgs& e)
    {
        std::cout << "Bookmark reached. "
            << "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
            << "\r\n\tText: " << e.Text << std::endl;
    };

    speechSynthesizer->SynthesisCanceled += [](const SpeechSynthesisEventArgs& e)
    {
        std::cout << "SynthesisCanceled event" << std::endl;
    };

    speechSynthesizer->SynthesisCompleted += [](const SpeechSynthesisEventArgs& e)
    {
        auto audioDuration = std::chrono::duration_cast<std::chrono::milliseconds>(e.Result->AudioDuration).count();

        std::cout << "SynthesisCompleted event:"
            << "\r\n\tAudioData: " << e.Result->GetAudioData()->size() << "bytes"
            << "\r\n\tAudioDuration: " << audioDuration << std::endl;
    };

    speechSynthesizer->SynthesisStarted += [](const SpeechSynthesisEventArgs& e)
    {
        std::cout << "SynthesisStarted event" << std::endl;
    };

    speechSynthesizer->Synthesizing += [](const SpeechSynthesisEventArgs& e)
    {
        std::cout << "Synthesizing event:"
            << "\r\n\tAudioData: " << e.Result->GetAudioData()->size() << "bytes" << std::endl;
    };

    speechSynthesizer->VisemeReceived += [](const SpeechSynthesisVisemeEventArgs& e)
    {
        std::cout << "VisemeReceived event:"
            << "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
            << "\r\n\tVisemeId: " << e.VisemeId << std::endl;
    };

    speechSynthesizer->WordBoundary += [](const SpeechSynthesisWordBoundaryEventArgs& e)
    {
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(e.Duration).count();
        
        auto boundaryType = "";
        switch (e.BoundaryType) {
        case SpeechSynthesisBoundaryType::Punctuation:
            boundaryType = "Punctuation";
            break;
        case SpeechSynthesisBoundaryType::Sentence:
            boundaryType = "Sentence";
            break;
        case SpeechSynthesisBoundaryType::Word:
            boundaryType = "Word";
            break;
        }

        std::cout << "WordBoundary event:"
            // Word, Punctuation, or Sentence
            << "\r\n\tBoundaryType: " << boundaryType
            << "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
            << "\r\n\tDuration: " << duration
            << "\r\n\tText: \"" << e.Text << "\""
            << "\r\n\tTextOffset: " << e.TextOffset
            << "\r\n\tWordLength: " << e.WordLength << std::endl;
    };

    auto result = speechSynthesizer->SpeakSsmlAsync(ssml).get();

    // Checks result.
    if (result->Reason == ResultReason::SynthesizingAudioCompleted)
    {
        std::cout << "SynthesizingAudioCompleted result" << std::endl;
    }
    else if (result->Reason == ResultReason::Canceled)
    {
        auto cancellation = SpeechSynthesisCancellationDetails::FromResult(result);
        std::cout << "CANCELED: Reason=" << (int)cancellation->Reason << std::endl;

        if (cancellation->Reason == CancellationReason::Error)
        {
            std::cout << "CANCELED: ErrorCode=" << (int)cancellation->ErrorCode << std::endl;
            std::cout << "CANCELED: ErrorDetails=[" << cancellation->ErrorDetails << "]" << std::endl;
            std::cout << "CANCELED: Did you set the speech resource key and region values?" << std::endl;
        }
    }

    std::cout << "Press enter to exit..." << std::endl;
    std::cin.get();
}

std::string getEnvironmentVariable(const char* name)
{
#if defined(_MSC_VER)
    size_t requiredSize = 0;
    (void)getenv_s(&requiredSize, nullptr, 0, name);
    if (requiredSize == 0)
    {
        return "";
    }
    auto buffer = std::make_unique<char[]>(requiredSize);
    (void)getenv_s(&requiredSize, buffer.get(), requiredSize, name);
    return buffer.get();
#else
    auto value = getenv(name);
    return value ? value : "";
#endif
}

Další texty pro ukázky řeči najdete na GitHubu.

Použití vlastního koncového bodu

Vlastní koncový bod je funkčně identický se standardním koncovým bodem, který se používá k převodu textu na požadavky na řeč.

Jedním z rozdílů je to, že EndpointId je nutné zadat, aby se váš vlastní hlas používal prostřednictvím sady Speech SDK. Můžete začít s textem na řeč rychlý start a pak aktualizovat kód pomocí operátoru EndpointId a SpeechSynthesisVoiceName.

auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);
speechConfig->SetSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig->SetEndpointId("YourEndpointId");

Pokud chcete použít vlastní hlas prostřednictvím jazyka SSML (Speech Synthesis Markup Language), zadejte název modelu jako hlasový název. Tento příklad používá YourCustomVoiceName hlas.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Spuštění a použití kontejneru

Kontejnery služby Speech poskytují rozhraní API koncových bodů dotazů založených na websocketu, ke kterým se přistupuje prostřednictvím sady Speech SDK a rozhraní příkazového řádku služby Speech. Sada Speech SDK a Rozhraní příkazového řádku služby Speech ve výchozím nastavení používají veřejnou službu Speech. Pokud chcete kontejner použít, musíte změnit inicializační metodu. Místo klíče a oblasti použijte adresu URL hostitele kontejneru.

Další informace o kontejnerech najdete v tématu Instalace a spouštění kontejnerů služby Speech pomocí Dockeru.

Referenční dokumentace | – balíček (Go) | Další ukázky na GitHubu

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Požadavky

Instalace sady Speech SDK

Než budete moct cokoli udělat, musíte nainstalovat sadu Speech SDK pro Go.

Převod textu na řeč mluvčího

Pomocí následující ukázky kódu spusťte syntézu řeči na výchozí výstupní zvukové zařízení. Nahraďte proměnné subscription a region klíčem řeči a umístěním a oblastí. Spuštěním skriptu vyslovíte svůj vstupní text s výchozím mluvčím.

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 := "YourSpeechKey"
    region := "YourSpeechRegion"

    audioConfig, err := audio.NewAudioConfigFromDefaultSpeakerOutput()
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer audioConfig.Close()
    speechConfig, err := speech.NewSpeechConfigFromSubscription(subscription, region)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechConfig.Close()
    speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, 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 set the speech resource key and region values?\n",
                    cancellation.ErrorCode,
                    cancellation.ErrorDetails)
            }
        }
    }
}

Spuštěním následujících příkazů vytvořte soubor go.mod , který odkazuje na komponenty hostované na GitHubu:

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

Teď sestavte a spusťte kód:

go build
go run quickstart

Podrobné informace o třídách najdete v SpeechConfig dokumentaci a SpeechSynthesizer referenční dokumentaci.

Převod textu na řeč na datový proud v paměti

Výsledná zvuková data můžete použít jako datový proud v paměti místo přímého zápisu do souboru. Pomocí datového proudu v paměti můžete vytvářet vlastní chování:

  • Abstrahujte výsledné bajtové pole jako vyhledatelný datový proud pro vlastní podřízené služby.
  • Integrujte výsledek s jinými rozhraními API nebo službami.
  • Upravte zvuková data, zapište vlastní záhlaví .wav a proveďte související úlohy.

Tuto změnu můžete provést v předchozím příkladu. Odeberte blok, protože chování výstupu AudioConfig spravujete ručně od tohoto okamžiku, abyste zvýšili kontrolu. Pak předejte nilAudioConfig konstruktoru SpeechSynthesizer .

Poznámka:

AudioConfigKdyž ho předáte nil , místo abyste ho vynechali jako v předchozím příkladu výstupu reproduktoru, ve výchozím nastavení se na aktuálním aktivním výstupním zařízení nepřehraje zvuk.

Uložte výsledek do SpeechSynthesisResult proměnné. Vlastnost AudioData vrátí []byte instanci pro výstupní data. S touto []byte instancí můžete pracovat ručně nebo můžete použít AudioDataStream třídu ke správě datového proudu v paměti. V tomto příkladu NewAudioDataStreamFromSpeechSynthesisResult() použijete statickou funkci k získání datového proudu z výsledku.

Nahraďte proměnné subscription a region klíčem řeči a umístěním a oblastí:

package main

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

    "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 := "YourSpeechKey"
    region := "YourSpeechRegion"

    speechConfig, err := speech.NewSpeechConfigFromSubscription(subscription, region)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechConfig.Close()
    speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, 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 cases, 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))
    }
}

Spuštěním následujících příkazů vytvořte soubor go.mod , který odkazuje na komponenty hostované na GitHubu:

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

Teď sestavte a spusťte kód:

go build
go run quickstart

Podrobné informace o třídách najdete v SpeechConfig dokumentaci a SpeechSynthesizer referenční dokumentaci.

Výběr jazyka syntézy a hlasu

Funkce převodu textu na řeč ve službě Speech podporuje více než 400 hlasů a více než 140 jazyků a variant. Můžete získat úplný seznam nebo je vyzkoušet v Galerii hlasu.

Zadejte jazyk nebo hlas, který odpovídá vašemu vstupnímu SpeechConfig textu, a použijte zadaný hlas:

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

speechConfig.SetSpeechSynthesisLanguage("en-US")
speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural")

Všechny neurální hlasy jsou vícejazyčné a fluentní ve svém vlastním jazyce a angličtině. Pokud je například vstupní text v angličtině", "Jsem nadšený z pokusu o převod textu na řeč", a vyberete es-ES-ElviraNeural, text se mluví v angličtině se španělským zvýrazněním.

Pokud hlas nemluví jazykem vstupního textu, služba Speech nevytváří syntetizovaný zvuk. Úplný seznam podporovaných neurálních hlasů najdete v tématu Podpora jazyka a hlasu pro službu Speech.

Poznámka:

Výchozí hlas je první hlas vrácený pro každé národní prostředí z rozhraní API seznamu hlasu.

Hlas, který mluví, je určen v pořadí podle priority následujícím způsobem:

  • Pokud ho nenastavíte SpeechSynthesisVoiceName nebo SpeechSynthesisLanguage, výchozí hlas pro en-US mluvený hlas.
  • Pokud nastavíte SpeechSynthesisLanguagepouze , výchozí hlas pro zadané národní prostředí mluví.
  • Pokud jsou obě SpeechSynthesisVoiceName i SpeechSynthesisLanguage nastavené, SpeechSynthesisLanguage nastavení se ignoruje. Hlas, který určíte pomocí SpeechSynthesisVoiceName mluvených mluvčích.
  • Pokud je hlasový prvek nastaven pomocí jazyka SSML (Speech Synthesis Markup Language), budou ignorovány SpeechSynthesisVoiceName a SpeechSynthesisLanguage nastavení.

Přizpůsobení charakteristik řeči pomocí SSML

Pomocí jazyka SSML (Speech Synthesis Markup Language) můžete doladit tón, výslovnost, rychlost mluvení, hlasitost a další informace v textu na výstup řeči odesláním požadavků ze schématu XML. Tato část ukazuje příklad změny hlasu. Další informace naleznete v tématu Přehled jazyka Speech Synthesis Markup Language.

Pokud chcete začít používat SSML k přizpůsobení, provedete menší změnu, která přepne hlas.

Nejprve vytvořte nový soubor XML pro konfiguraci SSML v kořenovém adresáři projektu. V tomto příkladu je ssml.xmlto . Kořenový prvek je vždy <speak>. Obtékání textu do elementu <voice> umožňuje změnit hlas pomocí parametru name . Úplný seznam podporovaných neurálních hlasů najdete v tématu Podporované jazyky.

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

Dále je potřeba změnit požadavek syntézy řeči tak, aby odkaz na váš soubor XML. Požadavek je většinou stejný, ale místo použití SpeakTextAsync() funkce použijete SpeakSsmlAsync(). Tato funkce očekává řetězec XML, takže nejprve načtete konfiguraci SSML jako řetězec. Z tohoto okamžiku je výsledný objekt přesně stejný jako předchozí příklady.

Poznámka:

Pokud chcete nastavit hlas bez použití SSML, můžete vlastnost SpeechConfig nastavit pomocí .speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural")

Přihlášení k odběru událostí syntetizátoru

Možná budete chtít získat další přehledy o zpracování textu a výsledcích řeči. Můžete například chtít vědět, kdy syntetizátor začíná a zastavuje, nebo můžete chtít vědět o jiných událostech, ke kterým došlo během syntézy.

Při použití speechSynthesizer pro převod textu na řeč můžete přihlásit k odběru událostí v této tabulce:

Událost Popis Případ použití
BookmarkReached Signály, že byla dosažena záložka. K aktivaci události bookmark dosažení záložky se v SSML vyžaduje prvek. Tato událost hlásí uplynulý čas výstupu zvuku mezi začátkem syntézy a prvkem bookmark . Vlastnost události Text je řetězcová hodnota, kterou jste nastavili v atributu záložky mark . Prvky bookmark nejsou mluvené. Pomocí elementu bookmark můžete vložit vlastní značky do SSML, abyste získali posun každé značky ve zvukovém streamu. Tento bookmark prvek lze použít k odkazování na konkrétní umístění v textu nebo sekvenci značek.
SynthesisCanceled Signály, že syntéza řeči byla zrušena. Můžete ověřit, kdy je syntéza zrušena.
SynthesisCompleted Signály, že syntéza řeči je kompletní. Po dokončení syntézy můžete potvrdit.
SynthesisStarted Signály, které syntéza řeči začala. Po spuštění syntézy můžete potvrdit.
Synthesizing Signály, že syntéza řeči probíhá. Tato událost se aktivuje pokaždé, když sada SDK obdrží zvukový blok dat ze služby Speech. Můžete ověřit, kdy probíhá syntéza.
VisemeReceived Signály, že byla přijata událost viseme. Viseme se často používají k reprezentaci klíčových pozic v pozorované řeči. Klíčové pozice zahrnují pozici rtů, jawa a jazyk při výrobě konkrétního fonemu. Pomocí visem můžete animovat tvář znaku při přehrávání hlasového zvuku.
WordBoundary Signály, že byla přijata hranice slova. Tato událost se vyvolá na začátku každého nového mluveného slova, interpunkce a věty. Událost hlásí posun času aktuálního slova od začátku výstupního zvuku. Tato událost také hlásí pozici znaku ve vstupním textu nebo SSML bezprostředně před slovem, které se chystáte vyslovit. Tato událost se běžně používá k získání relativní pozice textu a odpovídajícího zvuku. Možná budete chtít vědět o novém slově a pak provést akci na základě načasování. Můžete například získat informace, které vám pomůžou rozhodnout, kdy a jak dlouho se mají slova zvýrazňovat při mluveném slově.

Poznámka:

Události se aktivují, jakmile budou k dispozici výstupní zvuková data, což je rychlejší než přehrávání do výstupního zařízení. Volající musí odpovídajícím způsobem synchronizovat streamování a v reálném čase.

Tady je příklad, který ukazuje, jak se přihlásit k odběru událostí pro syntézu řeči. Můžete postupovat podle pokynů v rychlém startu, ale nahradit obsah tohoto speech-synthesis.go souboru následujícím kódem Go:

package main

import (
    "fmt"
    "os"
    "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 bookmarkReachedHandler(event speech.SpeechSynthesisBookmarkEventArgs) {
    defer event.Close()
    fmt.Println("BookmarkReached event")
}

func synthesisCanceledHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("SynthesisCanceled event")
}

func synthesisCompletedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("SynthesisCompleted event")
    fmt.Printf("\tAudioData: %d bytes\n", len(event.Result.AudioData))
    fmt.Printf("\tAudioDuration: %d\n", event.Result.AudioDuration)
}

func synthesisStartedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("SynthesisStarted event")
}

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

func visemeReceivedHandler(event speech.SpeechSynthesisVisemeEventArgs) {
    defer event.Close()
    fmt.Println("VisemeReceived event")
    fmt.Printf("\tAudioOffset: %dms\n", (event.AudioOffset+5000)/10000)
    fmt.Printf("\tVisemeID %d\n", event.VisemeID)
}

func wordBoundaryHandler(event speech.SpeechSynthesisWordBoundaryEventArgs) {
    defer event.Close()
    boundaryType := ""
    switch event.BoundaryType {
    case 0:
        boundaryType = "Word"
    case 1:
        boundaryType = "Punctuation"
    case 2:
        boundaryType = "Sentence"
    }
    fmt.Println("WordBoundary event")
    fmt.Printf("\tBoundaryType %v\n", boundaryType)
    fmt.Printf("\tAudioOffset: %dms\n", (event.AudioOffset+5000)/10000)
    fmt.Printf("\tDuration %d\n", event.Duration)
    fmt.Printf("\tText %s\n", event.Text)
    fmt.Printf("\tTextOffset %d\n", event.TextOffset)
    fmt.Printf("\tWordLength %d\n", event.WordLength)
}

func main() {
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    speechKey := os.Getenv("SPEECH_KEY")
    speechRegion := os.Getenv("SPEECH_REGION")

    audioConfig, err := audio.NewAudioConfigFromDefaultSpeakerOutput()
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer audioConfig.Close()
    speechConfig, err := speech.NewSpeechConfigFromSubscription(speechKey, speechRegion)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechConfig.Close()

    // Required for WordBoundary event sentences.
    speechConfig.SetProperty(common.SpeechServiceResponseRequestSentenceBoundary, "true")

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

    speechSynthesizer.BookmarkReached(bookmarkReachedHandler)
    speechSynthesizer.SynthesisCanceled(synthesisCanceledHandler)
    speechSynthesizer.SynthesisCompleted(synthesisCompletedHandler)
    speechSynthesizer.SynthesisStarted(synthesisStartedHandler)
    speechSynthesizer.Synthesizing(synthesizingHandler)
    speechSynthesizer.VisemeReceived(visemeReceivedHandler)
    speechSynthesizer.WordBoundary(wordBoundaryHandler)

    speechSynthesisVoiceName := "en-US-AvaMultilingualNeural"

    ssml := fmt.Sprintf(`<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
            <voice name='%s'>
                <mstts:viseme type='redlips_front'/>
                The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
            </voice>
        </speak>`, speechSynthesisVoiceName)

    // Synthesize the SSML
    fmt.Printf("SSML to synthesize: \n\t%s\n", ssml)
    task := speechSynthesizer.SpeakSsmlAsync(ssml)

    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.Println("SynthesizingAudioCompleted result")
    } 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 set the speech resource key and region values?\n",
                cancellation.ErrorCode,
                cancellation.ErrorDetails)
        }
    }
}

Další texty pro ukázky řeči najdete na GitHubu.

Spuštění a použití kontejneru

Kontejnery služby Speech poskytují rozhraní API koncových bodů dotazů založených na websocketu, ke kterým se přistupuje prostřednictvím sady Speech SDK a rozhraní příkazového řádku služby Speech. Sada Speech SDK a Rozhraní příkazového řádku služby Speech ve výchozím nastavení používají veřejnou službu Speech. Pokud chcete kontejner použít, musíte změnit inicializační metodu. Místo klíče a oblasti použijte adresu URL hostitele kontejneru.

Další informace o kontejnerech najdete v tématu Instalace a spouštění kontejnerů služby Speech pomocí Dockeru.

Referenční dokumentace | Další ukázky na GitHubu

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Výběr jazyka syntézy a hlasu

Funkce převodu textu na řeč ve službě Speech podporuje více než 400 hlasů a více než 140 jazyků a variant. Můžete získat úplný seznam nebo je vyzkoušet v Galerii hlasu.

Zadejte jazyk nebo hlas služby SpeechConfig tak, aby odpovídal vašemu vstupnímu textu, a použijte zadaný hlas. Následující fragment kódu ukazuje, jak tato technika funguje:

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    // Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
    speechConfig.setSpeechSynthesisLanguage("en-US"); 
    speechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
}

Všechny neurální hlasy jsou vícejazyčné a fluentní ve svém vlastním jazyce a angličtině. Pokud je například vstupní text v angličtině", "Jsem nadšený z pokusu o převod textu na řeč", a vyberete es-ES-ElviraNeural, text se mluví v angličtině se španělským zvýrazněním.

Pokud hlas nemluví jazykem vstupního textu, služba Speech nevytváří syntetizovaný zvuk. Úplný seznam podporovaných neurálních hlasů najdete v tématu Podpora jazyka a hlasu pro službu Speech.

Poznámka:

Výchozí hlas je první hlas vrácený pro každé národní prostředí z rozhraní API seznamu hlasu.

Hlas, který mluví, je určen v pořadí podle priority následujícím způsobem:

  • Pokud ho nenastavíte SpeechSynthesisVoiceName nebo SpeechSynthesisLanguage, výchozí hlas pro en-US mluvený hlas.
  • Pokud nastavíte SpeechSynthesisLanguagepouze , výchozí hlas pro zadané národní prostředí mluví.
  • Pokud jsou obě SpeechSynthesisVoiceName i SpeechSynthesisLanguage nastavené, SpeechSynthesisLanguage nastavení se ignoruje. Hlas, který jste zadali pomocí SpeechSynthesisVoiceName mluvených řečí.
  • Pokud je hlasový prvek nastaven pomocí jazyka SSML (Speech Synthesis Markup Language), budou ignorovány SpeechSynthesisVoiceName a SpeechSynthesisLanguage nastavení.

Syntetizace řeči do souboru

Vytvoření objektu SpeechSynthesizer Tento objekt spouští převody řeči a výstupy do mluvčích, souborů nebo jiných výstupních datových proudů. SpeechSynthesizer přijímá jako parametry:

  • Objekt SpeechConfig , který jste vytvořili v předchozím kroku.
  • Objekt AudioConfig , který určuje, jak se mají zpracovat výstupní výsledky.
  1. AudioConfig Vytvořte instanci, která automaticky zapíše výstup do souboru .wav pomocí fromWavFileOutput() statické funkce:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    }
    
  2. SpeechSynthesizer Vytvoření instance Předejte objekt speechConfig a audioConfig objekt jako parametry. Pokud chcete syntetizovat řeč a zapisovat do souboru, spusťte SpeakText() řetězec textu.

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    
        SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
        speechSynthesizer.SpeakText("I'm excited to try text to speech");
    }
    

Když program spustíte, vytvoří syntetizovaný .wav soubor, který se zapíše do zadaného umístění. Tento výsledek je dobrým příkladem nejzákladnějšího použití. Dále můžete přizpůsobit výstup a zpracovat výstupní odpověď jako datový proud v paměti pro práci s vlastními scénáři.

Syntetizování výstupu reproduktoru

Možná budete chtít získat další přehledy o zpracování textu a výsledcích řeči. Můžete například chtít vědět, kdy syntetizátor začíná a zastavuje, nebo můžete chtít vědět o jiných událostech, ke kterým došlo během syntézy.

K výstupu syntetizované řeči do aktuálního aktivního výstupního zařízení, jako je například reproduktor, vytvořte instanci AudioConfig pomocí fromDefaultSpeakerOutput() statické funkce. Tady je příklad:

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    AudioConfig audioConfig = AudioConfig.fromDefaultSpeakerOutput();

    SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    speechSynthesizer.SpeakText("I'm excited to try text to speech");
}

Získání výsledku jako datového proudu v paměti

Výsledná zvuková data můžete použít jako datový proud v paměti místo přímého zápisu do souboru. Pomocí datového proudu v paměti můžete vytvářet vlastní chování:

  • Abstrahujte výsledné bajtové pole jako vyhledatelný datový proud pro vlastní podřízené služby.
  • Integrujte výsledek s jinými rozhraními API nebo službami.
  • Upravte zvuková data, zapište vlastní záhlaví .wav a proveďte související úlohy.

Tuto změnu můžete provést v předchozím příkladu. Nejprve blok odeberte, protože chování výstupu AudioConfig spravujete ručně od tohoto okamžiku, aby se zvýšila kontrola. Pak předejte nullAudioConfig konstruktoru SpeechSynthesizer .

Poznámka:

AudioConfigKdyž ho předáte null , místo abyste ho vynechali jako v předchozím příkladu výstupu reproduktoru, ve výchozím nastavení se na aktuálním aktivním výstupním zařízení nepřehraje zvuk.

Uložte výsledek do SpeechSynthesisResult proměnné. Funkce SpeechSynthesisResult.getAudioData() vrátí byte [] instanci výstupních dat. S touto byte [] instancí můžete pracovat ručně nebo můžete použít AudioDataStream třídu ke správě datového proudu v paměti.

V tomto příkladu AudioDataStream.fromResult() použijte statickou funkci k získání datového proudu z výsledku:

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);

    SpeechSynthesisResult result = speechSynthesizer.SpeakText("I'm excited to try text to speech");
    AudioDataStream stream = AudioDataStream.fromResult(result);
    System.out.print(stream.getStatus());
}

V tomto okamžiku můžete implementovat jakékoli vlastní chování pomocí výsledného stream objektu.

Přizpůsobení formátu zvuku

Můžete přizpůsobit atributy zvukového výstupu, včetně:

  • Typ zvukového souboru
  • Vzorkovací frekvence
  • Hloubka bitu

Pokud chcete změnit formát zvuku setSpeechSynthesisOutputFormat() , použijte funkci na objektu SpeechConfig . Tato funkce očekává enum instanci typu SpeechSynthesisOutputFormat. Pomocí příkazu enum vyberte výstupní formát. Dostupné formáty najdete v seznamu zvukových formátů.

Existují různé možnosti pro různé typy souborů v závislosti na vašich požadavcích. Podle definice nezpracované formáty, jako Raw24Khz16BitMonoPcm například neobsahují záhlaví zvuku. V jedné z těchto situací používejte nezpracované formáty:

  • Víte, že vaše podřízená implementace může dekódovat nezpracovaný bitstream.
  • Plánujete ručně vytvářet hlavičky na základě faktorů, jako je hloubka bitu, vzorkovací frekvence a počet kanálů.

Tento příklad určuje formát Riff24Khz16BitMonoPcm RIFF s vysokou věrností nastavením SpeechSynthesisOutputFormat objektu SpeechConfig . Podobně jako v příkladu v předchozí části AudioDataStream získáte datový proud v paměti výsledku a pak ho zapíšete do souboru.

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");

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

    SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
    SpeechSynthesisResult result = speechSynthesizer.SpeakText("I'm excited to try text to speech");
    AudioDataStream stream = AudioDataStream.fromResult(result);
    stream.saveToWavFile("path/to/write/file.wav");
}

Když program spustíte, zapíše .wav soubor do zadané cesty.

Přizpůsobení charakteristik řeči pomocí SSML

SSML můžete použít k vyladění tónu, výslovnosti, míry mluvení, hlasitosti a dalších aspektů v textu na výstup řeči odesláním požadavků ze schématu XML. Tato část ukazuje příklad změny hlasu. Další informace najdete v článku s postupy pro SSML.

Pokud chcete začít používat SSML k přizpůsobení, provedete menší změnu, která přepne hlas.

  1. Vytvořte nový soubor XML pro konfiguraci SSML v kořenovém adresáři projektu.

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

    V tomto příkladu je soubor ssml.xml. Kořenový prvek je vždy <speak>. Obtékání textu do elementu <voice> umožňuje změnit hlas pomocí parametru name . Úplný seznam podporovaných neurálních hlasů najdete v tématu Podporované jazyky.

  2. Změňte požadavek na syntézu řeči tak, aby odkaz na váš soubor XML. Požadavek je většinou stejný. Místo použití SpeakText() funkce použijete SpeakSsml(). Tato funkce očekává řetězec XML, takže nejprve vytvořte funkci, která načte soubor XML a vrátí ho jako řetězec:

    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.";
        }
    }
    

    V tomto okamžiku je výsledný objekt přesně stejný jako předchozí příklady:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
    
        String ssml = xmlToString("ssml.xml");
        SpeechSynthesisResult result = speechSynthesizer.SpeakSsml(ssml);
        AudioDataStream stream = AudioDataStream.fromResult(result);
        stream.saveToWavFile("path/to/write/file.wav");
    }
    

Poznámka:

Pokud chcete změnit hlas bez použití SSML, nastavte vlastnost SpeechConfig pomocí .SpeechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");

Přihlášení k odběru událostí syntetizátoru

Možná budete chtít získat další přehledy o zpracování textu a výsledcích řeči. Můžete například chtít vědět, kdy syntetizátor začíná a zastavuje, nebo můžete chtít vědět o jiných událostech, ke kterým došlo během syntézy.

Při použití speechSynthesizer pro převod textu na řeč můžete přihlásit k odběru událostí v této tabulce:

Událost Popis Případ použití
BookmarkReached Signály, že byla dosažena záložka. K aktivaci události bookmark dosažení záložky se v SSML vyžaduje prvek. Tato událost hlásí uplynulý čas výstupu zvuku mezi začátkem syntézy a prvkem bookmark . Vlastnost události Text je řetězcová hodnota, kterou jste nastavili v atributu záložky mark . Prvky bookmark nejsou mluvené. Pomocí elementu bookmark můžete vložit vlastní značky do SSML, abyste získali posun každé značky ve zvukovém streamu. Tento bookmark prvek lze použít k odkazování na konkrétní umístění v textu nebo sekvenci značek.
SynthesisCanceled Signály, že syntéza řeči byla zrušena. Můžete ověřit, kdy je syntéza zrušena.
SynthesisCompleted Signály, že syntéza řeči je kompletní. Po dokončení syntézy můžete potvrdit.
SynthesisStarted Signály, které syntéza řeči začala. Po spuštění syntézy můžete potvrdit.
Synthesizing Signály, že syntéza řeči probíhá. Tato událost se aktivuje pokaždé, když sada SDK obdrží zvukový blok dat ze služby Speech. Můžete ověřit, kdy probíhá syntéza.
VisemeReceived Signály, že byla přijata událost viseme. Viseme se často používají k reprezentaci klíčových pozic v pozorované řeči. Klíčové pozice zahrnují pozici rtů, jawa a jazyk při výrobě konkrétního fonemu. Pomocí visem můžete animovat tvář znaku při přehrávání hlasového zvuku.
WordBoundary Signály, že byla přijata hranice slova. Tato událost se vyvolá na začátku každého nového mluveného slova, interpunkce a věty. Událost hlásí posun času aktuálního slova od začátku výstupního zvuku. Tato událost také hlásí pozici znaku ve vstupním textu nebo SSML bezprostředně před slovem, které se chystáte vyslovit. Tato událost se běžně používá k získání relativní pozice textu a odpovídajícího zvuku. Možná budete chtít vědět o novém slově a pak provést akci na základě načasování. Můžete například získat informace, které vám pomůžou rozhodnout, kdy a jak dlouho se mají slova zvýrazňovat při mluveném slově.

Poznámka:

Události se aktivují, jakmile budou k dispozici výstupní zvuková data, což je rychlejší než přehrávání do výstupního zařízení. Volající musí odpovídajícím způsobem synchronizovat streamování a v reálném čase.

Tady je příklad, který ukazuje, jak se přihlásit k odběru událostí pro syntézu řeči. Můžete postupovat podle pokynů v rychlém startu, ale nahradit obsah tohoto souboru SpeechSynthesis.java následujícím kódem Java:

import com.microsoft.cognitiveservices.speech.*;
import com.microsoft.cognitiveservices.speech.audio.*;

import java.util.Scanner;
import java.util.concurrent.ExecutionException;

public class SpeechSynthesis {
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    private static String speechKey = System.getenv("SPEECH_KEY");
    private static String speechRegion = System.getenv("SPEECH_REGION");

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
        
        // Required for WordBoundary event sentences.
        speechConfig.setProperty(PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");

        String speechSynthesisVoiceName = "en-US-AvaMultilingualNeural"; 
        
        String ssml = String.format("<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>"
            .concat(String.format("<voice name='%s'>", speechSynthesisVoiceName))
            .concat("<mstts:viseme type='redlips_front'/>")
            .concat("The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.")
            .concat("</voice>")
            .concat("</speak>"));

        SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig);
        {
            // Subscribe to events

            speechSynthesizer.BookmarkReached.addEventListener((o, e) -> {
                System.out.println("BookmarkReached event:");
                System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
                System.out.println("\tText: " + e.getText());
            });

            speechSynthesizer.SynthesisCanceled.addEventListener((o, e) -> {
                System.out.println("SynthesisCanceled event");
            });

            speechSynthesizer.SynthesisCompleted.addEventListener((o, e) -> {
                SpeechSynthesisResult result = e.getResult();                
                byte[] audioData = result.getAudioData();
                System.out.println("SynthesisCompleted event:");
                System.out.println("\tAudioData: " + audioData.length + " bytes");
                System.out.println("\tAudioDuration: " + result.getAudioDuration());
                result.close();
            });
            
            speechSynthesizer.SynthesisStarted.addEventListener((o, e) -> {
                System.out.println("SynthesisStarted event");
            });

            speechSynthesizer.Synthesizing.addEventListener((o, e) -> {
                SpeechSynthesisResult result = e.getResult();
                byte[] audioData = result.getAudioData();
                System.out.println("Synthesizing event:");
                System.out.println("\tAudioData: " + audioData.length + " bytes");
                result.close();
            });

            speechSynthesizer.VisemeReceived.addEventListener((o, e) -> {
                System.out.println("VisemeReceived event:");
                System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
                System.out.println("\tVisemeId: " + e.getVisemeId());
            });

            speechSynthesizer.WordBoundary.addEventListener((o, e) -> {
                System.out.println("WordBoundary event:");
                System.out.println("\tBoundaryType: " + e.getBoundaryType());
                System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
                System.out.println("\tDuration: " + e.getDuration());
                System.out.println("\tText: " + e.getText());
                System.out.println("\tTextOffset: " + e.getTextOffset());
                System.out.println("\tWordLength: " + e.getWordLength());
            });

            // Synthesize the SSML
            System.out.println("SSML to synthesize:");
            System.out.println(ssml);
            SpeechSynthesisResult speechSynthesisResult = speechSynthesizer.SpeakSsmlAsync(ssml).get();

            if (speechSynthesisResult.getReason() == ResultReason.SynthesizingAudioCompleted) {
                System.out.println("SynthesizingAudioCompleted result");
            }
            else if (speechSynthesisResult.getReason() == ResultReason.Canceled) {
                SpeechSynthesisCancellationDetails cancellation = SpeechSynthesisCancellationDetails.fromResult(speechSynthesisResult);
                System.out.println("CANCELED: Reason=" + cancellation.getReason());

                if (cancellation.getReason() == CancellationReason.Error) {
                    System.out.println("CANCELED: ErrorCode=" + cancellation.getErrorCode());
                    System.out.println("CANCELED: ErrorDetails=" + cancellation.getErrorDetails());
                    System.out.println("CANCELED: Did you set the speech resource key and region values?");
                }
            }
        }
        speechSynthesizer.close();

        System.exit(0);
    }
}

Další texty pro ukázky řeči najdete na GitHubu.

Použití vlastního koncového bodu

Vlastní koncový bod je funkčně identický se standardním koncovým bodem, který se používá k převodu textu na požadavky na řeč.

Jedním z rozdílů je to, že EndpointId je nutné zadat, aby se váš vlastní hlas používal prostřednictvím sady Speech SDK. Můžete začít s textem na řeč rychlý start a pak aktualizovat kód pomocí operátoru EndpointId a SpeechSynthesisVoiceName.

SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
speechConfig.setSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig.setEndpointId("YourEndpointId");

Pokud chcete použít vlastní hlas prostřednictvím jazyka SSML (Speech Synthesis Markup Language), zadejte název modelu jako hlasový název. Tento příklad používá YourCustomVoiceName hlas.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Spuštění a použití kontejneru

Kontejnery služby Speech poskytují rozhraní API koncových bodů dotazů založených na websocketu, ke kterým se přistupuje prostřednictvím sady Speech SDK a rozhraní příkazového řádku služby Speech. Sada Speech SDK a Rozhraní příkazového řádku služby Speech ve výchozím nastavení používají veřejnou službu Speech. Pokud chcete kontejner použít, musíte změnit inicializační metodu. Místo klíče a oblasti použijte adresu URL hostitele kontejneru.

Další informace o kontejnerech najdete v tématu Instalace a spouštění kontejnerů služby Speech pomocí Dockeru.

Referenční dokumentace | Balíček (npm) | Další ukázky zdrojového kódu knihovny GitHub |

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Výběr jazyka syntézy a hlasu

Funkce převodu textu na řeč ve službě Speech podporuje více než 400 hlasů a více než 140 jazyků a variant. Můžete získat úplný seznam nebo je vyzkoušet v Galerii hlasu.

Zadejte jazyk nebo hlas, který odpovídá vašemu vstupnímu SpeechConfig textu, a použijte zadaný hlas:

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    // Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
    speechConfig.speechSynthesisLanguage = "en-US"; 
    speechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
}

synthesizeSpeech();

Všechny neurální hlasy jsou vícejazyčné a fluentní ve svém vlastním jazyce a angličtině. Pokud je například vstupní text v angličtině", "Jsem nadšený z pokusu o převod textu na řeč", a vyberete es-ES-ElviraNeural, text se mluví v angličtině se španělským zvýrazněním.

Pokud hlas nemluví jazykem vstupního textu, služba Speech nevytváří syntetizovaný zvuk. Úplný seznam podporovaných neurálních hlasů najdete v tématu Podpora jazyka a hlasu pro službu Speech.

Poznámka:

Výchozí hlas je první hlas vrácený pro každé národní prostředí z rozhraní API seznamu hlasu.

Hlas, který mluví, je určen v pořadí podle priority následujícím způsobem:

  • Pokud ho nenastavíte SpeechSynthesisVoiceName nebo SpeechSynthesisLanguage, výchozí hlas pro en-US mluvený hlas.
  • Pokud nastavíte SpeechSynthesisLanguagepouze , výchozí hlas pro zadané národní prostředí mluví.
  • Pokud jsou obě SpeechSynthesisVoiceName i SpeechSynthesisLanguage nastavené, SpeechSynthesisLanguage nastavení se ignoruje. Hlas, který určíte pomocí SpeechSynthesisVoiceName mluvených mluvčích.
  • Pokud je hlasový prvek nastaven pomocí jazyka SSML (Speech Synthesis Markup Language), budou ignorovány SpeechSynthesisVoiceName a SpeechSynthesisLanguage nastavení.

Syntetizace textu na řeč

K výstupu syntetizované řeči do aktuálního aktivního výstupního zařízení, jako je například reproduktor, vytvořte instanci AudioConfig pomocí fromDefaultSpeakerOutput() statické funkce. Tady je příklad:

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    const audioConfig = sdk.AudioConfig.fromDefaultSpeakerOutput();

    const speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    speechSynthesizer.speakTextAsync(
        "I'm excited to try text to speech",
        result => {
            if (result) {
                speechSynthesizer.close();
                return result.audioData;
            }
        },
        error => {
            console.log(error);
            speechSynthesizer.close();
        });
}

Při spuštění programu se syntetizovaný zvuk přehraje z reproduktoru. Tento výsledek je dobrým příkladem nejzákladnějšího použití. Dále můžete výstup přizpůsobit a zpracovat výstupní odpověď jako datový proud v paměti pro práci s vlastními scénáři.

Získání výsledku jako datového proudu v paměti

Výsledná zvuková data můžete použít jako datový proud v paměti místo přímého zápisu do souboru. Pomocí datového proudu v paměti můžete vytvářet vlastní chování:

  • Abstrahujte výsledné bajtové pole jako vyhledatelný datový proud pro vlastní podřízené služby.
  • Integrujte výsledek s jinými rozhraními API nebo službami.
  • Upravte zvuková data, zapisujte vlastní .wav záhlaví a proveďte související úkoly.

Tuto změnu můžete provést v předchozím příkladu. Odeberte blok, protože chování výstupu AudioConfig spravujete ručně od tohoto okamžiku, abyste zvýšili kontrolu. Pak předejte nullAudioConfig konstruktoru SpeechSynthesizer .

Poznámka:

AudioConfigKdyž ho předáte null , místo abyste ho vynechali jako v předchozím příkladu výstupu reproduktoru, ve výchozím nastavení se na aktuálním aktivním výstupním zařízení nepřehraje zvuk.

Uložte výsledek do proměnné SpeechSynthesisResult . Vlastnost SpeechSynthesisResult.audioData vrátí ArrayBuffer hodnotu výstupních dat, výchozí typ streamu prohlížeče. Pro kód na straně serveru převeďte ArrayBuffer na stream vyrovnávací paměti.

Následující kód funguje na straně klienta:

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig);

    speechSynthesizer.speakTextAsync(
        "I'm excited to try text to speech",
        result => {
            speechSynthesizer.close();
            return result.audioData;
        },
        error => {
            console.log(error);
            speechSynthesizer.close();
        });
}

Pomocí výsledného ArrayBuffer objektu můžete implementovat jakékoli vlastní chování. ArrayBuffer je běžný typ pro příjem v prohlížeči a přehrávání z tohoto formátu.

Pro jakýkoli serverový kód, pokud potřebujete pracovat s daty jako datový proud, musíte převést ArrayBuffer objekt na datový proud:

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig);

    speechSynthesizer.speakTextAsync(
        "I'm excited to try text to speech",
        result => {
            const { audioData } = result;

            speechSynthesizer.close();

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

Přizpůsobení formátu zvuku

Můžete přizpůsobit atributy zvukového výstupu, včetně:

  • Typ zvukového souboru
  • Vzorkovací frekvence
  • Hloubka bitu

Pokud chcete změnit formát zvuku speechSynthesisOutputFormat , použijte vlastnost objektu SpeechConfig . Tato vlastnost očekává enum instanci typu SpeechSynthesisOutputFormat. Pomocí příkazu enum vyberte výstupní formát. Dostupné formáty najdete v seznamu zvukových formátů.

Existují různé možnosti pro různé typy souborů v závislosti na vašich požadavcích. Podle definice nezpracované formáty, jako Raw24Khz16BitMonoPcm například neobsahují záhlaví zvuku. V jedné z těchto situací používejte nezpracované formáty:

  • Víte, že vaše podřízená implementace může dekódovat nezpracovaný bitstream.
  • Plánujete ručně vytvářet hlavičky na základě faktorů, jako je hloubka bitu, vzorkovací frekvence a počet kanálů.

Tento příklad určuje formát Riff24Khz16BitMonoPcm RIFF s vysokou věrností nastavením speechSynthesisOutputFormat objektu SpeechConfig . Podobně jako v příkladu v předchozí části získejte zvuková ArrayBuffer data a interagujte s nimi.

function synthesizeSpeech() {
    const speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");

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

    const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, null);
    speechSynthesizer.speakTextAsync(
        "I'm excited to try text to speech",
        result => {
            // Interact with the audio ArrayBuffer data
            const audioData = result.audioData;
            console.log(`Audio data byte size: ${audioData.byteLength}.`)

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

Přizpůsobení charakteristik řeči pomocí SSML

SSML můžete použít k vyladění tónu, výslovnosti, míry mluvení, hlasitosti a dalších aspektů v textu na výstup řeči odesláním požadavků ze schématu XML. Tato část ukazuje příklad změny hlasu. Další informace naleznete v tématu Přehled jazyka Speech Synthesis Markup Language.

Pokud chcete začít používat SSML k přizpůsobení, provedete menší změnu, která přepne hlas.

  1. Vytvořte nový soubor XML pro konfiguraci SSML v kořenovém adresáři projektu.

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

    V tomto příkladu je to ssml.xml. Kořenový prvek je vždy <speak>. Obtékání textu do elementu <voice> umožňuje změnit hlas pomocí parametru name . Úplný seznam podporovaných neurálních hlasů najdete v tématu Podporované jazyky.

  2. Změňte požadavek na syntézu řeči tak, aby odkaz na váš soubor XML. Požadavek je většinou stejný, ale místo použití speakTextAsync() funkce použijete speakSsmlAsync(). Tato funkce očekává řetězec XML. Vytvořte funkci, která načte soubor XML a vrátí ho jako řetězec:

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

    Další informace o readFileSyncsystému souborů Node.js.

    Výsledný objekt je přesně stejný jako předchozí příklady:

    function synthesizeSpeech() {
        const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, null);
    
        const ssml = xmlToString("ssml.xml");
        speechSynthesizer.speakSsmlAsync(
            ssml,
            result => {
                if (result.errorDetails) {
                    console.error(result.errorDetails);
                } else {
                    console.log(JSON.stringify(result));
                }
    
                speechSynthesizer.close();
            },
            error => {
                console.log(error);
                speechSynthesizer.close();
            });
    }
    

Poznámka:

Pokud chcete změnit hlas bez použití SSML, můžete vlastnost SpeechConfig nastavit pomocí .SpeechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";

Přihlášení k odběru událostí syntetizátoru

Možná budete chtít získat další přehledy o zpracování textu a výsledcích řeči. Můžete například chtít vědět, kdy syntetizátor začíná a zastavuje, nebo můžete chtít vědět o jiných událostech, ke kterým došlo během syntézy.

Při použití speechSynthesizer pro převod textu na řeč můžete přihlásit k odběru událostí v této tabulce:

Událost Popis Případ použití
BookmarkReached Signály, že byla dosažena záložka. K aktivaci události bookmark dosažení záložky se v SSML vyžaduje prvek. Tato událost hlásí uplynulý čas výstupu zvuku mezi začátkem syntézy a prvkem bookmark . Vlastnost události Text je řetězcová hodnota, kterou jste nastavili v atributu záložky mark . Prvky bookmark nejsou mluvené. Pomocí elementu bookmark můžete vložit vlastní značky do SSML, abyste získali posun každé značky ve zvukovém streamu. Tento bookmark prvek lze použít k odkazování na konkrétní umístění v textu nebo sekvenci značek.
SynthesisCanceled Signály, že syntéza řeči byla zrušena. Můžete ověřit, kdy je syntéza zrušena.
SynthesisCompleted Signály, že syntéza řeči je kompletní. Po dokončení syntézy můžete potvrdit.
SynthesisStarted Signály, které syntéza řeči začala. Po spuštění syntézy můžete potvrdit.
Synthesizing Signály, že syntéza řeči probíhá. Tato událost se aktivuje pokaždé, když sada SDK obdrží zvukový blok dat ze služby Speech. Můžete ověřit, kdy probíhá syntéza.
VisemeReceived Signály, že byla přijata událost viseme. Viseme se často používají k reprezentaci klíčových pozic v pozorované řeči. Klíčové pozice zahrnují pozici rtů, jawa a jazyk při výrobě konkrétního fonemu. Pomocí visem můžete animovat tvář znaku při přehrávání hlasového zvuku.
WordBoundary Signály, že byla přijata hranice slova. Tato událost se vyvolá na začátku každého nového mluveného slova, interpunkce a věty. Událost hlásí posun času aktuálního slova od začátku výstupního zvuku. Tato událost také hlásí pozici znaku ve vstupním textu nebo SSML bezprostředně před slovem, které se chystáte vyslovit. Tato událost se běžně používá k získání relativní pozice textu a odpovídajícího zvuku. Možná budete chtít vědět o novém slově a pak provést akci na základě načasování. Můžete například získat informace, které vám pomůžou rozhodnout, kdy a jak dlouho se mají slova zvýrazňovat při mluveném slově.

Poznámka:

Události se aktivují, jakmile budou k dispozici výstupní zvuková data, což je rychlejší než přehrávání do výstupního zařízení. Volající musí odpovídajícím způsobem synchronizovat streamování a v reálném čase.

Tady je příklad, který ukazuje, jak se přihlásit k odběru událostí pro syntézu řeči. Můžete postupovat podle pokynů v rychlém startu, ale nahradit obsah tohoto souboru SpeechSynthesis.js následujícím kódem JavaScriptu.

(function() {

    "use strict";

    var sdk = require("microsoft-cognitiveservices-speech-sdk");

    var audioFile = "YourAudioFile.wav";
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    const speechConfig = sdk.SpeechConfig.fromSubscription(process.env.SPEECH_KEY, process.env.SPEECH_REGION);
    const audioConfig = sdk.AudioConfig.fromAudioFileOutput(audioFile);

    var speechSynthesisVoiceName  = "en-US-AvaMultilingualNeural";  
    var ssml = `<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'> \r\n \
        <voice name='${speechSynthesisVoiceName}'> \r\n \
            <mstts:viseme type='redlips_front'/> \r\n \
            The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>. \r\n \
        </voice> \r\n \
    </speak>`;
    
    // Required for WordBoundary event sentences.
    speechConfig.setProperty(sdk.PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");

    // Create the speech speechSynthesizer.
    var speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, audioConfig);

    speechSynthesizer.bookmarkReached = function (s, e) {
        var str = `BookmarkReached event: \
            \r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
            \r\n\tText: \"${e.text}\".`;
        console.log(str);
    };

    speechSynthesizer.synthesisCanceled = function (s, e) {
        console.log("SynthesisCanceled event");
    };
    
    speechSynthesizer.synthesisCompleted = function (s, e) {
        var str = `SynthesisCompleted event: \
                    \r\n\tAudioData: ${e.result.audioData.byteLength} bytes \
                    \r\n\tAudioDuration: ${e.result.audioDuration}`;
        console.log(str);
    };

    speechSynthesizer.synthesisStarted = function (s, e) {
        console.log("SynthesisStarted event");
    };

    speechSynthesizer.synthesizing = function (s, e) {
        var str = `Synthesizing event: \
            \r\n\tAudioData: ${e.result.audioData.byteLength} bytes`;
        console.log(str);
    };
    
    speechSynthesizer.visemeReceived = function(s, e) {
        var str = `VisemeReceived event: \
            \r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
            \r\n\tVisemeId: ${e.visemeId}`;
        console.log(str);
    };

    speechSynthesizer.wordBoundary = function (s, e) {
        // Word, Punctuation, or Sentence
        var str = `WordBoundary event: \
            \r\n\tBoundaryType: ${e.boundaryType} \
            \r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
            \r\n\tDuration: ${e.duration} \
            \r\n\tText: \"${e.text}\" \
            \r\n\tTextOffset: ${e.textOffset} \
            \r\n\tWordLength: ${e.wordLength}`;
        console.log(str);
    };

    // Synthesize the SSML
    console.log(`SSML to synthesize: \r\n ${ssml}`)
    console.log(`Synthesize to: ${audioFile}`);
    speechSynthesizer.speakSsmlAsync(ssml,
        function (result) {
      if (result.reason === sdk.ResultReason.SynthesizingAudioCompleted) {
        console.log("SynthesizingAudioCompleted result");
      } else {
        console.error("Speech synthesis canceled, " + result.errorDetails +
            "\nDid you set the speech resource key and region values?");
      }
      speechSynthesizer.close();
      speechSynthesizer = null;
    },
        function (err) {
      console.trace("err - " + err);
      speechSynthesizer.close();
      speechSynthesizer = null;
    });
}());

Další texty pro ukázky řeči najdete na GitHubu.

Spuštění a použití kontejneru

Kontejnery služby Speech poskytují rozhraní API koncových bodů dotazů založených na websocketu, ke kterým se přistupuje prostřednictvím sady Speech SDK a rozhraní příkazového řádku služby Speech. Sada Speech SDK a Rozhraní příkazového řádku služby Speech ve výchozím nastavení používají veřejnou službu Speech. Pokud chcete kontejner použít, musíte změnit inicializační metodu. Místo klíče a oblasti použijte adresu URL hostitele kontejneru.

Další informace o kontejnerech najdete v tématu Instalace a spouštění kontejnerů služby Speech pomocí Dockeru.

Referenční dokumentace | Balíček (stáhnout) | Další ukázky na GitHubu

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Požadavky

Instalace sady Speech SDK a ukázek

Úložiště Azure-Samples/cognitive-services-speech-sdk obsahuje ukázky napsané v Objective-C pro iOS a Mac. Výběrem odkazu zobrazíte pokyny k instalaci jednotlivých ukázek:

Použití vlastního koncového bodu

Vlastní koncový bod je funkčně identický se standardním koncovým bodem, který se používá k převodu textu na požadavky na řeč.

Jedním z rozdílů je to, že EndpointId je nutné zadat, aby se váš vlastní hlas používal prostřednictvím sady Speech SDK. Můžete začít s textem na řeč rychlý start a pak aktualizovat kód pomocí operátoru EndpointId a SpeechSynthesisVoiceName.

SPXSpeechConfiguration *speechConfig = [[SPXSpeechConfiguration alloc] initWithSubscription:speechKey region:speechRegion];
speechConfig.speechSynthesisVoiceName = @"YourCustomVoiceName";
speechConfig.EndpointId = @"YourEndpointId";

Pokud chcete použít vlastní hlas prostřednictvím jazyka SSML (Speech Synthesis Markup Language), zadejte název modelu jako hlasový název. Tento příklad používá YourCustomVoiceName hlas.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Spuštění a použití kontejneru

Kontejnery služby Speech poskytují rozhraní API koncových bodů dotazů založených na websocketu, ke kterým se přistupuje prostřednictvím sady Speech SDK a rozhraní příkazového řádku služby Speech. Sada Speech SDK a Rozhraní příkazového řádku služby Speech ve výchozím nastavení používají veřejnou službu Speech. Pokud chcete kontejner použít, musíte změnit inicializační metodu. Místo klíče a oblasti použijte adresu URL hostitele kontejneru.

Další informace o kontejnerech najdete v tématu Instalace a spouštění kontejnerů služby Speech pomocí Dockeru.

Referenční dokumentace | Balíček (stáhnout) | Další ukázky na GitHubu

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Požadavky

Instalace sady Speech SDK a ukázek

Úložiště Azure-Samples/cognitive-services-speech-sdk obsahuje ukázky napsané ve Swiftu pro iOS a Mac. Výběrem odkazu zobrazíte pokyny k instalaci jednotlivých ukázek:

Spuštění a použití kontejneru

Kontejnery služby Speech poskytují rozhraní API koncových bodů dotazů založených na websocketu, ke kterým se přistupuje prostřednictvím sady Speech SDK a rozhraní příkazového řádku služby Speech. Sada Speech SDK a Rozhraní příkazového řádku služby Speech ve výchozím nastavení používají veřejnou službu Speech. Pokud chcete kontejner použít, musíte změnit inicializační metodu. Místo klíče a oblasti použijte adresu URL hostitele kontejneru.

Další informace o kontejnerech najdete v tématu Instalace a spouštění kontejnerů služby Speech pomocí Dockeru.

Referenční dokumentace | – balíček (PyPi) | Další ukázky na GitHubu

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Výběr jazyka syntézy a hlasu

Funkce převodu textu na řeč ve službě Speech podporuje více než 400 hlasů a více než 140 jazyků a variant. Můžete získat úplný seznam nebo je vyzkoušet v Galerii hlasu.

Zadejte jazyk nebo hlas, který odpovídá vašemu vstupnímu SpeechConfig textu, a použijte zadaný hlas:

# Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speech_config.speech_synthesis_language = "en-US" 
speech_config.speech_synthesis_voice_name ="en-US-AvaMultilingualNeural"

Všechny neurální hlasy jsou vícejazyčné a fluentní ve svém vlastním jazyce a angličtině. Pokud je například vstupní text v angličtině", "Jsem nadšený z pokusu o převod textu na řeč", a vyberete es-ES-ElviraNeural, text se mluví v angličtině se španělským zvýrazněním.

Pokud hlas nemluví jazykem vstupního textu, služba Speech nevytváří syntetizovaný zvuk. Úplný seznam podporovaných neurálních hlasů najdete v tématu Podpora jazyka a hlasu pro službu Speech.

Poznámka:

Výchozí hlas je první hlas vrácený pro každé národní prostředí z rozhraní API seznamu hlasu.

Hlas, který mluví, je určen v pořadí podle priority následujícím způsobem:

  • Pokud ho nenastavíte SpeechSynthesisVoiceName nebo SpeechSynthesisLanguage, výchozí hlas pro en-US mluvený hlas.
  • Pokud nastavíte SpeechSynthesisLanguagepouze , výchozí hlas pro zadané národní prostředí mluví.
  • Pokud jsou obě SpeechSynthesisVoiceName i SpeechSynthesisLanguage nastavené, SpeechSynthesisLanguage nastavení se ignoruje. Hlas, který určíte pomocí SpeechSynthesisVoiceName mluvených mluvčích.
  • Pokud je hlasový prvek nastaven pomocí jazyka SSML (Speech Synthesis Markup Language), budou ignorovány SpeechSynthesisVoiceName a SpeechSynthesisLanguage nastavení.

Syntetizace řeči do souboru

Vytvořte objekt SpeechSynthesizer . Tento objekt spouští převody řeči a výstupy do mluvčích, souborů nebo jiných výstupních datových proudů. SpeechSynthesizer přijímá jako parametry:

  • Objekt SpeechConfig , který jste vytvořili v předchozím kroku.
  • Objekt AudioOutputConfig , který určuje, jak se mají zpracovat výstupní výsledky.
  1. AudioOutputConfig Vytvořte instanci, která automaticky zapíše výstup do souboru .wav pomocí parametru konstruktorufilename:

    audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
    
  2. SpeechSynthesizer Vytvořte instanci předáním speech_config objektu a objektu audio_config jako parametrů. Pokud chcete syntetizovat řeč a zapisovat do souboru, spusťte speak_text_async() řetězec textu.

    speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
    speech_synthesizer.speak_text_async("I'm excited to try text to speech")
    

Když program spustíte, vytvoří syntetizovaný .wav soubor, který se zapíše do zadaného umístění. Tento výsledek je dobrým příkladem nejzákladnějšího použití. Dále můžete přizpůsobit výstup a zpracovat výstupní odpověď jako datový proud v paměti pro práci s vlastními scénáři.

Syntetizování výstupu reproduktoru

Pokud chcete výstupem syntetizované řeči do aktuálního aktivního výstupního zařízení, jako je například reproduktor, nastavte use_default_speaker parametr při vytváření AudioOutputConfig instance. Tady je příklad:

audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)

Získání výsledku jako datového proudu v paměti

Výsledná zvuková data můžete použít jako datový proud v paměti místo přímého zápisu do souboru. Pomocí datového proudu v paměti můžete vytvářet vlastní chování:

  • Abstrahujte výsledné bajtové pole jako vyhledatelný datový proud pro vlastní podřízené služby.
  • Integrujte výsledek s jinými rozhraními API nebo službami.
  • Upravte zvuková data, zapište vlastní záhlaví .wav a proveďte související úlohy.

Tuto změnu můžete provést v předchozím příkladu. Nejprve odeberte AudioConfig, protože chování výstupu spravujete ručně od tohoto okamžiku, abyste zvýšili kontrolu. AudioConfig Předejte None konstruktoruSpeechSynthesizer.

Poznámka:

AudioConfigKdyž ho předáte None , místo abyste ho vynechali jako v předchozím příkladu výstupu reproduktoru, ve výchozím nastavení se na aktuálním aktivním výstupním zařízení nepřehraje zvuk.

Uložte výsledek do SpeechSynthesisResult proměnné. Vlastnost audio_data obsahuje bytes objekt výstupních dat. S tímto objektem můžete pracovat ručně nebo můžete použít AudioDataStream třídu ke správě datového proudu v paměti.

V tomto příkladu AudioDataStream použijte konstruktor k získání datového proudu z výsledku:

speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = AudioDataStream(result)

V tomto okamžiku můžete implementovat jakékoli vlastní chování pomocí výsledného stream objektu.

Přizpůsobení formátu zvuku

Můžete přizpůsobit atributy zvukového výstupu, včetně:

  • Typ zvukového souboru
  • Vzorkovací frekvence
  • Hloubka bitu

Pokud chcete změnit formát zvuku set_speech_synthesis_output_format() , použijte funkci objektu SpeechConfig . Tato funkce očekává enum instanci typu SpeechSynthesisOutputFormat. Pomocí příkazu enum vyberte výstupní formát. Dostupné formáty najdete v seznamu zvukových formátů.

Existují různé možnosti pro různé typy souborů v závislosti na vašich požadavcích. Podle definice nezpracované formáty, jako Raw24Khz16BitMonoPcm například neobsahují záhlaví zvuku. V jedné z těchto situací používejte nezpracované formáty:

  • Víte, že vaše podřízená implementace může dekódovat nezpracovaný bitstream.
  • Plánujete ručně vytvářet hlavičky na základě faktorů, jako je hloubka bitu, vzorkovací frekvence a počet kanálů.

Tento příklad určuje formát Riff24Khz16BitMonoPcm RIFF s vysokou věrností nastavením SpeechSynthesisOutputFormat objektu SpeechConfig . Podobně jako v příkladu v předchozí části AudioDataStream získáte datový proud v paměti výsledku a pak ho zapíšete do souboru.

speech_config.set_speech_synthesis_output_format(speechsdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm)
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)

result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = speechsdk.AudioDataStream(result)
stream.save_to_wav_file("path/to/write/file.wav")

Když program spustíte, zapíše .wav soubor do zadané cesty.

Přizpůsobení charakteristik řeči pomocí SSML

SSML můžete použít k vyladění tónu, výslovnosti, míry mluvení, hlasitosti a dalších aspektů v textu na výstup řeči odesláním požadavků ze schématu XML. Tato část ukazuje příklad změny hlasu. Další informace naleznete v tématu Přehled jazyka Speech Synthesis Markup Language.

Pokud chcete začít používat SSML k přizpůsobení, proveďte menší změnu, která přepne hlas.

  1. Vytvořte nový soubor XML pro konfiguraci SSML v kořenovém adresáři projektu.

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

    V tomto příkladu je soubor ssml.xml. Kořenový prvek je vždy <speak>. Obtékání textu do elementu <voice> umožňuje změnit hlas pomocí parametru name . Úplný seznam podporovaných neurálních hlasů najdete v tématu Podporované jazyky.

  2. Změňte požadavek na syntézu řeči tak, aby odkaz na váš soubor XML. Požadavek je většinou stejný. Místo použití speak_text_async() funkce použijte speak_ssml_async(). Tato funkce očekává řetězec XML. Nejprve si přečtěte konfiguraci SSML jako řetězec. Z tohoto okamžiku je výsledný objekt přesně stejný jako předchozí příklady.

    Poznámka:

    ssml_string Pokud váš řetězec obsahuje  na začátku řetězce, musíte odstranit formát kusovníku nebo služba vrátí chybu. Provedete to nastavením parametru encoding následujícím způsobem: open("ssml.xml", "r", encoding="utf-8-sig").

    speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
    
    ssml_string = open("ssml.xml", "r").read()
    result = speech_synthesizer.speak_ssml_async(ssml_string).get()
    
    stream = speechsdk.AudioDataStream(result)
    stream.save_to_wav_file("path/to/write/file.wav")
    

Poznámka:

Pokud chcete změnit hlas bez použití SSML, můžete vlastnost SpeechConfig nastavit pomocí .speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural"

Přihlášení k odběru událostí syntetizátoru

Možná budete chtít získat další přehledy o zpracování textu a výsledcích řeči. Můžete například chtít vědět, kdy syntetizátor začíná a zastavuje, nebo můžete chtít vědět o jiných událostech, ke kterým došlo během syntézy.

Při použití speechSynthesizer pro převod textu na řeč můžete přihlásit k odběru událostí v této tabulce:

Událost Popis Případ použití
BookmarkReached Signály, že byla dosažena záložka. K aktivaci události bookmark dosažení záložky se v SSML vyžaduje prvek. Tato událost hlásí uplynulý čas výstupu zvuku mezi začátkem syntézy a prvkem bookmark . Vlastnost události Text je řetězcová hodnota, kterou jste nastavili v atributu záložky mark . Prvky bookmark nejsou mluvené. Pomocí elementu bookmark můžete vložit vlastní značky do SSML, abyste získali posun každé značky ve zvukovém streamu. Tento bookmark prvek lze použít k odkazování na konkrétní umístění v textu nebo sekvenci značek.
SynthesisCanceled Signály, že syntéza řeči byla zrušena. Můžete ověřit, kdy je syntéza zrušena.
SynthesisCompleted Signály, že syntéza řeči je kompletní. Po dokončení syntézy můžete potvrdit.
SynthesisStarted Signály, které syntéza řeči začala. Po spuštění syntézy můžete potvrdit.
Synthesizing Signály, že syntéza řeči probíhá. Tato událost se aktivuje pokaždé, když sada SDK obdrží zvukový blok dat ze služby Speech. Můžete ověřit, kdy probíhá syntéza.
VisemeReceived Signály, že byla přijata událost viseme. Viseme se často používají k reprezentaci klíčových pozic v pozorované řeči. Klíčové pozice zahrnují pozici rtů, jawa a jazyk při výrobě konkrétního fonemu. Pomocí visem můžete animovat tvář znaku při přehrávání hlasového zvuku.
WordBoundary Signály, že byla přijata hranice slova. Tato událost se vyvolá na začátku každého nového mluveného slova, interpunkce a věty. Událost hlásí posun času aktuálního slova od začátku výstupního zvuku. Tato událost také hlásí pozici znaku ve vstupním textu nebo SSML bezprostředně před slovem, které se chystáte vyslovit. Tato událost se běžně používá k získání relativní pozice textu a odpovídajícího zvuku. Možná budete chtít vědět o novém slově a pak provést akci na základě načasování. Můžete například získat informace, které vám pomůžou rozhodnout, kdy a jak dlouho se mají slova zvýrazňovat při mluveném slově.

Poznámka:

Události se aktivují, jakmile budou k dispozici výstupní zvuková data, což je rychlejší než přehrávání do výstupního zařízení. Volající musí odpovídajícím způsobem synchronizovat streamování a v reálném čase.

Tady je příklad, který ukazuje, jak se přihlásit k odběru událostí pro syntézu řeči. Postupujte podle pokynů v rychlém startu, ale nahraďte obsah tohoto souboru speech-synthesis.py následujícím kódem Pythonu:

import os
import azure.cognitiveservices.speech as speechsdk

def speech_synthesizer_bookmark_reached_cb(evt: speechsdk.SessionEventArgs):
    print('BookmarkReached event:')
    print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
    print('\tText: {}'.format(evt.text))

def speech_synthesizer_synthesis_canceled_cb(evt: speechsdk.SessionEventArgs):
    print('SynthesisCanceled event')

def speech_synthesizer_synthesis_completed_cb(evt: speechsdk.SessionEventArgs):
    print('SynthesisCompleted event:')
    print('\tAudioData: {} bytes'.format(len(evt.result.audio_data)))
    print('\tAudioDuration: {}'.format(evt.result.audio_duration))

def speech_synthesizer_synthesis_started_cb(evt: speechsdk.SessionEventArgs):
    print('SynthesisStarted event')

def speech_synthesizer_synthesizing_cb(evt: speechsdk.SessionEventArgs):
    print('Synthesizing event:')
    print('\tAudioData: {} bytes'.format(len(evt.result.audio_data)))

def speech_synthesizer_viseme_received_cb(evt: speechsdk.SessionEventArgs):
    print('VisemeReceived event:')
    print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
    print('\tVisemeId: {}'.format(evt.viseme_id))

def speech_synthesizer_word_boundary_cb(evt: speechsdk.SessionEventArgs):
    print('WordBoundary event:')
    print('\tBoundaryType: {}'.format(evt.boundary_type))
    print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
    print('\tDuration: {}'.format(evt.duration))
    print('\tText: {}'.format(evt.text))
    print('\tTextOffset: {}'.format(evt.text_offset))
    print('\tWordLength: {}'.format(evt.word_length))

# This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
speech_config = speechsdk.SpeechConfig(subscription=os.environ.get('SPEECH_KEY'), region=os.environ.get('SPEECH_REGION'))

# Required for WordBoundary event sentences.
speech_config.set_property(property_id=speechsdk.PropertyId.SpeechServiceResponse_RequestSentenceBoundary, value='true')

audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)

# Subscribe to events
speech_synthesizer.bookmark_reached.connect(speech_synthesizer_bookmark_reached_cb)
speech_synthesizer.synthesis_canceled.connect(speech_synthesizer_synthesis_canceled_cb)
speech_synthesizer.synthesis_completed.connect(speech_synthesizer_synthesis_completed_cb)
speech_synthesizer.synthesis_started.connect(speech_synthesizer_synthesis_started_cb)
speech_synthesizer.synthesizing.connect(speech_synthesizer_synthesizing_cb)
speech_synthesizer.viseme_received.connect(speech_synthesizer_viseme_received_cb)
speech_synthesizer.synthesis_word_boundary.connect(speech_synthesizer_word_boundary_cb)

# The language of the voice that speaks.
speech_synthesis_voice_name='en-US-AvaMultilingualNeural'

ssml = """<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
    <voice name='{}'>
        <mstts:viseme type='redlips_front'/>
        The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
    </voice>
</speak>""".format(speech_synthesis_voice_name)

# Synthesize the SSML
print("SSML to synthesize: \r\n{}".format(ssml))
speech_synthesis_result = speech_synthesizer.speak_ssml_async(ssml).get()

if speech_synthesis_result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted:
    print("SynthesizingAudioCompleted result")
elif speech_synthesis_result.reason == speechsdk.ResultReason.Canceled:
    cancellation_details = speech_synthesis_result.cancellation_details
    print("Speech synthesis canceled: {}".format(cancellation_details.reason))
    if cancellation_details.reason == speechsdk.CancellationReason.Error:
        if cancellation_details.error_details:
            print("Error details: {}".format(cancellation_details.error_details))
            print("Did you set the speech resource key and region values?")

Další texty pro ukázky řeči najdete na GitHubu.

Použití vlastního koncového bodu

Vlastní koncový bod je funkčně identický se standardním koncovým bodem, který se používá k převodu textu na požadavky na řeč.

Jedním z rozdílů je to, že endpoint_id je nutné zadat, aby se váš vlastní hlas používal prostřednictvím sady Speech SDK. Můžete začít s textem na řeč rychlý start a pak aktualizovat kód pomocí operátoru endpoint_id a speech_synthesis_voice_name.

speech_config = speechsdk.SpeechConfig(subscription=os.environ.get('SPEECH_KEY'), region=os.environ.get('SPEECH_REGION'))
speech_config.endpoint_id = "YourEndpointId"
speech_config.speech_synthesis_voice_name = "YourCustomVoiceName"

Pokud chcete použít vlastní hlas prostřednictvím jazyka SSML (Speech Synthesis Markup Language), zadejte název modelu jako hlasový název. Tento příklad používá YourCustomVoiceName hlas.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Spuštění a použití kontejneru

Kontejnery služby Speech poskytují rozhraní API koncových bodů dotazů založených na websocketu, ke kterým se přistupuje prostřednictvím sady Speech SDK a rozhraní příkazového řádku služby Speech. Sada Speech SDK a Rozhraní příkazového řádku služby Speech ve výchozím nastavení používají veřejnou službu Speech. Pokud chcete kontejner použít, musíte změnit inicializační metodu. Místo klíče a oblasti použijte adresu URL hostitele kontejneru.

Další informace o kontejnerech najdete v tématu Instalace a spouštění kontejnerů služby Speech pomocí Dockeru.

Speech to text REST API reference | Speech to text REST API for short audio reference | Additional Samples on GitHub

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Požadavky

Převod textu na řeč

Na příkazovém řádku spusťte následující příkaz. Do příkazu vložte tyto hodnoty:

  • Váš klíč prostředku služby Speech
  • Vaše oblast prostředků služby Speech

Můžete také chtít změnit následující hodnoty:

  • Hodnota X-Microsoft-OutputFormat záhlaví, která řídí formát výstupu zvuku. Seznam podporovaných formátů zvukového výstupu najdete v referenčních informacích k rozhraní REST API pro převod textu na řeč.
  • Výstupní hlas. Pokud chcete získat seznam hlasů dostupných pro koncový bod služby Speech, podívejte se na rozhraní API pro seznam hlasových služeb.
  • Výstupní soubor. V tomto příkladu směrujeme odpověď ze serveru do souboru s názvem output.mp3.
curl --location --request POST 'https://YOUR_RESOURCE_REGION.tts.speech.microsoft.com/cognitiveservices/v1' \
--header 'Ocp-Apim-Subscription-Key: YOUR_RESOURCE_KEY' \
--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 name='\''en-US-AvaMultilingualNeural'\''>
        I am excited to try text to speech
    </voice>
</speak>' > output.mp3

V tomto průvodci postupy se naučíte běžné vzory návrhu pro provádění syntézy textu na řeč.

Další informace o následujících oblastech najdete v tématu Co je text na řeč?

  • Získávání odpovědí jako datových proudů v paměti
  • Přizpůsobení výstupní vzorkovací frekvence a přenosové rychlosti
  • Odesílání žádostí o syntézu pomocí jazyka SSML (Speech Synthesis Markup Language).
  • Použití neurálních hlasů
  • Přihlášení k odběru událostí a akce na základě výsledků

Požadavky

Stažení a instalace

Postupujte podle těchtokrokůch

  1. Spuštěním následujícího příkazu .NET CLI nainstalujte Rozhraní příkazového řádku služby Speech:

    dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
    
  2. Spuštěním následujících příkazů nakonfigurujte klíč prostředku a oblast služby Speech. Nahraďte SUBSCRIPTION-KEY klíčem prostředku služby Speech a nahraďte REGION oblastí prostředků služby Speech.

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

Syntéza řeči do reproduktoru

Teď jste připraveni spustit rozhraní příkazového řádku služby Speech pro syntetizaci řeči z textu.

  • V okně konzoly přejděte do adresáře, který obsahuje binární soubor Rozhraní příkazového řádku služby Speech. Pak spusťte následující příkaz:

    spx synthesize --text "I'm excited to try text to speech"
    

Rozhraní příkazového řádku služby Speech vytváří přirozený jazyk v angličtině prostřednictvím počítačového mluvčího.

Syntetizace řeči do souboru

  • Spuštěním následujícího příkazu změňte výstup z reproduktoru na soubor .wav :

    spx synthesize --text "I'm excited to try text to speech" --audio output greetings.wav
    

Rozhraní příkazového řádku služby Speech vytvoří přirozený jazyk v angličtině do zvukového souboru greetings.wav .

Spuštění a použití kontejneru

Kontejnery služby Speech poskytují rozhraní API koncových bodů dotazů založených na websocketu, ke kterým se přistupuje prostřednictvím sady Speech SDK a rozhraní příkazového řádku služby Speech. Sada Speech SDK a Rozhraní příkazového řádku služby Speech ve výchozím nastavení používají veřejnou službu Speech. Pokud chcete kontejner použít, musíte změnit inicializační metodu. Místo klíče a oblasti použijte adresu URL hostitele kontejneru.

Další informace o kontejnerech najdete v tématu Instalace a spouštění kontejnerů služby Speech pomocí Dockeru.

Další kroky