Compartilhar via


Como sintetizar a fala a partir de texto

Documentação de referência | Pacote (NuGet) | Exemplos adicionais no GitHub

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Selecionar idioma e voz para a síntese

O recurso de Conversão de Texto em Fala no serviço de Fala dá suporte a mais de 400 vozes e mais de 140 idiomas e variantes. Acesse a lista completa ou experimente-as na Galeria de Voz.

Especifique o idioma ou a voz de SpeechConfig para corresponder ao seu texto de entrada e usar a voz especificada. O snippet de código a seguir mostra como essa técnica funciona:

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

Todas as vozes neurais são multilíngues e fluentes em seu próprio idioma e inglês. Por exemplo, se o texto de entrada em inglês for "I'm excited to try text to speech" e você seleciona es-ES-ElviraNeural, o texto será falado em inglês com um sotaque espanhol.

Se a voz não falar o idioma do texto de entrada, o serviço de Fala não criará o áudio sintetizado. Para obter uma lista completa de vozes neurais com suporte, confira Suporte de idioma e vozes do serviço de Fala.

Observação

A voz padrão é a primeira voz retornada por localidade através da API de lista de vozes.

A voz que fala é determinada em ordem de prioridade, da seguinte maneira:

  • Se você não definir SpeechSynthesisVoiceName ou SpeechSynthesisLanguage, a voz padrão de en-US será falada.
  • Se você definir apenas SpeechSynthesisLanguage, a voz padrão da localidade especificada será falada.
  • Se SpeechSynthesisVoiceName e SpeechSynthesisLanguage estiverem definidos, a configuração SpeechSynthesisLanguage será ignorada. A voz que você especifica usando SpeechSynthesisVoiceName fala.
  • Se o elemento de voz for definido usando a SSML (Linguagem de Marcação de Síntese de Fala), as configurações de SpeechSynthesisVoiceName e SpeechSynthesisLanguage serão ignoradas.

Em resumo, a ordem de prioridade pode ser descrita como:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Resultado
Voz padrão para falas en-US
A voz padrão para a localidade especificada fala.
A voz que você especifica usando SpeechSynthesisVoiceName fala.
A voz que você especifica usando SSML fala.

Sintetizar fala em um arquivo

Crie um objeto SpeechSynthesizer. Esse objeto mostrado nos seguintes snippets de código executa conversões de texto em fala e gera saídas para alto-falantes, arquivos ou outros fluxos de saída. SpeechSynthesizer aceita como parâmetros:

  • O objeto SpeechConfig que você criou na etapa anterior.
  • Um objeto AudioConfig que especifica como os resultados de saída devem ser tratados.
  1. Crie uma instância AudioConfig para gravar automaticamente a saída em um arquivo .wav usando a função FromWavFileOutput(). Instancie-a com uma instrução using.

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

    Uma instrução using, neste contexto, descarta automaticamente os recursos não gerenciados e faz com que o objeto saia do escopo após o descarte.

  2. Crie uma instância SpeechSynthesizer com outra instrução using. Passe os objetos speechConfig e audioConfig como parâmetros. Para sintetizar a fala e gravar em um arquivo, execute SpeakTextAsync() com uma cadeia de caracteres de texto.

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

Quando você executa o programa, ele cria um arquivo .wav sintetizado, que é gravado no local especificado. Esse resultado é um bom exemplo do uso mais básico. A seguir, você pode personalizar a saída e manipular a resposta de saída como um fluxo na memória para trabalhar com cenários personalizados.

Sintetizar para saída em alto-Falante

Para dar saída na fala sintetizada para o dispositivo de saída ativo atualmente, como um alto-falante, omita o parâmetro AudioConfig ao criar a instância SpeechSynthesizer. Aqui está um exemplo:

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

Obter um resultado como um fluxo na memória

Você pode usar os dados de áudio resultantes como um fluxo na memória em vez de gravar diretamente em um arquivo. Com o fluxo na memória, você pode criar um comportamento personalizado:

  • Abstrair a matriz de bytes resultante como um fluxo pesquisável para serviços downstream personalizados.
  • Integrar o resultado com outras APIs ou serviços.
  • Modifique os dados de áudio, grave os cabeçalhos .wav personalizados e execute as tarefas relacionadas.

Você pode fazer essa alteração no exemplo anterior. Primeiro, remova o bloco AudioConfig, pois daqui em diante você gerencia o comportamento de saída manualmente para ter mais controle. Passe null para o AudioConfig no construtor SpeechSynthesizer.

Observação

Passe null para o AudioConfig, em vez de omiti-lo como no exemplo da saída para o alto-falante anterior, não reproduz o áudio por padrão no dispositivo de saída ativo.

Salve o resultado em uma variável SpeechSynthesisResult. A propriedade AudioData contém uma instância byte [] para os dados de saída. Você pode trabalhar com essa instância byte [] manualmente ou pode usar a classe AudioDataStream para gerenciar o fluxo na memória.

Neste exemplo, você usa a função estática AudioDataStream.FromResult() para obter um fluxo do resultado:

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);
}

Nesse momento, você pode implementar qualquer comportamento personalizado usando o objeto stream resultante.

Personalizar o formato de áudio

Você pode personalizar os atributos de saída de áudio, incluindo:

  • Tipo de arquivo de áudio
  • Taxa de amostragem
  • Profundidade de bits

Para alterar o formato do áudio, use a função SetSpeechSynthesisOutputFormat() no objeto SpeechConfig. Essa função espera uma instância enum do tipo SpeechSynthesisOutputFormat. Use o enum para selecionar o formato de saída. Para ver os formatos disponíveis, consulte a lista de formatos de áudio.

Há várias opções de diferentes tipos de arquivo dependendo de seus requisitos. Por definição, formatos brutos como Raw24Khz16BitMonoPcm não incluem cabeçalhos de áudio. Use formatos brutos apenas em uma destas situações:

  • Você sabe que sua implementação downstream pode decodificar um fluxo de bits bruto.
  • Você planeja criar cabeçalhos manualmente com base em fatores como profundidade de bits, taxa de amostragem e número de canais.

Esse exemplo especifica um formato RIFF Riff24Khz16BitMonoPcm de alta fidelidade definindo o SpeechSynthesisOutputFormat no objeto SpeechConfig. Semelhante ao exemplo na seção anterior, você usa AudioDataStream para obter um fluxo na memória do resultado para depois gravá-lo em um arquivo.

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

Quando você executa o programa, ele grava um arquivo .wav no caminho especificado.

Usar SSML para personalizar as características de fala

É possível usar a SSML para ajustar a densidade, a pronúncia, a velocidade de fala, o volume e outros aspectos na saída da conversão de texto em fala enviando suas solicitações de um esquema XML. Esta seção mostra um exemplo de alteração de voz. Para obter mais informações, confira Visão geral da Linguagem de Marcação de Síntese de Fala.

Para começar a usar a SSML para personalização, faça uma pequena alteração que muda a voz.

  1. Crie um novo arquivo XML para a configuração da SSML no diretório do projeto raiz.

    <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>
    

    Nesse exemplo, o arquivo é ssml.xml. Elemento raiz é sempre <speak>. Encapsular o texto em um elemento <voice> permite que você altere a voz usando o parâmetro name. Para ver uma lista completa de vozes neurais com suporte, confira Idiomas com suporte.

  2. Altere a solicitação de sintetização de voz para fazer referência ao arquivo XML. A solicitação é basicamente a mesma, mas em vez de usar a função SpeakTextAsync(), você usa SpeakSsmlAsync(). Essa função espera uma cadeia de caracteres XML. Primeiro, carregue sua configuração de SSML como uma cadeia de caracteres usando File.ReadAllText(). A partir desse ponto, o objeto resultante é exatamente o mesmo que nos exemplos anteriores.

    Observação

    Se você estiver usando o Visual Studio, provavelmente sua configuração de build não encontrará seu arquivo XML por padrão. Clique com o botão direito do mouse no arquivo XML e selecione Propriedades. Altere a Ação de build para Conteúdo. Altere Copiar para diretório de saída para Copiar sempre.

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

Observação

Para alterar a voz sem usar SSML, você pode definir a propriedade no SpeechConfig usando SpeechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

Assinar eventos de sintetizador

Talvez você queira obter mais informações sobre o processamento de conversão de texto em fala e os resultados. Por exemplo, talvez você queira saber quando o sintetizador é iniciado e interrompido, ou talvez queira saber mais sobre outros eventos encontrados durante a síntese.

Ao usar o SpeechSynthesizer para conversão de texto em fala, você pode assinar os eventos nesta tabela:

Evento Descrição Caso de uso
BookmarkReached Sinaliza que um indicador foi atingido. Para disparar um evento alcançado pelo indicador, é necessário um elemento bookmark no SSML. Este evento relata o tempo decorrido entre o início da sintetização e o elemento bookmark da saída de áudio. A propriedade Text do evento é o valor da cadeia de caracteres que você define no atributo mark do indicador. Os elementos de bookmark não são falados. Use o elemento bookmark para inserir marcadores personalizados na SSML a fim de obter o deslocamento de cada marcador no fluxo de áudio. O elemento bookmark pode ser usado para referenciar uma localização específica no texto ou na sequência de marcas.
SynthesisCanceled Sinaliza que a síntese de fala foi cancelada. Você pode confirmar quando a síntese é cancelada.
SynthesisCompleted Sinaliza que a síntese de fala está concluída. Você pode confirmar quando a síntese está concluída.
SynthesisStarted Sinaliza que a síntese de fala começou. Você pode confirmar quando a síntese começou.
Synthesizing Sinaliza que a síntese de fala está em andamento. Esse evento é acionado sempre que o SDK recebe um trecho de áudio do Serviço de Fala. Você pode confirmar quando a síntese está em andamento.
VisemeReceived Sinaliza que um evento de visema foi recebido. Os visemas são usados geralmente para representar as principais poses na fala observada. As principais poses incluem a posição dos lábios, do maxilar e da língua na produção de um fonema específico. Você pode usar visemas para animar o rosto de um personagem conforme o áudio da fala é reproduzido.
WordBoundary Sinaliza que um limite de palavra foi recebido. Esse evento é gerado no início de cada nova palavra falada, pontuação ou frase. O evento relata a diferença de tempo da palavra atual, em tiques, desde o início do áudio de saída. Esse evento também relata a posição do caractere no texto de entrada ou SSML imediatamente antes da palavra que está prestes a ser falada. Esse evento geralmente é usado para obter posições relativas do texto e do áudio correspondente. Talvez você queira saber sobre uma nova palavra e, em seguida, tomar medidas com base no tempo. Por exemplo, você pode obter informações que podem ajudar a decidir quando e por quanto tempo realçar as palavras conforme elas são faladas.

Observação

Os eventos são gerados à medida que os dados de áudio de saída ficam disponíveis, o que é mais rápido do que a reprodução em um dispositivo de saída. O chamador deve sincronizar adequadamente o streaming e o tempo real.

Aqui está um exemplo que mostra como assinar eventos para síntese de fala.

Importante

Se você usar uma chave de API, armazene-a com segurança em outro lugar, como no Azure Key Vault. Não inclua a chave da API diretamente no seu código e nunca a publique publicamente.

Para obter mais informações sobre a segurança dos serviços de IA, confira Autenticar solicitações para serviços de IA do Azure.

Você pode seguir as instruções no início rápido, mas substitua o conteúdo do arquivo Program.cs pelo código C# a seguir:

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();
    }
}

Você pode encontrar mais amostras de conversão de texto em fala no GitHub.

Usar um ponto de extremidade personalizado

O ponto de extremidade personalizado é funcionalmente idêntico ao ponto de extremidade padrão usado para solicitações de conversão de texto em fala.

Uma diferença é que o EndpointId deve ser especificado para usar a voz personalizada por meio do SDK de Fala. Você pode começar com o início rápido da conversão de texto em fala e, em seguida, atualizar o código com EndpointId e o SpeechSynthesisVoiceName.

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

Para usar uma voz neural personalizada por meio de Speech Synthesis Markup Language (SSML), especifique o nome do modelo como o nome da voz. Este exemplo usa a voz YourCustomVoiceName.

<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>

Executar e usar um contêiner

Os contêineres de Fala fornecem APIs de ponto de extremidade de consulta baseadas em websocket que são acessadas através do SDK de Fala e da CLI de Fala. Por padrão, o SDK de Fala e a CLI de Fala usam o serviço público de Fala. Para usar o contêiner, você precisa alterar o método de inicialização. Use uma URL de host de contêiner em vez de chave e região.

Para obter mais informações sobre os contêineres, consulte Instalar e executar contêineres de Fala com o Docker.

Documentação de referência | Pacote (NuGet) | Exemplos adicionais no GitHub

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Selecionar idioma e voz para a síntese

O recurso de Conversão de Texto em Fala no serviço de Fala dá suporte a mais de 400 vozes e mais de 140 idiomas e variantes. Veja a lista completa de localidades com suporte na conversão de texto em fala ou experimente-as na Galeria de Voz.

Especifique o idioma ou a voz da classe SpeechConfig para corresponder ao seu texto de entrada e usar a voz especificada. O snippet de código a seguir mostra como essa técnica funciona:

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

Todas as vozes neurais são multilíngues e fluentes em seu próprio idioma e inglês. Por exemplo, se o texto de entrada em inglês for "I'm excited to try text to speech" e você seleciona es-ES-ElviraNeural, o texto será falado em inglês com um sotaque espanhol.

Se a voz não falar o idioma do texto de entrada, o serviço de Fala não criará o áudio sintetizado. Para obter uma lista completa de vozes neurais com suporte, confira Suporte de idioma e vozes do serviço de Fala.

Observação

A voz padrão é a primeira voz retornada por localidade através da API de lista de vozes.

A voz que fala é determinada em ordem de prioridade, da seguinte maneira:

  • Se você não definir SpeechSynthesisVoiceName ou SpeechSynthesisLanguage, a voz padrão de en-US será falada.
  • Se você definir apenas SpeechSynthesisLanguage, a voz padrão da localidade especificada será falada.
  • Se SpeechSynthesisVoiceName e SpeechSynthesisLanguage estiverem definidos, a configuração SpeechSynthesisLanguage será ignorada. A voz que você especifica usando SpeechSynthesisVoiceName fala.
  • Se o elemento de voz for definido usando a SSML (Linguagem de Marcação de Síntese de Fala), as configurações de SpeechSynthesisVoiceName e SpeechSynthesisLanguage serão ignoradas.

Em resumo, a ordem de prioridade pode ser descrita como:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Resultado
Voz padrão para falas en-US
A voz padrão para a localidade especificada fala.
A voz que você especifica usando SpeechSynthesisVoiceName fala.
A voz que você especifica usando SSML fala.

Sintetizar fala em um arquivo

Crie um objeto SpeechSynthesizer. Esse objeto mostrado nos seguintes snippets de código executa conversões de texto em fala e gera saídas para alto-falantes, arquivos ou outros fluxos de saída. SpeechSynthesizer aceita como parâmetros:

  • O objeto SpeechConfig que você criou na etapa anterior.
  • Um objeto AudioConfig que especifica como os resultados de saída devem ser tratados.
  1. Crie uma instância AudioConfig para gravar automaticamente a saída em um arquivo .wav usando a função FromWavFileOutput():

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Crie uma instância SpeechSynthesizer. Passe os objetos speechConfig e audioConfig como parâmetros. Para sintetizar a fala e gravar em um arquivo, execute SpeakTextAsync() com uma cadeia de caracteres de texto.

    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();
    }
    

Quando você executa o programa, ele cria um arquivo .wav sintetizado, que é gravado no local especificado. Esse resultado é um bom exemplo do uso mais básico. A seguir, você pode personalizar a saída e manipular a resposta de saída como um fluxo na memória para trabalhar com cenários personalizados.

Sintetizar para saída em alto-Falante

Para gerar a saída de fala sintetizada para o dispositivo de saída ativo atualmente, como um alto-falante, omita o parâmetro AudioConfig ao criar a instância SpeechSynthesizer. Veja um exemplo:

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();
}

Obter um resultado como um fluxo na memória

Você pode usar os dados de áudio resultantes como um fluxo na memória em vez de gravar diretamente em um arquivo. Com o fluxo na memória, você pode criar um comportamento personalizado:

  • Abstrair a matriz de bytes resultante como um fluxo pesquisável para serviços downstream personalizados.
  • Integrar o resultado com outras APIs ou serviços.
  • Modifique os dados de áudio, grave os cabeçalhos .wav personalizados e execute as tarefas relacionadas.

Você pode fazer essa alteração no exemplo anterior. Primeiro, remova o bloco AudioConfig, pois daqui em diante você gerencia o comportamento de saída manualmente para ter mais controle. Passe NULL para o AudioConfig no construtor SpeechSynthesizer.

Observação

Passe NULL para o AudioConfig, em vez de omiti-lo como no exemplo da saída para o alto-falante anterior, não reproduz o áudio por padrão no dispositivo de saída ativo.

Salve o resultado em uma variável SpeechSynthesisResult. O getter de GetAudioData retorna uma instância byte [] para os dados de saída. Você pode trabalhar com essa instância byte [] manualmente ou pode usar a classe AudioDataStream para gerenciar o fluxo na memória.

Nesse exemplo, você usa a função estática AudioDataStream.FromResult() para obter um fluxo do resultado:

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);
}

Nesse momento, você pode implementar qualquer comportamento personalizado usando o objeto stream resultante.

Personalizar o formato de áudio

Você pode personalizar os atributos de saída de áudio, incluindo:

  • Tipo de arquivo de áudio
  • Taxa de amostragem
  • Profundidade de bits

Para alterar o formato do áudio, use a função SetSpeechSynthesisOutputFormat() no objeto SpeechConfig. Essa função espera uma instância enum do tipo SpeechSynthesisOutputFormat. Use o enum para selecionar o formato de saída. Para ver os formatos disponíveis, consulte a lista de formatos de áudio.

Há várias opções de diferentes tipos de arquivo dependendo de seus requisitos. Por definição, formatos brutos como Raw24Khz16BitMonoPcm não incluem cabeçalhos de áudio. Use formatos brutos apenas em uma destas situações:

  • Você sabe que sua implementação downstream pode decodificar um fluxo de bits bruto.
  • Você planeja criar cabeçalhos manualmente com base em fatores como profundidade de bits, taxa de amostragem e número de canais.

Esse exemplo especifica um formato RIFF Riff24Khz16BitMonoPcm de alta fidelidade definindo o SpeechSynthesisOutputFormat no objeto SpeechConfig. Semelhante ao exemplo na seção anterior, você usa AudioDataStream para obter um fluxo na memória do resultado e, em seguida, gravá-lo em um arquivo.

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();
}

Quando você executa o programa, ele grava um arquivo .wav no caminho especificado.

Usar SSML para personalizar as características de fala

É possível usar a SSML para ajustar a densidade, a pronúncia, a velocidade de fala, o volume e outros aspectos na saída da conversão de texto em fala enviando suas solicitações de um esquema XML. Esta seção mostra um exemplo de alteração de voz. Para obter mais informações, confira Visão geral da Linguagem de Marcação de Síntese de Fala.

Para começar a usar a SSML para personalização, faça uma pequena alteração que muda a voz.

  1. Crie um novo arquivo XML para a configuração da SSML no diretório do projeto raiz.

    <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>
    

    Nesse exemplo, o arquivo é ssml.xml. Elemento raiz é sempre <speak>. Encapsular o texto em um elemento <voice> permite que você altere a voz usando o parâmetro name. Para ver uma lista completa de vozes neurais com suporte, confira Idiomas com suporte.

  2. Altere a solicitação de sintetização de voz para fazer referência ao arquivo XML. A solicitação é basicamente a mesma. Em vez de usar a função SpeakTextAsync(), você usa SpeakSsmlAsync(). Essa função espera uma cadeia de caracteres XML. Primeiro, carregue sua configuração de SSML como uma cadeia de caracteres. A partir desse ponto, o objeto resultante é exatamente o mesmo que nos exemplos anteriores.

    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();
    }
    

Observação

Para alterar a voz sem usar SSML, você pode definir a propriedade no SpeechConfig usando SpeechConfig.SetSpeechSynthesisVoiceName("en-US-AndrewMultilingualNeural").

Assinar eventos de sintetizador

Talvez você queira obter mais informações sobre o processamento de conversão de texto em fala e os resultados. Por exemplo, talvez você queira saber quando o sintetizador é iniciado e interrompido, ou talvez queira saber mais sobre outros eventos encontrados durante a síntese.

Ao usar o SpeechSynthesizer para conversão de texto em fala, você pode assinar os eventos nesta tabela:

Evento Descrição Caso de uso
BookmarkReached Sinaliza que um indicador foi atingido. Para disparar um evento alcançado pelo indicador, é necessário um elemento bookmark no SSML. Este evento relata o tempo decorrido entre o início da sintetização e o elemento bookmark da saída de áudio. A propriedade Text do evento é o valor da cadeia de caracteres que você define no atributo mark do indicador. Os elementos de bookmark não são falados. Use o elemento bookmark para inserir marcadores personalizados na SSML a fim de obter o deslocamento de cada marcador no fluxo de áudio. O elemento bookmark pode ser usado para referenciar uma localização específica no texto ou na sequência de marcas.
SynthesisCanceled Sinaliza que a síntese de fala foi cancelada. Você pode confirmar quando a síntese é cancelada.
SynthesisCompleted Sinaliza que a síntese de fala está concluída. Você pode confirmar quando a síntese está concluída.
SynthesisStarted Sinaliza que a síntese de fala começou. Você pode confirmar quando a síntese começou.
Synthesizing Sinaliza que a síntese de fala está em andamento. Esse evento é acionado sempre que o SDK recebe um trecho de áudio do Serviço de Fala. Você pode confirmar quando a síntese está em andamento.
VisemeReceived Sinaliza que um evento de visema foi recebido. Os visemas são usados geralmente para representar as principais poses na fala observada. As principais poses incluem a posição dos lábios, do maxilar e da língua na produção de um fonema específico. Você pode usar visemas para animar o rosto de um personagem conforme o áudio da fala é reproduzido.
WordBoundary Sinaliza que um limite de palavra foi recebido. Esse evento é gerado no início de cada nova palavra falada, pontuação ou frase. O evento relata a diferença de tempo da palavra atual, em tiques, desde o início do áudio de saída. Esse evento também relata a posição do caractere no texto de entrada ou SSML imediatamente antes da palavra que está prestes a ser falada. Esse evento geralmente é usado para obter posições relativas do texto e do áudio correspondente. Talvez você queira saber sobre uma nova palavra e, em seguida, tomar medidas com base no tempo. Por exemplo, você pode obter informações que podem ajudar a decidir quando e por quanto tempo realçar as palavras conforme elas são faladas.

Observação

Os eventos são gerados à medida que os dados de áudio de saída ficam disponíveis, o que é mais rápido do que a reprodução em um dispositivo de saída. O chamador deve sincronizar adequadamente o streaming e o tempo real.

Aqui está um exemplo que mostra como assinar eventos para síntese de fala.

Importante

Se você usar uma chave de API, armazene-a com segurança em outro lugar, como no Azure Key Vault. Não inclua a chave da API diretamente no seu código e nunca a publique publicamente.

Para obter mais informações sobre a segurança dos serviços de IA, confira Autenticar solicitações para serviços de IA do Azure.

Você pode seguir as instruções no início rápido, mas substitua o conteúdo do arquivo main.cpp pelo código a seguir:

#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
}

Você pode encontrar mais amostras de conversão de texto em fala no GitHub.

Usar um ponto de extremidade personalizado

O ponto de extremidade personalizado é funcionalmente idêntico ao ponto de extremidade padrão usado para solicitações de conversão de texto em fala.

Uma diferença é que o EndpointId deve ser especificado para usar a voz personalizada por meio do SDK de Fala. Você pode começar com o início rápido da conversão de texto em fala e, em seguida, atualizar o código com EndpointId e o SpeechSynthesisVoiceName.

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

Para usar uma voz neural personalizada por meio de Speech Synthesis Markup Language (SSML), especifique o nome do modelo como o nome da voz. Este exemplo usa a voz YourCustomVoiceName.

<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>

Executar e usar um contêiner

Os contêineres de Fala fornecem APIs de ponto de extremidade de consulta baseadas em websocket que são acessadas através do SDK de Fala e da CLI de Fala. Por padrão, o SDK de Fala e a CLI de Fala usam o serviço público de Fala. Para usar o contêiner, você precisa alterar o método de inicialização. Use uma URL de host de contêiner em vez de chave e região.

Para obter mais informações sobre os contêineres, consulte Instalar e executar contêineres de Fala com o Docker.

Documentação de referência | Pacote (Go) | Exemplos adicionais no GitHub

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Pré-requisitos

  • Uma assinatura do Azure. É possível criar uma gratuitamente.
  • Criar um recurso de Fala no portal do Azure.
  • Obter a região e a chave do recurso para Fala. Depois que o recurso de Fala for implantado, selecione Ir para o recurso para exibir e gerenciar as chaves.

Instalar o SDK de Fala

Antes de fazer qualquer coisa, instale o SDK de Fala para Go.

Conversão de texto em fala para o alto-falante

Use o exemplo de código a seguir para executar a síntese de fala no dispositivo de saída de áudio padrão. Substitua as variáveis subscription e region pela sua chave de fala e local/região. A execução do script falará o texto de entrada no alto-falante padrão.

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)
            }
        }
    }
}

Execute os comandos a seguir para criar um arquivo go.mod vinculado aos componentes hospedados no GitHub:

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

Agora compile e execute o código:

go build
go run quickstart

Para obter informações detalhadas sobre as classes, consulte os documentos de referência SpeechConfig e SpeechSynthesizer.

Conversão de texto em fala para o fluxo na memória

Você pode usar os dados de áudio resultantes como um fluxo na memória em vez de gravar diretamente em um arquivo. Com o fluxo na memória, você pode criar um comportamento personalizado:

  • Abstrair a matriz de bytes resultante como um fluxo pesquisável para serviços downstream personalizados.
  • Integrar o resultado com outras APIs ou serviços.
  • Modifique os dados de áudio, grave os cabeçalhos .wav personalizados e execute as tarefas relacionadas.

Você pode fazer essa alteração no exemplo anterior. Remova o bloco AudioConfig, pois daqui em diante você gerencia o comportamento de saída manualmente para ter mais controle. Em seguida, passe nil para o AudioConfig no construtor SpeechSynthesizer.

Observação

Passar nil para AudioConfig, em vez de omiti-lo como foi feito no exemplo da saída para o alto-falante anterior, não reproduzirá o áudio por padrão no dispositivo de saída ativo.

Salve o resultado em uma variável SpeechSynthesisResult. A propriedade AudioData retorna uma instância []byte para os dados de saída. Você pode trabalhar com essa instância []byte manualmente ou pode usar a classe AudioDataStream para gerenciar o fluxo na memória. Neste exemplo, você usa a função estática NewAudioDataStreamFromSpeechSynthesisResult() para obter um fluxo do resultado.

Substitua as variáveis subscription e region pela sua chave de fala e local/região:

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))
    }
}

Execute os comandos a seguir para criar um arquivo go.mod vinculado aos componentes hospedados no GitHub:

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

Agora compile e execute o código:

go build
go run quickstart

Para obter informações detalhadas sobre as classes, consulte os documentos de referência SpeechConfig e SpeechSynthesizer.

Selecionar idioma e voz para a síntese

O recurso de Conversão de Texto em Fala no serviço de Fala dá suporte a mais de 400 vozes e mais de 140 idiomas e variantes. Acesse a lista completa ou experimente-as na Galeria de Voz.

Especifique o idioma ou a voz de SpeechConfig para corresponder ao seu texto de entrada e usar a voz especificada:

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")

Todas as vozes neurais são multilíngues e fluentes em seu próprio idioma e inglês. Por exemplo, se o texto de entrada em inglês for "I'm excited to try text to speech" e você seleciona es-ES-ElviraNeural, o texto será falado em inglês com um sotaque espanhol.

Se a voz não falar o idioma do texto de entrada, o serviço de Fala não criará o áudio sintetizado. Para obter uma lista completa de vozes neurais com suporte, confira Suporte de idioma e vozes do serviço de Fala.

Observação

A voz padrão é a primeira voz retornada por localidade através da API de lista de vozes.

A voz que fala é determinada em ordem de prioridade, da seguinte maneira:

  • Se você não definir SpeechSynthesisVoiceName ou SpeechSynthesisLanguage, a voz padrão de en-US será falada.
  • Se você definir apenas SpeechSynthesisLanguage, a voz padrão da localidade especificada será falada.
  • Se SpeechSynthesisVoiceName e SpeechSynthesisLanguage estiverem definidos, a configuração SpeechSynthesisLanguage será ignorada. A voz que você especifica usando SpeechSynthesisVoiceName fala.
  • Se o elemento de voz for definido usando a SSML (Linguagem de Marcação de Síntese de Fala), as configurações de SpeechSynthesisVoiceName e SpeechSynthesisLanguage serão ignoradas.

Em resumo, a ordem de prioridade pode ser descrita como:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Resultado
Voz padrão para falas en-US
A voz padrão para a localidade especificada fala.
A voz que você especifica usando SpeechSynthesisVoiceName fala.
A voz que você especifica usando SSML fala.

Usar SSML para personalizar as características de fala

É possível utilizar a linguagem SSML (linguagem marcação de sintetização de voz) para ajustar a densidade, a pronúncia, a taxa de fala, o volume e outras características da saída da conversão de texto em fala ao enviar suas solicitações de um esquema XML. Esta seção mostra um exemplo de alteração de voz. Para obter mais informações, confira Visão geral da Linguagem de Marcação de Síntese de Fala.

Para começar a usar a SSML para personalização, faça uma pequena alteração que muda a voz.

Primeiro, crie um novo arquivo XML para a configuração de SSML no diretório do projeto raiz. Neste exemplo, é ssml.xml. Elemento raiz é sempre <speak>. Encapsular o texto em um elemento <voice> permite que você altere a voz usando o parâmetro name. Para ver uma lista completa de vozes neurais com suporte, confira Idiomas com suporte.

<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>

Em seguida, você precisa alterar a solicitação de sintetização de voz para fazer referência ao arquivo XML. A solicitação é basicamente a mesma, mas em vez de usar a função SpeakTextAsync(), você usa SpeakSsmlAsync(). Essa função espera uma cadeia de caracteres XML, portanto, você primeiro carrega a configuração de SSML como uma cadeia de caracteres. A partir desse ponto, o objeto resultante é exatamente o mesmo que nos exemplos anteriores.

Observação

Para definir a voz sem usar SSML, você pode definir a propriedade em SpeechConfig usando speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural").

Assinar eventos de sintetizador

Talvez você queira obter mais informações sobre o processamento de conversão de texto em fala e os resultados. Por exemplo, talvez você queira saber quando o sintetizador é iniciado e interrompido, ou talvez queira saber mais sobre outros eventos encontrados durante a síntese.

Ao usar o SpeechSynthesizer para conversão de texto em fala, você pode assinar os eventos nesta tabela:

Evento Descrição Caso de uso
BookmarkReached Sinaliza que um indicador foi atingido. Para disparar um evento alcançado pelo indicador, é necessário um elemento bookmark no SSML. Este evento relata o tempo decorrido entre o início da sintetização e o elemento bookmark da saída de áudio. A propriedade Text do evento é o valor da cadeia de caracteres que você define no atributo mark do indicador. Os elementos de bookmark não são falados. Use o elemento bookmark para inserir marcadores personalizados na SSML a fim de obter o deslocamento de cada marcador no fluxo de áudio. O elemento bookmark pode ser usado para referenciar uma localização específica no texto ou na sequência de marcas.
SynthesisCanceled Sinaliza que a síntese de fala foi cancelada. Você pode confirmar quando a síntese é cancelada.
SynthesisCompleted Sinaliza que a síntese de fala está concluída. Você pode confirmar quando a síntese está concluída.
SynthesisStarted Sinaliza que a síntese de fala começou. Você pode confirmar quando a síntese começou.
Synthesizing Sinaliza que a síntese de fala está em andamento. Esse evento é acionado sempre que o SDK recebe um trecho de áudio do Serviço de Fala. Você pode confirmar quando a síntese está em andamento.
VisemeReceived Sinaliza que um evento de visema foi recebido. Os visemas são usados geralmente para representar as principais poses na fala observada. As principais poses incluem a posição dos lábios, do maxilar e da língua na produção de um fonema específico. Você pode usar visemas para animar o rosto de um personagem conforme o áudio da fala é reproduzido.
WordBoundary Sinaliza que um limite de palavra foi recebido. Esse evento é gerado no início de cada nova palavra falada, pontuação ou frase. O evento relata a diferença de tempo da palavra atual, em tiques, desde o início do áudio de saída. Esse evento também relata a posição do caractere no texto de entrada ou SSML imediatamente antes da palavra que está prestes a ser falada. Esse evento geralmente é usado para obter posições relativas do texto e do áudio correspondente. Talvez você queira saber sobre uma nova palavra e, em seguida, tomar medidas com base no tempo. Por exemplo, você pode obter informações que podem ajudar a decidir quando e por quanto tempo realçar as palavras conforme elas são faladas.

Observação

Os eventos são gerados à medida que os dados de áudio de saída ficam disponíveis, o que é mais rápido do que a reprodução em um dispositivo de saída. O chamador deve sincronizar adequadamente o streaming e o tempo real.

Aqui está um exemplo que mostra como assinar eventos para síntese de fala.

Importante

Se você usar uma chave de API, armazene-a com segurança em outro lugar, como no Azure Key Vault. Não inclua a chave da API diretamente no seu código e nunca a publique publicamente.

Para obter mais informações sobre a segurança dos serviços de IA, confira Autenticar solicitações para serviços de IA do Azure.

Você pode seguir as instruções no início rápido, mas substitua o conteúdo do arquivo speech-synthesis.go pelo código Go a seguir:

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)
        }
    }
}

Você pode encontrar mais amostras de conversão de texto em fala no GitHub.

Executar e usar um contêiner

Os contêineres de Fala fornecem APIs de ponto de extremidade de consulta baseadas em websocket que são acessadas através do SDK de Fala e da CLI de Fala. Por padrão, o SDK de Fala e a CLI de Fala usam o serviço público de Fala. Para usar o contêiner, você precisa alterar o método de inicialização. Use uma URL de host de contêiner em vez de chave e região.

Para obter mais informações sobre os contêineres, consulte Instalar e executar contêineres de Fala com o Docker.

Documentação de referência | Exemplos adicionais no GitHub

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Selecionar idioma e voz para a síntese

O recurso de Conversão de Texto em Fala no serviço de Fala dá suporte a mais de 400 vozes e mais de 140 idiomas e variantes. Acesse a lista completa ou experimente-as na Galeria de Voz.

Especifique o idioma ou a voz de SpeechConfig para corresponder ao seu texto de entrada e usar a voz especificada. O snippet de código a seguir mostra como essa técnica funciona:

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

Todas as vozes neurais são multilíngues e fluentes em seu próprio idioma e inglês. Por exemplo, se o texto de entrada em inglês for "I'm excited to try text to speech" e você seleciona es-ES-ElviraNeural, o texto será falado em inglês com um sotaque espanhol.

Se a voz não falar o idioma do texto de entrada, o serviço de Fala não criará o áudio sintetizado. Para obter uma lista completa de vozes neurais com suporte, confira Suporte de idioma e vozes do serviço de Fala.

Observação

A voz padrão é a primeira voz retornada por localidade através da API de lista de vozes.

A voz que fala é determinada em ordem de prioridade, da seguinte maneira:

  • Se você não definir SpeechSynthesisVoiceName ou SpeechSynthesisLanguage, a voz padrão de en-US será falada.
  • Se você definir apenas SpeechSynthesisLanguage, a voz padrão da localidade especificada será falada.
  • Se SpeechSynthesisVoiceName e SpeechSynthesisLanguage estiverem definidos, a configuração SpeechSynthesisLanguage será ignorada. A voz que você especificou usando SpeechSynthesisVoiceName fala.
  • Se o elemento de voz for definido usando a SSML (Linguagem de Marcação de Síntese de Fala), as configurações de SpeechSynthesisVoiceName e SpeechSynthesisLanguage serão ignoradas.

Em resumo, a ordem de prioridade pode ser descrita como:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Resultado
Voz padrão para falas en-US
A voz padrão para a localidade especificada fala.
A voz que você especifica usando SpeechSynthesisVoiceName fala.
A voz que você especifica usando SSML fala.

Sintetizar fala em um arquivo

Crie um objeto SpeechSynthesizer. Esse objeto executa conversões de texto em fala e gera saídas para alto-falantes, arquivos ou outros fluxos de saída. SpeechSynthesizer aceita como parâmetros:

  • O objeto SpeechConfig que você criou na etapa anterior.
  • Um objeto AudioConfig que especifica como os resultados de saída devem ser tratados.
  1. Crie uma instância AudioConfig para gravar automaticamente a saída em um arquivo .wav usando a função estática fromWavFileOutput():

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Crie uma instância SpeechSynthesizer. Passe os objetos speechConfig e audioConfig como parâmetros. Para sintetizar a fala e gravar em um arquivo, execute SpeakText() com uma cadeia de caracteres de texto.

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

Quando você executa o programa, ele cria um arquivo .wav sintetizado, que é gravado no local especificado. Esse resultado é um bom exemplo do uso mais básico. A seguir, você pode personalizar a saída e manipular a resposta de saída como um fluxo na memória para trabalhar com cenários personalizados.

Sintetizar para saída em alto-Falante

Talvez você queira obter mais informações sobre o processamento de conversão de texto em fala e os resultados. Por exemplo, talvez você queira saber quando o sintetizador é iniciado e interrompido, ou talvez queira saber mais sobre outros eventos encontrados durante a síntese.

Para gerar a fala sintetizada para o dispositivo de saída ativo atual, como um alto-falante, instancie AudioConfig usando a função estática fromDefaultSpeakerOutput(). Aqui está um exemplo:

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

Obter um resultado como um fluxo na memória

Você pode usar os dados de áudio resultantes como um fluxo na memória em vez de gravar diretamente em um arquivo. Com o fluxo na memória, você pode criar um comportamento personalizado:

  • Abstrair a matriz de bytes resultante como um fluxo pesquisável para serviços downstream personalizados.
  • Integrar o resultado com outras APIs ou serviços.
  • Modifique os dados de áudio, grave os cabeçalhos .wav personalizados e execute as tarefas relacionadas.

Você pode fazer essa alteração no exemplo anterior. Primeiro, remova o bloco AudioConfig, pois daqui em diante você gerencia o comportamento de saída manualmente para ter mais controle. Em seguida, passe null para o AudioConfig no construtor SpeechSynthesizer.

Observação

Passe null para o AudioConfig, em vez de omiti-lo como foi feito no exemplo da saída para o alto-falante anterior, não reproduzirá o áudio por padrão no dispositivo de saída ativo.

Salve o resultado em uma variável SpeechSynthesisResult. A função SpeechSynthesisResult.getAudioData() retorna uma instância byte [] dos dados de saída. Você pode trabalhar com essa instância byte [] manualmente ou pode usar a classe AudioDataStream para gerenciar o fluxo na memória.

Nesse exemplo, você usa a função estática AudioDataStream.fromResult() para obter um fluxo do resultado:

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());
}

Nesse momento, você pode implementar qualquer comportamento personalizado usando o objeto stream resultante.

Personalizar o formato de áudio

Você pode personalizar os atributos de saída de áudio, incluindo:

  • Tipo de arquivo de áudio
  • Taxa de amostragem
  • Profundidade de bits

Para alterar o formato do áudio, use a função setSpeechSynthesisOutputFormat() no objeto SpeechConfig. Essa função espera uma instância enum do tipo SpeechSynthesisOutputFormat. Use o enum para selecionar o formato de saída. Para ver os formatos disponíveis, consulte a lista de formatos de áudio.

Há várias opções de diferentes tipos de arquivo dependendo de seus requisitos. Por definição, formatos brutos como Raw24Khz16BitMonoPcm não incluem cabeçalhos de áudio. Use formatos brutos apenas em uma destas situações:

  • Você sabe que sua implementação downstream pode decodificar um fluxo de bits bruto.
  • Você planeja criar cabeçalhos manualmente com base em fatores como profundidade de bits, taxa de amostragem e número de canais.

Esse exemplo especifica um formato RIFF Riff24Khz16BitMonoPcm de alta fidelidade definindo o SpeechSynthesisOutputFormat no objeto SpeechConfig. Semelhante ao exemplo na seção anterior, você usa AudioDataStream para obter um fluxo na memória do resultado e, em seguida, gravá-lo em um arquivo.

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

Quando você executa o programa, ele grava um arquivo .wav no caminho especificado.

Usar SSML para personalizar as características de fala

É possível usar a SSML para ajustar a densidade, a pronúncia, a velocidade de fala, o volume e outros aspectos na saída da conversão de texto em fala enviando suas solicitações de um esquema XML. Esta seção mostra um exemplo de alteração de voz. Para obter mais informações, confira o artigo sobre como usar a SSML.

Para começar a usar a SSML para personalização, faça uma pequena alteração que muda a voz.

  1. Crie um novo arquivo XML para a configuração da SSML no diretório do projeto raiz.

    <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>
    

    Nesse exemplo, o arquivo é ssml.xml. Elemento raiz é sempre <speak>. Encapsular o texto em um elemento <voice> permite que você altere a voz usando o parâmetro name. Para ver uma lista completa de vozes neurais com suporte, confira Idiomas com suporte.

  2. Altere a solicitação de sintetização de voz para fazer referência ao arquivo XML. A solicitação é basicamente a mesma. Em vez de usar a função SpeakText(), você usa SpeakSsml(). Essa função espera uma cadeia de caracteres XML, portanto, primeiro você cria uma função para carregar um arquivo XML e retorná-lo como uma cadeia de caracteres:

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

    Nesse momento, o objeto resultante é exatamente o mesmo que nos exemplos anteriores:

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

Observação

Para alterar a voz sem usar a SSML, você pode definir a propriedade no SpeechConfig usando SpeechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");.

Assinar eventos de sintetizador

Talvez você queira obter mais informações sobre o processamento de conversão de texto em fala e os resultados. Por exemplo, talvez você queira saber quando o sintetizador é iniciado e interrompido, ou talvez queira saber mais sobre outros eventos encontrados durante a síntese.

Ao usar o SpeechSynthesizer para conversão de texto em fala, você pode assinar os eventos nesta tabela:

Evento Descrição Caso de uso
BookmarkReached Sinaliza que um indicador foi atingido. Para disparar um evento alcançado pelo indicador, é necessário um elemento bookmark no SSML. Este evento relata o tempo decorrido entre o início da sintetização e o elemento bookmark da saída de áudio. A propriedade Text do evento é o valor da cadeia de caracteres que você define no atributo mark do indicador. Os elementos de bookmark não são falados. Use o elemento bookmark para inserir marcadores personalizados na SSML a fim de obter o deslocamento de cada marcador no fluxo de áudio. O elemento bookmark pode ser usado para referenciar uma localização específica no texto ou na sequência de marcas.
SynthesisCanceled Sinaliza que a síntese de fala foi cancelada. Você pode confirmar quando a síntese é cancelada.
SynthesisCompleted Sinaliza que a síntese de fala está concluída. Você pode confirmar quando a síntese está concluída.
SynthesisStarted Sinaliza que a síntese de fala começou. Você pode confirmar quando a síntese começou.
Synthesizing Sinaliza que a síntese de fala está em andamento. Esse evento é acionado sempre que o SDK recebe um trecho de áudio do Serviço de Fala. Você pode confirmar quando a síntese está em andamento.
VisemeReceived Sinaliza que um evento de visema foi recebido. Os visemas são usados geralmente para representar as principais poses na fala observada. As principais poses incluem a posição dos lábios, do maxilar e da língua na produção de um fonema específico. Você pode usar visemas para animar o rosto de um personagem conforme o áudio da fala é reproduzido.
WordBoundary Sinaliza que um limite de palavra foi recebido. Esse evento é gerado no início de cada nova palavra falada, pontuação ou frase. O evento relata a diferença de tempo da palavra atual, em tiques, desde o início do áudio de saída. Esse evento também relata a posição do caractere no texto de entrada ou SSML imediatamente antes da palavra que está prestes a ser falada. Esse evento geralmente é usado para obter posições relativas do texto e do áudio correspondente. Talvez você queira saber sobre uma nova palavra e, em seguida, tomar medidas com base no tempo. Por exemplo, você pode obter informações que podem ajudar a decidir quando e por quanto tempo realçar as palavras conforme elas são faladas.

Observação

Os eventos são gerados à medida que os dados de áudio de saída ficam disponíveis, o que é mais rápido do que a reprodução em um dispositivo de saída. O chamador deve sincronizar adequadamente o streaming e o tempo real.

Aqui está um exemplo que mostra como assinar eventos para síntese de fala.

Importante

Se você usar uma chave de API, armazene-a com segurança em outro lugar, como no Azure Key Vault. Não inclua a chave da API diretamente no seu código e nunca a publique publicamente.

Para obter mais informações sobre a segurança dos serviços de IA, confira Autenticar solicitações para serviços de IA do Azure.

Você pode seguir as instruções no início rápido, mas substitua o conteúdo do arquivo SpeechSynthesis.java pelo código Java a seguir:

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);
    }
}

Você pode encontrar mais amostras de conversão de texto em fala no GitHub.

Usar um ponto de extremidade personalizado

O ponto de extremidade personalizado é funcionalmente idêntico ao ponto de extremidade padrão usado para solicitações de conversão de texto em fala.

Uma diferença é que o EndpointId deve ser especificado para usar a voz personalizada por meio do SDK de Fala. Você pode começar com o início rápido da conversão de texto em fala e, em seguida, atualizar o código com EndpointId e o SpeechSynthesisVoiceName.

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

Para usar uma voz neural personalizada por meio de Speech Synthesis Markup Language (SSML), especifique o nome do modelo como o nome da voz. Este exemplo usa a voz YourCustomVoiceName.

<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>

Executar e usar um contêiner

Os contêineres de Fala fornecem APIs de ponto de extremidade de consulta baseadas em websocket que são acessadas através do SDK de Fala e da CLI de Fala. Por padrão, o SDK de Fala e a CLI de Fala usam o serviço público de Fala. Para usar o contêiner, você precisa alterar o método de inicialização. Use uma URL de host de contêiner em vez de chave e região.

Para obter mais informações sobre os contêineres, consulte Instalar e executar contêineres de Fala com o Docker.

Documentação de referência | Pacote (npm) | Exemplos adicionais no GitHub | Código-fonte da biblioteca

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Selecionar idioma e voz para a síntese

O recurso de Conversão de Texto em Fala no serviço de Fala dá suporte a mais de 400 vozes e mais de 140 idiomas e variantes. Acesse a lista completa ou experimente-as na Galeria de Voz.

Especifique o idioma ou a voz de SpeechConfig para corresponder ao seu texto de entrada e usar a voz especificada:

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();

Todas as vozes neurais são multilíngues e fluentes em seu próprio idioma e inglês. Por exemplo, se o texto de entrada em inglês for "I'm excited to try text to speech" e você seleciona es-ES-ElviraNeural, o texto será falado em inglês com um sotaque espanhol.

Se a voz não falar o idioma do texto de entrada, o serviço de Fala não criará o áudio sintetizado. Para obter uma lista completa de vozes neurais com suporte, confira Suporte de idioma e vozes do serviço de Fala.

Observação

A voz padrão é a primeira voz retornada por localidade através da API de lista de vozes.

A voz que fala é determinada em ordem de prioridade, da seguinte maneira:

  • Se você não definir SpeechSynthesisVoiceName ou SpeechSynthesisLanguage, a voz padrão de en-US será falada.
  • Se você definir apenas SpeechSynthesisLanguage, a voz padrão da localidade especificada será falada.
  • Se SpeechSynthesisVoiceName e SpeechSynthesisLanguage estiverem definidos, a configuração SpeechSynthesisLanguage será ignorada. A voz que você especifica usando SpeechSynthesisVoiceName fala.
  • Se o elemento de voz for definido usando a SSML (Linguagem de Marcação de Síntese de Fala), as configurações de SpeechSynthesisVoiceName e SpeechSynthesisLanguage serão ignoradas.

Em resumo, a ordem de prioridade pode ser descrita como:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Resultado
Voz padrão para falas en-US
A voz padrão para a localidade especificada fala.
A voz que você especifica usando SpeechSynthesisVoiceName fala.
A voz que você especifica usando SSML fala.

Sintetizar a conversão de texto em fala

Para gerar a fala sintetizada para o dispositivo de saída ativo atual, como um alto-falante, instancie AudioConfig usando a função estática fromDefaultSpeakerOutput(). Veja um exemplo:

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();
        });
}

Quando você executa o programa, o áudio sintetizado será executado do alto-falante. Esse resultado é um bom exemplo do uso mais básico. A seguir, você pode personalizar a saída e manipular a resposta de saída como um fluxo na memória para trabalhar com cenários personalizados.

Obter um resultado como um fluxo na memória

Você pode usar os dados de áudio resultantes como um fluxo na memória em vez de gravar diretamente em um arquivo. Com o fluxo na memória, você pode criar um comportamento personalizado:

  • Abstrair a matriz de bytes resultante como um fluxo pesquisável para serviços downstream personalizados.
  • Integrar o resultado com outras APIs ou serviços.
  • Modificar os dados de áudio, gravar os cabeçalhos .wav personalizados e executar as tarefas relacionadas.

Você pode fazer essa alteração no exemplo anterior. Remova o bloco AudioConfig, pois daqui em diante você gerencia o comportamento de saída manualmente para ter mais controle. Em seguida, passe null para o AudioConfig no construtor SpeechSynthesizer.

Observação

Passe null para o AudioConfig, em vez de omiti-lo como foi feito no exemplo da saída para o alto-falante anterior, não reproduzirá o áudio por padrão no dispositivo de saída ativo.

Salve o resultado em uma variável SpeechSynthesisResult. A propriedade SpeechSynthesisResult.audioData retorna um valor ArrayBuffer dos dados de saída, o tipo de fluxo do navegador padrão. Para código do lado do servidor, converta ArrayBuffer para um fluxo de buffer.

O código a seguir funciona para o lado do cliente:

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();
        });
}

Você pode implementar qualquer comportamento personalizado usando o objeto ArrayBuffer resultante. ArrayBuffer é um tipo comum para receber em um navegador e reproduzir por meio desse formato.

Para qualquer código baseado no servidor, se você precisar trabalhar com os dados em formato de fluxo, será necessário converter o objeto ArrayBuffer em um fluxo:

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();
        });
}

Personalizar o formato de áudio

Você pode personalizar os atributos de saída de áudio, incluindo:

  • Tipo de arquivo de áudio
  • Taxa de amostragem
  • Profundidade de bits

Para alterar o formato do áudio, use a propriedade speechSynthesisOutputFormat no objeto SpeechConfig. Essa propriedade espera uma instância enum do tipo SpeechSynthesisOutputFormat. Use o enum para selecionar o formato de saída. Para ver os formatos disponíveis, consulte a lista de formatos de áudio.

Há várias opções de diferentes tipos de arquivo dependendo de seus requisitos. Por definição, formatos brutos como Raw24Khz16BitMonoPcm não incluem cabeçalhos de áudio. Use formatos brutos apenas em uma destas situações:

  • Você sabe que sua implementação downstream pode decodificar um fluxo de bits bruto.
  • Você planeja criar cabeçalhos manualmente com base em fatores como profundidade de bits, taxa de amostragem e número de canais.

Esse exemplo especifica um formato RIFF Riff24Khz16BitMonoPcm de alta fidelidade definindo o speechSynthesisOutputFormat no objeto SpeechConfig. Semelhante ao exemplo na seção anterior, obtenha os dados ArrayBuffer de áudio e interaja com eles.

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();
        });
}

Usar SSML para personalizar as características de fala

É possível usar a SSML para ajustar a densidade, a pronúncia, a velocidade de fala, o volume e outros aspectos na saída da conversão de texto em fala enviando suas solicitações de um esquema XML. Esta seção mostra um exemplo de alteração de voz. Para obter mais informações, confira Visão geral da Linguagem de Marcação de Síntese de Fala.

Para começar a usar a SSML para personalização, faça uma pequena alteração que muda a voz.

  1. Crie um novo arquivo XML para a configuração da SSML no diretório do projeto raiz.

    <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>
    

    Nesse exemplo, trata-se da ssml.xml. Elemento raiz é sempre <speak>. Encapsular o texto em um elemento <voice> permite que você altere a voz usando o parâmetro name. Para ver uma lista completa de vozes neurais com suporte, confira Idiomas com suporte.

  2. Altere a solicitação de sintetização de voz para fazer referência ao arquivo XML. A solicitação é basicamente a mesma, mas em vez de usar a função speakTextAsync(), você usa speakSsmlAsync(). Essa função espera uma cadeia de caracteres XML. Crie uma função para carregar um arquivo XML e retorná-lo como uma cadeia de caracteres:

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

    Para obter mais informações sobre readFileSync, confira Sistema de arquivos do Node.js.

    O objeto resultante é exatamente o mesmo que nos exemplos anteriores:

    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();
            });
    }
    

Observação

Para alterar a voz sem usar SSML, você pode definir a propriedade no SpeechConfig usando SpeechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

Assinar eventos de sintetizador

Talvez você queira obter mais informações sobre o processamento de conversão de texto em fala e os resultados. Por exemplo, talvez você queira saber quando o sintetizador é iniciado e interrompido, ou talvez queira saber mais sobre outros eventos encontrados durante a síntese.

Ao usar o SpeechSynthesizer para conversão de texto em fala, você pode assinar os eventos nesta tabela:

Evento Descrição Caso de uso
BookmarkReached Sinaliza que um indicador foi atingido. Para disparar um evento alcançado pelo indicador, é necessário um elemento bookmark no SSML. Este evento relata o tempo decorrido entre o início da sintetização e o elemento bookmark da saída de áudio. A propriedade Text do evento é o valor da cadeia de caracteres que você define no atributo mark do indicador. Os elementos de bookmark não são falados. Use o elemento bookmark para inserir marcadores personalizados na SSML a fim de obter o deslocamento de cada marcador no fluxo de áudio. O elemento bookmark pode ser usado para referenciar uma localização específica no texto ou na sequência de marcas.
SynthesisCanceled Sinaliza que a síntese de fala foi cancelada. Você pode confirmar quando a síntese é cancelada.
SynthesisCompleted Sinaliza que a síntese de fala está concluída. Você pode confirmar quando a síntese está concluída.
SynthesisStarted Sinaliza que a síntese de fala começou. Você pode confirmar quando a síntese começou.
Synthesizing Sinaliza que a síntese de fala está em andamento. Esse evento é acionado sempre que o SDK recebe um trecho de áudio do Serviço de Fala. Você pode confirmar quando a síntese está em andamento.
VisemeReceived Sinaliza que um evento de visema foi recebido. Os visemas são usados geralmente para representar as principais poses na fala observada. As principais poses incluem a posição dos lábios, do maxilar e da língua na produção de um fonema específico. Você pode usar visemas para animar o rosto de um personagem conforme o áudio da fala é reproduzido.
WordBoundary Sinaliza que um limite de palavra foi recebido. Esse evento é gerado no início de cada nova palavra falada, pontuação ou frase. O evento relata a diferença de tempo da palavra atual, em tiques, desde o início do áudio de saída. Esse evento também relata a posição do caractere no texto de entrada ou SSML imediatamente antes da palavra que está prestes a ser falada. Esse evento geralmente é usado para obter posições relativas do texto e do áudio correspondente. Talvez você queira saber sobre uma nova palavra e, em seguida, tomar medidas com base no tempo. Por exemplo, você pode obter informações que podem ajudar a decidir quando e por quanto tempo realçar as palavras conforme elas são faladas.

Observação

Os eventos são gerados à medida que os dados de áudio de saída ficam disponíveis, o que é mais rápido do que a reprodução em um dispositivo de saída. O chamador deve sincronizar adequadamente o streaming e o tempo real.

Aqui está um exemplo que mostra como assinar eventos para síntese de fala.

Importante

Se você usar uma chave de API, armazene-a com segurança em outro lugar, como no Azure Key Vault. Não inclua a chave da API diretamente no seu código e nunca a publique publicamente.

Para obter mais informações sobre a segurança dos serviços de IA, confira Autenticar solicitações para serviços de IA do Azure.

Você pode seguir as instruções no início rápido, mas substitua o conteúdo do arquivo SpeechSynthesis.js pelo código JavaScript a seguir.

(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;
    });
}());

Você pode encontrar mais amostras de conversão de texto em fala no GitHub.

Executar e usar um contêiner

Os contêineres de Fala fornecem APIs de ponto de extremidade de consulta baseadas em websocket que são acessadas através do SDK de Fala e da CLI de Fala. Por padrão, o SDK de Fala e a CLI de Fala usam o serviço público de Fala. Para usar o contêiner, você precisa alterar o método de inicialização. Use uma URL de host de contêiner em vez de chave e região.

Para obter mais informações sobre os contêineres, consulte Instalar e executar contêineres de Fala com o Docker.

Documentação de referência | Pacote (download) | Exemplos adicionais no GitHub

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Pré-requisitos

  • Uma assinatura do Azure. É possível criar uma gratuitamente.
  • Criar um recurso de Fala no portal do Azure.
  • Obter a região e a chave do recurso para Fala. Depois que o recurso de Fala for implantado, selecione Ir para o recurso para exibir e gerenciar as chaves.

Instalar o SDK de Fala e exemplos

O repositório Azure-Samples/cognitive-services-speech-sdk contém exemplos escritos em Objective-C para iOS e Mac. Selecione um link para ver as instruções de instalação de cada exemplo:

Usar um ponto de extremidade personalizado

O ponto de extremidade personalizado é funcionalmente idêntico ao ponto de extremidade padrão usado para solicitações de conversão de texto em fala.

Uma diferença é que o EndpointId deve ser especificado para usar a voz personalizada por meio do SDK de Fala. Você pode começar com o início rápido da conversão de texto em fala e, em seguida, atualizar o código com EndpointId e o SpeechSynthesisVoiceName.

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

Para usar uma voz neural personalizada por meio de Speech Synthesis Markup Language (SSML), especifique o nome do modelo como o nome da voz. Este exemplo usa a voz YourCustomVoiceName.

<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>

Executar e usar um contêiner

Os contêineres de Fala fornecem APIs de ponto de extremidade de consulta baseadas em websocket que são acessadas através do SDK de Fala e da CLI de Fala. Por padrão, o SDK de Fala e a CLI de Fala usam o serviço público de Fala. Para usar o contêiner, você precisa alterar o método de inicialização. Use uma URL de host de contêiner em vez de chave e região.

Para obter mais informações sobre os contêineres, consulte Instalar e executar contêineres de Fala com o Docker.

Documentação de referência | Pacote (download) | Exemplos adicionais no GitHub

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Pré-requisitos

  • Uma assinatura do Azure. É possível criar uma gratuitamente.
  • Criar um recurso de Fala no portal do Azure.
  • Obter a região e a chave do recurso para Fala. Depois que o recurso de Fala for implantado, selecione Ir para o recurso para exibir e gerenciar as chaves.

Instalar o SDK de Fala e exemplos

O repositório Azure-Samples/cognitive-services-speech-sdk contém exemplos escritos em Swift para iOS e Mac. Selecione um link para ver as instruções de instalação de cada exemplo:

Executar e usar um contêiner

Os contêineres de Fala fornecem APIs de ponto de extremidade de consulta baseadas em websocket que são acessadas através do SDK de Fala e da CLI de Fala. Por padrão, o SDK de Fala e a CLI de Fala usam o serviço público de Fala. Para usar o contêiner, você precisa alterar o método de inicialização. Use uma URL de host de contêiner em vez de chave e região.

Para obter mais informações sobre os contêineres, consulte Instalar e executar contêineres de Fala com o Docker.

Documentação de referência | Pacote (PyPi) | Exemplos adicionais no GitHub

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Selecionar idioma e voz para a síntese

O recurso de Conversão de Texto em Fala no serviço de Fala dá suporte a mais de 400 vozes e mais de 140 idiomas e variantes. Acesse a lista completa ou experimente-as na Galeria de Voz.

Especifique o idioma ou a voz de SpeechConfig para corresponder ao seu texto de entrada e usar a voz especificada:

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

Todas as vozes neurais são multilíngues e fluentes em seu próprio idioma e inglês. Por exemplo, se o texto de entrada em inglês for "I'm excited to try text to speech" e você seleciona es-ES-ElviraNeural, o texto será falado em inglês com um sotaque espanhol.

Se a voz não falar o idioma do texto de entrada, o serviço de Fala não criará o áudio sintetizado. Para obter uma lista completa de vozes neurais com suporte, confira Suporte de idioma e vozes do serviço de Fala.

Observação

A voz padrão é a primeira voz retornada por localidade através da API de lista de vozes.

A voz que fala é determinada em ordem de prioridade, da seguinte maneira:

  • Se você não definir SpeechSynthesisVoiceName ou SpeechSynthesisLanguage, a voz padrão de en-US será falada.
  • Se você definir apenas SpeechSynthesisLanguage, a voz padrão da localidade especificada será falada.
  • Se SpeechSynthesisVoiceName e SpeechSynthesisLanguage estiverem definidos, a configuração SpeechSynthesisLanguage será ignorada. A voz que você especifica usando SpeechSynthesisVoiceName fala.
  • Se o elemento de voz for definido usando a SSML (Linguagem de Marcação de Síntese de Fala), as configurações de SpeechSynthesisVoiceName e SpeechSynthesisLanguage serão ignoradas.

Em resumo, a ordem de prioridade pode ser descrita como:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Resultado
Voz padrão para falas en-US
A voz padrão para a localidade especificada fala.
A voz que você especifica usando SpeechSynthesisVoiceName fala.
A voz que você especifica usando SSML fala.

Sintetizar fala em um arquivo

Crie um objeto SpeechSynthesizer. Esse objeto executa conversões de texto em fala e gera saídas para alto-falantes, arquivos ou outros fluxos de saída. SpeechSynthesizer aceita como parâmetros:

  • O objeto SpeechConfig que você criou na etapa anterior.
  • Um objeto AudioOutputConfig que especifica como os resultados de saída devem ser tratados.
  1. Crie uma instância AudioOutputConfig para gravar automaticamente a saída em um arquivo .wav usando o parâmetro do construtor filename:

    audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
    
  2. Crie uma instância SpeechSynthesizer passando os objetos speech_config e audio_config como parâmetros. Para sintetizar a fala e gravar em um arquivo, execute speak_text_async() com uma cadeia de caracteres de texto.

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

Quando você executa o programa, ele cria um arquivo .wav sintetizado, que é gravado no local especificado. Esse resultado é um bom exemplo do uso mais básico. A seguir, você pode personalizar a saída e manipular a resposta de saída como um fluxo na memória para trabalhar com cenários personalizados.

Sintetizar para saída em alto-Falante

Para gerar a saída de fala sintetizada para o dispositivo de saída ativo atualmente, como um alto-falante, defina o parâmetro use_default_speaker ao criar a instância AudioOutputConfig. Veja um exemplo:

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

Obter um resultado como um fluxo na memória

Você pode usar os dados de áudio resultantes como um fluxo na memória em vez de gravar diretamente em um arquivo. Com o fluxo na memória, você pode criar um comportamento personalizado:

  • Abstrair a matriz de bytes resultante como um fluxo pesquisável para serviços downstream personalizados.
  • Integrar o resultado com outras APIs ou serviços.
  • Modifique os dados de áudio, grave os cabeçalhos .wav personalizados e execute as tarefas relacionadas.

Você pode fazer essa alteração no exemplo anterior. Primeiro, remova o AudioConfig, pois a partir daqui você gerenciará o comportamento de saída manualmente para ter mais controle. Passe None para o AudioConfig no construtor SpeechSynthesizer.

Observação

Passe None para o AudioConfig, em vez de omiti-lo como foi feito no exemplo da saída para o alto-falante anterior, não reproduzirá o áudio por padrão no dispositivo de saída ativo.

Salve o resultado em uma variável SpeechSynthesisResult. A propriedade audio_data contém um objeto bytes dos dados de saída. Você pode trabalhar com esse objeto manualmente ou pode usar a classe AudioDataStream para gerenciar o fluxo na memória.

Nesse exemplo, você usa o construtor AudioDataStream para obter um fluxo do resultado:

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

Nesse momento, você pode implementar qualquer comportamento personalizado usando o objeto stream resultante.

Personalizar o formato de áudio

Você pode personalizar os atributos de saída de áudio, incluindo:

  • Tipo de arquivo de áudio
  • Taxa de amostragem
  • Profundidade de bits

Para alterar o formato do áudio, use a função set_speech_synthesis_output_format() no objeto SpeechConfig. Essa função espera uma instância enum do tipo SpeechSynthesisOutputFormat. Use o enum para selecionar o formato de saída. Para ver os formatos disponíveis, consulte a lista de formatos de áudio.

Há várias opções de diferentes tipos de arquivo dependendo de seus requisitos. Por definição, formatos brutos como Raw24Khz16BitMonoPcm não incluem cabeçalhos de áudio. Use formatos brutos apenas em uma destas situações:

  • Você sabe que sua implementação downstream pode decodificar um fluxo de bits bruto.
  • Você planeja criar cabeçalhos manualmente com base em fatores como profundidade de bits, taxa de amostragem e número de canais.

Esse exemplo especifica um formato RIFF Riff24Khz16BitMonoPcm de alta fidelidade definindo o SpeechSynthesisOutputFormat no objeto SpeechConfig. Semelhante ao exemplo na seção anterior, você usa AudioDataStream para obter um fluxo na memória do resultado e, em seguida, gravá-lo em um arquivo.

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

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

Quando você executa o programa, ele grava um arquivo .wav no caminho especificado.

Usar SSML para personalizar as características de fala

É possível usar a SSML para ajustar a densidade, a pronúncia, a velocidade de fala, o volume e outros aspectos na saída da conversão de texto em fala enviando suas solicitações de um esquema XML. Esta seção mostra um exemplo de alteração de voz. Para obter mais informações, confira Visão geral da Linguagem de Marcação de Síntese de Fala.

Para começar a usar a SSML para personalização, faça uma pequena alteração que muda a voz.

  1. Crie um novo arquivo XML para a configuração da SSML no diretório do projeto raiz.

    <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>
    

    Nesse exemplo, o arquivo é ssml.xml. Elemento raiz é sempre <speak>. Encapsular o texto em um elemento <voice> permite que você altere a voz usando o parâmetro name. Para ver uma lista completa de vozes neurais com suporte, confira Idiomas com suporte.

  2. Altere a solicitação de sintetização de voz para fazer referência ao arquivo XML. A solicitação é basicamente a mesma. Em vez de usar a função speak_text_async(), use speak_ssml_async(). Essa função espera uma cadeia de caracteres XML. Primeiro, leia sua configuração de SSML como uma cadeia de caracteres. A partir desse ponto, o objeto resultante é exatamente o mesmo que nos exemplos anteriores.

    Observação

    Se o ssml_string contiver  no início da cadeia de caracteres, você precisará remover o formato da BOM ou o serviço retornará um erro. Você faz isso definindo o parâmetro encoding da seguinte maneira: 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()
    speech_synthesis_result = speech_synthesizer.speak_ssml_async(ssml_string).get()
    
    stream = speechsdk.AudioDataStream(speech_synthesis_result)
    stream.save_to_wav_file("path/to/write/file.wav")
    

Observação

Para alterar a voz sem usar SSML, você pode definir a propriedade no SpeechConfig usando speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural".

Assinar eventos de sintetizador

Talvez você queira obter mais informações sobre o processamento de conversão de texto em fala e os resultados. Por exemplo, talvez você queira saber quando o sintetizador é iniciado e interrompido, ou talvez queira saber mais sobre outros eventos encontrados durante a síntese.

Ao usar o SpeechSynthesizer para conversão de texto em fala, você pode assinar os eventos nesta tabela:

Evento Descrição Caso de uso
BookmarkReached Sinaliza que um indicador foi atingido. Para disparar um evento alcançado pelo indicador, é necessário um elemento bookmark no SSML. Este evento relata o tempo decorrido entre o início da sintetização e o elemento bookmark da saída de áudio. A propriedade Text do evento é o valor da cadeia de caracteres que você define no atributo mark do indicador. Os elementos de bookmark não são falados. Use o elemento bookmark para inserir marcadores personalizados na SSML a fim de obter o deslocamento de cada marcador no fluxo de áudio. O elemento bookmark pode ser usado para referenciar uma localização específica no texto ou na sequência de marcas.
SynthesisCanceled Sinaliza que a síntese de fala foi cancelada. Você pode confirmar quando a síntese é cancelada.
SynthesisCompleted Sinaliza que a síntese de fala está concluída. Você pode confirmar quando a síntese está concluída.
SynthesisStarted Sinaliza que a síntese de fala começou. Você pode confirmar quando a síntese começou.
Synthesizing Sinaliza que a síntese de fala está em andamento. Esse evento é acionado sempre que o SDK recebe um trecho de áudio do Serviço de Fala. Você pode confirmar quando a síntese está em andamento.
VisemeReceived Sinaliza que um evento de visema foi recebido. Os visemas são usados geralmente para representar as principais poses na fala observada. As principais poses incluem a posição dos lábios, do maxilar e da língua na produção de um fonema específico. Você pode usar visemas para animar o rosto de um personagem conforme o áudio da fala é reproduzido.
WordBoundary Sinaliza que um limite de palavra foi recebido. Esse evento é gerado no início de cada nova palavra falada, pontuação ou frase. O evento relata a diferença de tempo da palavra atual, em tiques, desde o início do áudio de saída. Esse evento também relata a posição do caractere no texto de entrada ou SSML imediatamente antes da palavra que está prestes a ser falada. Esse evento geralmente é usado para obter posições relativas do texto e do áudio correspondente. Talvez você queira saber sobre uma nova palavra e, em seguida, tomar medidas com base no tempo. Por exemplo, você pode obter informações que podem ajudar a decidir quando e por quanto tempo realçar as palavras conforme elas são faladas.

Observação

Os eventos são gerados à medida que os dados de áudio de saída ficam disponíveis, o que é mais rápido do que a reprodução em um dispositivo de saída. O chamador deve sincronizar adequadamente o streaming e o tempo real.

Aqui está um exemplo que mostra como assinar eventos para síntese de fala.

Importante

Se você usar uma chave de API, armazene-a com segurança em outro lugar, como no Azure Key Vault. Não inclua a chave da API diretamente no seu código e nunca a publique publicamente.

Para obter mais informações sobre a segurança dos serviços de IA, confira Autenticar solicitações para serviços de IA do Azure.

Você pode seguir as instruções no início rápido, mas substitua o conteúdo do arquivo speech-synthesis.py pelo código Python a seguir:

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?")

Você pode encontrar mais amostras de conversão de texto em fala no GitHub.

Usar um ponto de extremidade personalizado

O ponto de extremidade personalizado é funcionalmente idêntico ao ponto de extremidade padrão usado para solicitações de conversão de texto em fala.

Uma diferença é que o endpoint_id deve ser especificado para usar a voz personalizada por meio do SDK de Fala. Você pode começar com o início rápido da conversão de texto em fala e, em seguida, atualizar o código com endpoint_id e o 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"

Para usar uma voz neural personalizada por meio de Speech Synthesis Markup Language (SSML), especifique o nome do modelo como o nome da voz. Este exemplo usa a voz YourCustomVoiceName.

<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>

Executar e usar um contêiner

Os contêineres de Fala fornecem APIs de ponto de extremidade de consulta baseadas em websocket que são acessadas através do SDK de Fala e da CLI de Fala. Por padrão, o SDK de Fala e a CLI de Fala usam o serviço público de Fala. Para usar o contêiner, você precisa alterar o método de inicialização. Use uma URL de host de contêiner em vez de chave e região.

Para obter mais informações sobre os contêineres, consulte Instalar e executar contêineres de Fala com o Docker.

Referência da API REST de Conversão de fala em texto | API REST de fala em texto para breve referência de áudio | Exemplos adicionais no GitHub

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Pré-requisitos

  • Uma assinatura do Azure. É possível criar uma gratuitamente.
  • Criar um recurso de Fala no portal do Azure.
  • Obter a região e a chave do recurso para Fala. Depois que o recurso de Fala for implantado, selecione Ir para o recurso para exibir e gerenciar as chaves.

Converter texto em fala

No prompt de comando, execute o comando a seguir. Insira esses valores no comando:

  • Sua chave do recurso de Fala
  • Sua região do recurso de Fala

Talvez também seja interessante alterar os valores a seguir:

  • O valor do cabeçalho X-Microsoft-OutputFormat, que controla o formato de saída de áudio. Você pode encontrar uma lista de formatos de saída de áudio com suporte na referência da API REST de conversão de texto em fala.
  • A voz de saída. Para obter uma lista de vozes disponíveis para seu ponto de extremidade do serviço de Fala, confira a API da lista de vozes.
  • O arquivo de saída. Neste exemplo, direcionamos a resposta do servidor para um arquivo chamado 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

Neste guia de instruções, você aprende os padrões de design comuns para fazer uma síntese da conversão de texto em fala.

Para obter mais informações sobre as seguintes áreas, consulte O que é a conversão de texto em fala?

  • Obter respostas como fluxos na memória.
  • Personalizar a taxa de bits e a taxa de amostragem de saída.
  • Enviar solicitações de sintetização usando SSML (linguagem de marcação de sintetização de fala).
  • Usar vozes neurais.
  • Assinar eventos e atuar nos resultados.

Pré-requisitos

  • Uma assinatura do Azure. É possível criar uma gratuitamente.
  • Criar um recurso de Fala no portal do Azure.
  • Obter a região e a chave do recurso para Fala. Depois que o recurso de Fala for implantado, selecione Ir para o recurso para exibir e gerenciar as chaves.

Baixar e instalar

Siga estas etapas e consulte o início rápido da CLI de Fala para obter outros requisitos para sua plataforma.

  1. Execute o seguinte comando da CLI do .NET para instalar a CLI de Fala:

    dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
    
  2. Execute os comandos a seguir para configurar a chave e a região do recurso Fala. Substitua SUBSCRIPTION-KEY pela sua chave do recurso de Fala e substitua REGION pela sua região do recurso de Fala.

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

Sintetizar uma fala em um alto-falante

Agora você está pronto para executar a CLI de Fala para sintetizar a fala de um texto.

  • Na janela do console, altere para o diretório que contém o arquivo binário da CLI de Fala. Em seguida, execute o seguinte comando:

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

A CLI de Fala produz o idioma natural em inglês por meio do alto-falante do computador.

Sintetizar fala em um arquivo

  • Execute o comando a seguir para alterar a saída do seu alto-falante para um arquivo .wav:

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

A CLI de Fala produz o idioma natural em inglês no arquivo para o arquivo de áudio greetings.wav.

Executar e usar um contêiner

Os contêineres de Fala fornecem APIs de ponto de extremidade de consulta baseadas em websocket que são acessadas através do SDK de Fala e da CLI de Fala. Por padrão, o SDK de Fala e a CLI de Fala usam o serviço público de Fala. Para usar o contêiner, você precisa alterar o método de inicialização. Use uma URL de host de contêiner em vez de chave e região.

Para obter mais informações sobre os contêineres, consulte Instalar e executar contêineres de Fala com o Docker.

Próximas etapas