Cara mensintesis ucapan dari teks

Dokumentasi referensi | Paket (NuGet) | Sampel Tambahan pada GitHub

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Memilih bahasa dan suara sintesis

Fitur teks ke ucapan dalam layanan Ucapan mendukung lebih dari 400 suara dan lebih dari 140 bahasa dan varian. Anda bisa mendapatkan daftar lengkap atau mencobanya di Galeri Suara.

Tentukan bahasa atau suara SpeechConfig untuk mencocokkan teks input Anda dan gunakan suara yang ditentukan. Cuplikan kode berikut menunjukkan cara kerja teknik ini:

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

Semua suara saraf multibahasa dan fasih dalam bahasa dan bahasa Inggris mereka sendiri. Misalnya, jika teks input dalam bahasa Inggris, adalah "Saya senang mencoba teks ke ucapan," dan Anda memilih es-ES-ElviraNeural, teks diucapkan dalam bahasa Inggris dengan aksen Spanyol.

Jika suara tidak berbicara bahasa teks input, layanan Ucapan tidak membuat audio yang disintesis. Untuk daftar lengkap suara saraf yang didukung, lihat Dukungan bahasa dan suara untuk layanan Ucapan.

Catatan

Suara default adalah suara pertama yang dikembalikan per lokal dari API Daftar Suara.

Suara yang berbicara ditentukan dalam urutan prioritas sebagai berikut:

  • Jika Anda tidak mengatur SpeechSynthesisVoiceName atau SpeechSynthesisLanguage, suara default untuk en-US berbicara.
  • Jika Anda hanya mengatur SpeechSynthesisLanguage, suara default untuk lokal yang ditentukan akan berbicara.
  • Jika keduanya SpeechSynthesisVoiceName dan SpeechSynthesisLanguage diatur, SpeechSynthesisLanguage pengaturan diabaikan. Suara yang Anda tentukan dengan menggunakan SpeechSynthesisVoiceName ucapan.
  • Jika elemen suara diatur dengan menggunakan Speech Synthesis Markup Language (SSML), SpeechSynthesisVoiceName pengaturan dan SpeechSynthesisLanguage akan diabaikan.

Mensintesis ucapan ke file

Buat objek SpeechSynthesizer . Objek ini ditampilkan dalam cuplikan berikut menjalankan konversi teks ke ucapan dan output ke speaker, file, atau aliran output lainnya. SpeechSynthesizer menerima sebagai parameter:

  • Objek SpeechConfig yang Anda buat di langkah sebelumnya.
  • Objek AudioConfig yang menentukan bagaimana hasil output harus ditangani.
  1. Buat AudioConfig instans untuk menulis output secara otomatis ke file .wav dengan menggunakan FromWavFileOutput() fungsi . Instanskan dengan pernyataan using.

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

    Pernyataan using dalam konteks ini secara otomatis membuang sumber daya yang tidak dikelola dan menyebabkan objek keluar dari cakupan setelah dibuang.

  2. SpeechSynthesizer Buat instans dengan pernyataan lainusing. Teruskan objek speechConfig Anda dan objek audioConfig sebagai parameter. Untuk mensintesis ucapan dan menulis ke file, jalankan SpeakTextAsync() dengan string teks.

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

Saat Anda menjalankan program, program akan membuat file .wav yang disintesis, yang ditulis ke lokasi yang Anda tentukan. Hasil ini adalah contoh yang baik dari penggunaan yang paling mendasar. Selanjutnya, Anda dapat menyesuaikan output dan menangani respons output sebagai aliran dalam memori untuk bekerja dengan skenario kustom.

Mensintesis ke output speaker

Untuk menghasilkan ucapan yang disintesis ke perangkat output aktif saat ini seperti speaker, hilangkan AudioConfig parameter saat Anda membuat SpeechSynthesizer instans. Berikut contohnya:

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

Dapatkan hasil sebagai aliran dalam memori

Anda dapat menggunakan data audio yang dihasilkan sebagai aliran dalam memori daripada langsung menulis ke file. Dengan aliran dalam memori, Anda dapat membangun perilaku kustom:

  • Mengacak array byte yang dihasilkan sebagai aliran yang dapat dicari untuk layanan downstream kustom.
  • Mengintegrasi hasilnya dengan API atau layanan lain.
  • Ubah data audio, tulis header .wav kustom, dan lakukan tugas terkait.

Anda dapat membuat perubahan ini ke contoh sebelumnya. Pertama, hapus AudioConfig blok, karena Anda mengelola perilaku output secara manual dari titik ini dan seterusnya untuk peningkatan kontrol. Teruskan null untuk AudioConfig di SpeechSynthesizer konstruktor.

Catatan

Meneruskan null untuk AudioConfig, daripada menghilangkannya seperti dalam contoh output speaker sebelumnya, tidak memutar audio secara default pada perangkat output aktif saat ini.

Simpan hasilnya ke variabel SpeechSynthesisResult . Properti AudioData berisi instans byte [] untuk data output. Anda dapat bekerja dengan instans ini byte [] secara manual, atau Anda dapat menggunakan kelas AudioDataStream untuk mengelola aliran dalam memori.

Pada contoh berikut, Anda menggunakan fungsi statik AudioDataStream.FromResult() untuk mendapatkan aliran dari hasilnya:

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

Pada titik ini, Anda dapat menerapkan perilaku kustom apa pun dengan menggunakan objek yang stream dihasilkan.

Menyesuaikan format audio

Anda dapat menyesuaikan atribut output audio, termasuk:

  • Jenis file audio
  • Tingkat sampel
  • Kedalaman bit

Untuk mengubah format audio, Anda menggunakan fungsi SetSpeechSynthesisOutputFormat() pada objek SpeechConfig. Fungsi ini mengharapkan instans enum jenis SpeechSynthesisOutputFormat. enum Gunakan untuk memilih format output. Untuk format yang tersedia, lihat daftar format audio.

Ada berbagai opsi untuk berbagai jenis file tergantung pada kebutuhan Anda. Menurut definisi, format mentah seperti Raw24Khz16BitMonoPcm tidak menyertakan header audio. Gunakan format mentah hanya dalam salah satu situasi ini:

  • Anda tahu bahwa implementasi downstream Anda dapat memecahkan kode bitstream mentah.
  • Anda berencana untuk membuat header secara manual berdasarkan faktor-faktor seperti kedalaman bit, laju sampel, dan jumlah saluran.

Contoh ini menentukan format Riff24Khz16BitMonoPcm RIFF dengan fidelitas tinggi dengan mengatur SpeechSynthesisOutputFormat pada SpeechConfig objek. Mirip dengan contoh di bagian sebelumnya, Anda menggunakan AudioDataStream untuk mendapatkan aliran hasil dalam memori, lalu menulisnya ke file.

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

Ketika Anda menjalankan program, ia menulis file .wav ke jalur yang ditentukan.

Menggunakan SSML untuk menyesuaikan karakteristik ucapan

Anda dapat menggunakan SSML untuk menyempurnakan nada, pengucapan, laju bicara, volume, dan aspek lain dalam output teks ke ucapan dengan mengirimkan permintaan Anda dari skema XML. Sesi ini menunjukkan contoh mengubah suara. Untuk informasi selengkapnya, lihat Gambaran umum Bahasa Markup Sintesis Ucapan.

Untuk mulai menggunakan SSML untuk kustomisasi, Anda membuat perubahan kecil yang mengalihkan suara.

  1. Buat file XML baru untuk konfigurasi SSML di direktori proyek akar Anda.

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

    Dalam contoh ini, file ssml.xml. Elemen root selalu <speak>. Membungkus teks dalam elemen <voice> memungkinkan Anda untuk mengubah suara menggunakan parameter name. Untuk daftar lengkap suara saraf yang didukung, lihat Bahasa yang didukung.

  2. Ubah permintaan sintesis ucapan untuk mereferensikan file XML Anda. Permintaan tersebut pada dasarnya sama, tetapi alih-alih menggunakan fungsi SpeakTextAsync(), Anda menggunakan SpeakSsmlAsync(). Fungsi ini mengharapkan string XML. Pertama, muat konfigurasi SSML Anda sebagai string dengan menggunakan File.ReadAllText(). Dari titik ini, objek hasil sama persis dengan contoh sebelumnya.

    Catatan

    Jika Anda menggunakan Visual Studio, konfigurasi build Anda kemungkinan tidak akan menemukan file XML secara default. Klik kanan file XML dan pilih Properti. Ubah Tindakan Build menjadi Konten. Ubah Salin ke Direktori Output menjadi Salin selalu.

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

Catatan

Untuk mengubah suara tanpa menggunakan SSML, Anda dapat mengatur properti pada SpeechConfig menggunakan SpeechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

Berlangganan peristiwa synthesizer

Anda mungkin menginginkan lebih banyak wawasan tentang pemrosesan dan hasil teks ke ucapan. Misalnya, Anda mungkin ingin tahu kapan synthesizer dimulai dan berhenti, atau Anda mungkin ingin tahu tentang peristiwa lain yang ditemui selama sintesis.

Saat menggunakan SpeechSynthesizer untuk teks ke ucapan, Anda dapat berlangganan peristiwa dalam tabel ini:

Kejadian Deskripsi Gunakan huruf besar
BookmarkReached Sinyal bahwa marka buku tercapai. Untuk memicu peristiwa yang dicapai bookmark, bookmark elemen diperlukan di SSML. Kejadian ini melaporkan waktu audio output yang berlalu antara awal sintesis dan bookmark elemen . Properti peristiwa Text adalah nilai string yang Anda tetapkan di atribut bookmark mark . Elemen bookmark tidak diucapkan. Anda dapat menggunakan elemen bookmark untuk menyisipkan penanda kustom dalam SSML agar dapat mendapatkan keseimbangan setiap penanda di stream audio. Elemen bookmark dapat digunakan untuk mereferensikan lokasi tertentu dalam urutan teks atau tag.
SynthesisCanceled Sinyal bahwa sintesis ucapan dibatalkan. Anda dapat mengonfirmasi kapan sintesis dibatalkan.
SynthesisCompleted Sinyal bahwa sintesis ucapan selesai. Anda dapat mengonfirmasi kapan sintesis selesai.
SynthesisStarted Sinyal bahwa sintesis ucapan dimulai. Anda dapat mengonfirmasi kapan sintesis dimulai.
Synthesizing Sinyal bahwa sintesis ucapan sedang berlangsung. Kejadian ini diaktifkan setiap kali SDK menerima gugus audio dari layanan Ucapan. Anda dapat mengonfirmasi kapan sintesis sedang berlangsung.
VisemeReceived Sinyal bahwa peristiwa viseme diterima. Visemes sering digunakan untuk mewakili pose kunci dalam pidato yang diamati. Pose utama termasuk posisi bibir, rahang, dan lidah dalam memproduksi fonem tertentu. Anda dapat menggunakan viseme untuk menganimasikan wajah karakter saat audio ucapan diputar.
WordBoundary Memberi sinyal bahwa batas kata diterima. Peristiwa ini dimunculkan di awal setiap kata, tanda baca, dan kalimat lisan baru. Peristiwa melaporkan offset waktu kata saat ini, dalam tanda centang, dari awal audio output. Kejadian ini juga melaporkan posisi karakter dalam teks input atau SSML segera sebelum kata yang akan diucapkan. Kejadian ini biasanya digunakan untuk mendapatkan posisi relatif teks dan audio yang sesuai. Anda mungkin ingin tahu tentang kata baru, lalu mengambil tindakan berdasarkan waktu. Misalnya, Anda bisa mendapatkan informasi yang dapat membantu Anda memutuskan kapan dan berapa lama untuk menyoroti kata-kata saat diucapkan.

Catatan

Peristiwa dinaikkan saat data audio output tersedia, yang lebih cepat daripada pemutaran ke perangkat output. Pemanggil harus menyinkronkan streaming dan real-time dengan tepat.

Berikut adalah contoh yang menunjukkan cara berlangganan peristiwa untuk sintesis ucapan. Anda dapat mengikuti instruksi dalam mulai cepat, tetapi mengganti konten file Program.cs tersebut dengan kode C# berikut:

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

Anda dapat menemukan lebih banyak sampel teks ke ucapan di GitHub.

Menggunakan titik akhir kustom

Titik akhir kustom secara fungsional identik dengan titik akhir standar yang digunakan untuk permintaan teks ke ucapan.

Salah satu perbedaannya adalah harus EndpointId ditentukan untuk menggunakan suara kustom Anda melalui Speech SDK. Anda dapat memulai dengan mulai cepat teks ke ucapan lalu memperbarui kode dengan EndpointId dan SpeechSynthesisVoiceName.

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

Untuk menggunakan suara kustom melalui Speech Synthesis Markup Language (SSML), tentukan nama model sebagai nama suara. Contoh ini menggunakan YourCustomVoiceNamesuara.

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

Menjalankan dan menggunakan kontainer

Kontainer ucapan menyediakan API titik akhir kueri berbasis websocket yang diakses melalui Speech SDK dan Speech CLI. Secara default, Speech SDK dan Speech CLI menggunakan layanan Ucapan publik. Untuk menggunakan kontainer, Anda perlu mengubah metode inisialisasi. Gunakan URL host kontainer alih-alih kunci dan wilayah.

Untuk informasi selengkapnya tentang kontainer, lihat Menginstal dan menjalankan kontainer Ucapan dengan Docker.

Dokumentasi referensi | Paket (NuGet) | Sampel Tambahan pada GitHub

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Memilih bahasa dan suara sintesis

Fitur teks ke ucapan dalam layanan Ucapan mendukung lebih dari 400 suara dan lebih dari 140 bahasa dan varian. Lihat daftar lengkap teks yang didukung ke lokal ucapan atau coba di Galeri Suara.

Tentukan bahasa atau suara kelas SpeechConfig agar sesuai dengan teks input Anda dan gunakan suara yang ditentukan. Cuplikan kode berikut menunjukkan cara kerja teknik ini:

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

Semua suara saraf multibahasa dan fasih dalam bahasa dan bahasa Inggris mereka sendiri. Misalnya, jika teks input dalam bahasa Inggris adalah, "Saya senang mencoba teks ke ucapan," dan Anda memilih es-ES-ElviraNeural, teks diucapkan dalam bahasa Inggris dengan aksen Spanyol.

Jika suara tidak berbicara bahasa teks input, layanan Ucapan tidak membuat audio yang disintesis. Untuk daftar lengkap suara saraf yang didukung, lihat Dukungan bahasa dan suara untuk layanan Ucapan.

Catatan

Suara default adalah suara pertama yang dikembalikan per lokal dari API Daftar Suara.

Suara yang berbicara ditentukan dalam urutan prioritas sebagai berikut:

  • Jika Anda tidak mengatur SpeechSynthesisVoiceName atau SpeechSynthesisLanguage, suara default untuk en-US berbicara.
  • Jika Anda hanya mengatur SpeechSynthesisLanguage, suara default untuk lokal yang ditentukan akan berbicara.
  • Jika keduanya SpeechSynthesisVoiceName dan SpeechSynthesisLanguage diatur, SpeechSynthesisLanguage pengaturan diabaikan. Suara yang Anda tentukan dengan menggunakan SpeechSynthesisVoiceName ucapan.
  • Jika elemen suara diatur dengan menggunakan Speech Synthesis Markup Language (SSML), SpeechSynthesisVoiceName pengaturan dan SpeechSynthesisLanguage akan diabaikan.

Mensintesis ucapan ke file

Buat objek SpeechSynthesizer . Objek ini ditampilkan dalam cuplikan berikut menjalankan konversi teks ke ucapan dan output ke speaker, file, atau aliran output lainnya. SpeechSynthesizer menerima sebagai parameter:

  • Objek SpeechConfig yang Anda buat di langkah sebelumnya.
  • Objek AudioConfig yang menentukan bagaimana hasil output harus ditangani.
  1. Buat AudioConfig instans untuk menulis output secara otomatis ke file .wav dengan menggunakan FromWavFileOutput() fungsi :

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
    }
    
  2. SpeechSynthesizer Membuat instans instans. Teruskan objek speechConfig Anda dan objek audioConfig sebagai parameter. Untuk mensintesis ucapan dan menulis ke file, jalankan SpeakTextAsync() dengan string teks.

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

Saat Anda menjalankan program, program akan membuat file .wav yang disintesis, yang ditulis ke lokasi yang Anda tentukan. Hasil ini adalah contoh yang baik dari penggunaan yang paling mendasar. Selanjutnya, Anda dapat menyesuaikan output dan menangani respons output sebagai aliran dalam memori untuk bekerja dengan skenario kustom.

Mensintesis ke output speaker

Untuk menghasilkan ucapan yang disintesis ke perangkat output aktif saat ini seperti speaker, hilangkan AudioConfig parameter saat Anda membuat SpeechSynthesizer instans. Berikut contohnya:

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

Dapatkan hasil sebagai aliran dalam memori

Anda dapat menggunakan data audio yang dihasilkan sebagai aliran dalam memori daripada langsung menulis ke file. Dengan aliran dalam memori, Anda dapat membangun perilaku kustom:

  • Mengacak array byte yang dihasilkan sebagai aliran yang dapat dicari untuk layanan downstream kustom.
  • Mengintegrasi hasilnya dengan API atau layanan lain.
  • Ubah data audio, tulis header .wav kustom, dan lakukan tugas terkait.

Anda dapat membuat perubahan ini ke contoh sebelumnya. Pertama, hapus AudioConfig blok, karena Anda mengelola perilaku output secara manual dari titik ini dan seterusnya untuk peningkatan kontrol. Teruskan NULL untuk AudioConfig di SpeechSynthesizer konstruktor.

Catatan

Meneruskan NULL untuk AudioConfig, daripada menghilangkannya seperti dalam contoh output speaker sebelumnya, tidak memutar audio secara default pada perangkat output aktif saat ini.

Simpan hasilnya ke variabel SpeechSynthesisResult . Getter GetAudioData mengembalikan instans byte [] untuk data output. Anda dapat bekerja dengan instans ini byte [] secara manual, atau Anda dapat menggunakan kelas AudioDataStream untuk mengelola aliran dalam memori.

Dalam contoh ini, gunakan AudioDataStream.FromResult() fungsi statis untuk mendapatkan aliran dari hasilnya:

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

Pada titik ini, Anda dapat menerapkan perilaku kustom apa pun dengan menggunakan objek yang stream dihasilkan.

Menyesuaikan format audio

Anda dapat menyesuaikan atribut output audio, termasuk:

  • Jenis file audio
  • Tingkat sampel
  • Kedalaman bit

Untuk mengubah format audio, gunakan SetSpeechSynthesisOutputFormat() fungsi pada SpeechConfig objek. Fungsi ini mengharapkan instans enum jenis SpeechSynthesisOutputFormat. enum Gunakan untuk memilih format output. Untuk format yang tersedia, lihat daftar format audio.

Ada berbagai opsi untuk berbagai jenis file tergantung pada kebutuhan Anda. Menurut definisi, format mentah seperti Raw24Khz16BitMonoPcm tidak menyertakan header audio. Gunakan format mentah hanya dalam salah satu situasi ini:

  • Anda tahu bahwa implementasi downstream Anda dapat memecahkan kode bitstream mentah.
  • Anda berencana untuk membuat header secara manual berdasarkan faktor-faktor seperti kedalaman bit, laju sampel, dan jumlah saluran.

Contoh ini menentukan format Riff24Khz16BitMonoPcm RIFF dengan fidelitas tinggi dengan mengatur SpeechSynthesisOutputFormat pada SpeechConfig objek. Mirip dengan contoh di bagian sebelumnya, Anda menggunakan AudioDataStream untuk mendapatkan aliran dalam memori dari hasil, lalu menulisnya ke file.

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

Ketika Anda menjalankan program, ia menulis file .wav ke jalur yang ditentukan.

Menggunakan SSML untuk menyesuaikan karakteristik ucapan

Anda dapat menggunakan SSML untuk menyempurnakan nada, pengucapan, laju bicara, volume, dan aspek lain dalam output teks ke ucapan dengan mengirimkan permintaan Anda dari skema XML. Sesi ini menunjukkan contoh mengubah suara. Untuk informasi selengkapnya, lihat Gambaran umum Bahasa Markup Sintesis Ucapan.

Untuk mulai menggunakan SSML untuk kustomisasi, buat perubahan kecil yang mengalihkan suara.

  1. Buat file XML baru untuk konfigurasi SSML di direktori proyek akar Anda.

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

    Dalam contoh ini, file ssml.xml. Elemen root selalu <speak>. Membungkus teks dalam elemen <voice> memungkinkan Anda untuk mengubah suara menggunakan parameter name. Untuk daftar lengkap suara saraf yang didukung, lihat Bahasa yang didukung.

  2. Ubah permintaan sintesis ucapan untuk mereferensikan file XML Anda. Permintaan sebagian besar sama. Alih-alih menggunakan SpeakTextAsync() fungsi , Anda menggunakan SpeakSsmlAsync(). Fungsi ini mengharapkan string XML. Pertama, muat konfigurasi SSML Anda sebagai string. Dari titik ini, objek hasil sama persis dengan contoh sebelumnya.

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

Catatan

Untuk mengubah suara tanpa menggunakan SSML, Anda dapat mengatur properti pada SpeechConfig menggunakan SpeechConfig.SetSpeechSynthesisVoiceName("en-US-AndrewMultilingualNeural").

Berlangganan peristiwa synthesizer

Anda mungkin menginginkan lebih banyak wawasan tentang pemrosesan dan hasil teks ke ucapan. Misalnya, Anda mungkin ingin tahu kapan synthesizer dimulai dan berhenti, atau Anda mungkin ingin tahu tentang peristiwa lain yang ditemui selama sintesis.

Saat menggunakan SpeechSynthesizer untuk teks ke ucapan, Anda dapat berlangganan peristiwa dalam tabel ini:

Kejadian Deskripsi Gunakan huruf besar
BookmarkReached Sinyal bahwa marka buku tercapai. Untuk memicu peristiwa yang dicapai bookmark, bookmark elemen diperlukan di SSML. Kejadian ini melaporkan waktu audio output yang berlalu antara awal sintesis dan bookmark elemen . Properti peristiwa Text adalah nilai string yang Anda tetapkan di atribut bookmark mark . Elemen bookmark tidak diucapkan. Anda dapat menggunakan elemen bookmark untuk menyisipkan penanda kustom dalam SSML agar dapat mendapatkan keseimbangan setiap penanda di stream audio. Elemen bookmark dapat digunakan untuk mereferensikan lokasi tertentu dalam urutan teks atau tag.
SynthesisCanceled Sinyal bahwa sintesis ucapan dibatalkan. Anda dapat mengonfirmasi kapan sintesis dibatalkan.
SynthesisCompleted Sinyal bahwa sintesis ucapan selesai. Anda dapat mengonfirmasi kapan sintesis selesai.
SynthesisStarted Sinyal bahwa sintesis ucapan dimulai. Anda dapat mengonfirmasi kapan sintesis dimulai.
Synthesizing Sinyal bahwa sintesis ucapan sedang berlangsung. Kejadian ini diaktifkan setiap kali SDK menerima gugus audio dari layanan Ucapan. Anda dapat mengonfirmasi kapan sintesis sedang berlangsung.
VisemeReceived Sinyal bahwa peristiwa viseme diterima. Visemes sering digunakan untuk mewakili pose kunci dalam pidato yang diamati. Pose utama termasuk posisi bibir, rahang, dan lidah dalam memproduksi fonem tertentu. Anda dapat menggunakan viseme untuk menganimasikan wajah karakter saat audio ucapan diputar.
WordBoundary Memberi sinyal bahwa batas kata diterima. Peristiwa ini dimunculkan di awal setiap kata, tanda baca, dan kalimat lisan baru. Peristiwa melaporkan offset waktu kata saat ini, dalam tanda centang, dari awal audio output. Kejadian ini juga melaporkan posisi karakter dalam teks input atau SSML segera sebelum kata yang akan diucapkan. Kejadian ini biasanya digunakan untuk mendapatkan posisi relatif teks dan audio yang sesuai. Anda mungkin ingin tahu tentang kata baru, lalu mengambil tindakan berdasarkan waktu. Misalnya, Anda bisa mendapatkan informasi yang dapat membantu Anda memutuskan kapan dan berapa lama untuk menyoroti kata-kata saat diucapkan.

Catatan

Peristiwa dinaikkan saat data audio output tersedia, yang lebih cepat daripada pemutaran ke perangkat output. Pemanggil harus menyinkronkan streaming dan real-time dengan tepat.

Berikut adalah contoh yang menunjukkan cara berlangganan peristiwa untuk sintesis ucapan. Anda dapat mengikuti instruksi dalam mulai cepat, tetapi mengganti konten file main.cpp tersebut dengan kode berikut:

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

Anda dapat menemukan lebih banyak sampel teks ke ucapan di GitHub.

Menggunakan titik akhir kustom

Titik akhir kustom secara fungsional identik dengan titik akhir standar yang digunakan untuk permintaan teks ke ucapan.

Salah satu perbedaannya adalah harus EndpointId ditentukan untuk menggunakan suara kustom Anda melalui Speech SDK. Anda dapat memulai dengan mulai cepat teks ke ucapan lalu memperbarui kode dengan EndpointId dan SpeechSynthesisVoiceName.

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

Untuk menggunakan suara kustom melalui Speech Synthesis Markup Language (SSML), tentukan nama model sebagai nama suara. Contoh ini menggunakan YourCustomVoiceNamesuara.

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

Menjalankan dan menggunakan kontainer

Kontainer ucapan menyediakan API titik akhir kueri berbasis websocket yang diakses melalui Speech SDK dan Speech CLI. Secara default, Speech SDK dan Speech CLI menggunakan layanan Ucapan publik. Untuk menggunakan kontainer, Anda perlu mengubah metode inisialisasi. Gunakan URL host kontainer alih-alih kunci dan wilayah.

Untuk informasi selengkapnya tentang kontainer, lihat Menginstal dan menjalankan kontainer Ucapan dengan Docker.

Dokumentasi referensi | Paket (Go) | Sampel Tambahan pada GitHub

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Prasyarat

  • Langganan Azure - Buat langganan gratis.
  • Buat sumber daya Ucapan di portal Azure.
  • Kunci dan wilayah sumber daya Ucapan Anda. Setelah sumber daya Azure Cognitive Service untuk Ucapan Anda disebarkan, pilih Buka sumber daya untuk melihat dan mengelola kunci. Untuk informasi selengkapnya tentang sumber daya layanan Azure AI, lihat Mendapatkan kunci untuk sumber daya Anda.

Menginstal SDK Ucapan

Sebelum Anda dapat tindakan apa pun, Anda harus menginstal Speech SDK untuk Go.

Teks ke ucapan ke pembicara

Gunakan contoh kode berikut untuk menjalankan sintesis ucapan ke perangkat output audio default Anda. Ganti variabel subscription dan region dengan kunci ucapan dan lokasi/wilayah Anda. Menjalankan skrip mengucapkan teks input Anda ke speaker default.

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

Jalankan perintah berikut untuk membuat file go.mod yang menautkan ke komponen yang dihosting di GitHub:

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

Sekarang, bangun dan jalankan kode:

go build
go run quickstart

Untuk informasi terperinci tentang kelas, lihat dokumen referensi SpeechConfig dan SpeechSynthesizer.

Teks ke ucapan ke aliran dalam memori

Anda dapat menggunakan data audio yang dihasilkan sebagai aliran dalam memori daripada langsung menulis ke file. Dengan aliran dalam memori, Anda dapat membangun perilaku kustom:

  • Mengacak array byte yang dihasilkan sebagai aliran yang dapat dicari untuk layanan downstream kustom.
  • Mengintegrasi hasilnya dengan API atau layanan lain.
  • Ubah data audio, tulis header .wav kustom, dan lakukan tugas terkait.

Anda dapat membuat perubahan ini ke contoh sebelumnya. AudioConfig Hapus blok, karena Anda mengelola perilaku output secara manual dari titik ini dan seterusnya untuk peningkatan kontrol. Kemudian teruskan nil untuk AudioConfig pada konstruktor SpeechSynthesizer.

Catatan

Meneruskan nil untuk AudioConfig, daripada menghilangkannya seperti dalam contoh output speaker di atas, tidak akan memutar audio secara default pada perangkat output yang aktif saat ini.

Simpan hasilnya ke SpeechSynthesisResult variabel. Properti AudioData menghasilkan instans []byte untuk data output. Anda dapat bekerja dengan instans []byte secara manual, atau Anda dapat menggunakan kelas AudioDataStream untuk mengelola aliran dalam memori. Pada contoh berikut, Anda menggunakan fungsi statis NewAudioDataStreamFromSpeechSynthesisResult() untuk mendapatkan streaming dari hasilnya.

Ganti variabel subscription dan region dengan kunci ucapan dan lokasi/wilayah Anda:

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

Jalankan perintah berikut untuk membuat file go.mod yang menautkan ke komponen yang dihosting di GitHub:

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

Sekarang, bangun dan jalankan kode:

go build
go run quickstart

Untuk informasi terperinci tentang kelas, lihat dokumen referensi SpeechConfig dan SpeechSynthesizer.

Memilih bahasa dan suara sintesis

Fitur teks ke ucapan dalam layanan Ucapan mendukung lebih dari 400 suara dan lebih dari 140 bahasa dan varian. Anda bisa mendapatkan daftar lengkap atau mencobanya di Galeri Suara.

Tentukan bahasa atau suara SpeechConfig untuk mencocokkan teks input Anda dan gunakan suara yang ditentukan:

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

Semua suara saraf multibahasa dan fasih dalam bahasa dan bahasa Inggris mereka sendiri. Misalnya, jika teks input dalam bahasa Inggris adalah, "Saya senang mencoba teks ke ucapan," dan Anda memilih es-ES-ElviraNeural, teks diucapkan dalam bahasa Inggris dengan aksen Spanyol.

Jika suara tidak berbicara bahasa teks input, layanan Ucapan tidak membuat audio yang disintesis. Untuk daftar lengkap suara saraf yang didukung, lihat Dukungan bahasa dan suara untuk layanan Ucapan.

Catatan

Suara default adalah suara pertama yang dikembalikan per lokal dari API Daftar Suara.

Suara yang berbicara ditentukan dalam urutan prioritas sebagai berikut:

  • Jika Anda tidak mengatur SpeechSynthesisVoiceName atau SpeechSynthesisLanguage, suara default untuk en-US berbicara.
  • Jika Anda hanya mengatur SpeechSynthesisLanguage, suara default untuk lokal yang ditentukan akan berbicara.
  • Jika keduanya SpeechSynthesisVoiceName dan SpeechSynthesisLanguage diatur, SpeechSynthesisLanguage pengaturan diabaikan. Suara yang Anda tentukan dengan menggunakan SpeechSynthesisVoiceName ucapan.
  • Jika elemen suara diatur dengan menggunakan Speech Synthesis Markup Language (SSML), SpeechSynthesisVoiceName pengaturan dan SpeechSynthesisLanguage akan diabaikan.

Menggunakan SSML untuk menyesuaikan karakteristik ucapan

Anda dapat menggunakan Speech Synthesis Markup Language (SSML) untuk menyempurnakan nada, pengucapan, laju bicara, volume, dan lainnya dalam output teks ke ucapan dengan mengirimkan permintaan Anda dari skema XML. Sesi ini menunjukkan contoh mengubah suara. Untuk informasi selengkapnya, lihat Gambaran umum Bahasa Markup Sintesis Ucapan.

Untuk mulai menggunakan SSML untuk kustomisasi, Anda membuat perubahan kecil yang mengalihkan suara.

Pertama, buat file XML baru untuk konfigurasi SSML di direktori proyek root Anda. Contohnya, ssml.xml. Elemen root selalu <speak>. Membungkus teks dalam elemen <voice> memungkinkan Anda untuk mengubah suara menggunakan parameter name. Untuk daftar lengkap suara saraf yang didukung, lihat Bahasa yang didukung.

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

Selanjutnya, Anda perlu mengubah permintaan sintesis ucapan untuk mereferensikan file XML Anda. Permintaan tersebut pada dasarnya sama, tetapi alih-alih menggunakan fungsi SpeakTextAsync(), Anda menggunakan SpeakSsmlAsync(). Fungsi ini mengharapkan string XML, sehingga pertama-tama Anda memuat konfigurasi SSML sebagai string. Dari titik ini, objek hasil sama persis dengan contoh sebelumnya.

Catatan

Untuk mengatur suara tanpa menggunakan SSML, Anda dapat mengatur properti pada SpeechConfig menggunakan speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural").

Berlangganan peristiwa synthesizer

Anda mungkin menginginkan lebih banyak wawasan tentang pemrosesan dan hasil teks ke ucapan. Misalnya, Anda mungkin ingin tahu kapan synthesizer dimulai dan berhenti, atau Anda mungkin ingin tahu tentang peristiwa lain yang ditemui selama sintesis.

Saat menggunakan SpeechSynthesizer untuk teks ke ucapan, Anda dapat berlangganan peristiwa dalam tabel ini:

Kejadian Deskripsi Gunakan huruf besar
BookmarkReached Sinyal bahwa marka buku tercapai. Untuk memicu peristiwa yang dicapai bookmark, bookmark elemen diperlukan di SSML. Kejadian ini melaporkan waktu audio output yang berlalu antara awal sintesis dan bookmark elemen . Properti peristiwa Text adalah nilai string yang Anda tetapkan di atribut bookmark mark . Elemen bookmark tidak diucapkan. Anda dapat menggunakan elemen bookmark untuk menyisipkan penanda kustom dalam SSML agar dapat mendapatkan keseimbangan setiap penanda di stream audio. Elemen bookmark dapat digunakan untuk mereferensikan lokasi tertentu dalam urutan teks atau tag.
SynthesisCanceled Sinyal bahwa sintesis ucapan dibatalkan. Anda dapat mengonfirmasi kapan sintesis dibatalkan.
SynthesisCompleted Sinyal bahwa sintesis ucapan selesai. Anda dapat mengonfirmasi kapan sintesis selesai.
SynthesisStarted Sinyal bahwa sintesis ucapan dimulai. Anda dapat mengonfirmasi kapan sintesis dimulai.
Synthesizing Sinyal bahwa sintesis ucapan sedang berlangsung. Kejadian ini diaktifkan setiap kali SDK menerima gugus audio dari layanan Ucapan. Anda dapat mengonfirmasi kapan sintesis sedang berlangsung.
VisemeReceived Sinyal bahwa peristiwa viseme diterima. Visemes sering digunakan untuk mewakili pose kunci dalam pidato yang diamati. Pose utama termasuk posisi bibir, rahang, dan lidah dalam memproduksi fonem tertentu. Anda dapat menggunakan viseme untuk menganimasikan wajah karakter saat audio ucapan diputar.
WordBoundary Memberi sinyal bahwa batas kata diterima. Peristiwa ini dimunculkan di awal setiap kata, tanda baca, dan kalimat lisan baru. Peristiwa melaporkan offset waktu kata saat ini, dalam tanda centang, dari awal audio output. Kejadian ini juga melaporkan posisi karakter dalam teks input atau SSML segera sebelum kata yang akan diucapkan. Kejadian ini biasanya digunakan untuk mendapatkan posisi relatif teks dan audio yang sesuai. Anda mungkin ingin tahu tentang kata baru, lalu mengambil tindakan berdasarkan waktu. Misalnya, Anda bisa mendapatkan informasi yang dapat membantu Anda memutuskan kapan dan berapa lama untuk menyoroti kata-kata saat diucapkan.

Catatan

Peristiwa dinaikkan saat data audio output tersedia, yang lebih cepat daripada pemutaran ke perangkat output. Pemanggil harus menyinkronkan streaming dan real-time dengan tepat.

Berikut adalah contoh yang menunjukkan cara berlangganan peristiwa untuk sintesis ucapan. Anda dapat mengikuti instruksi dalam mulai cepat, tetapi mengganti konten speech-synthesis.go file tersebut dengan kode Go berikut:

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

Anda dapat menemukan lebih banyak sampel teks ke ucapan di GitHub.

Menjalankan dan menggunakan kontainer

Kontainer ucapan menyediakan API titik akhir kueri berbasis websocket yang diakses melalui Speech SDK dan Speech CLI. Secara default, Speech SDK dan Speech CLI menggunakan layanan Ucapan publik. Untuk menggunakan kontainer, Anda perlu mengubah metode inisialisasi. Gunakan URL host kontainer alih-alih kunci dan wilayah.

Untuk informasi selengkapnya tentang kontainer, lihat Menginstal dan menjalankan kontainer Ucapan dengan Docker.

Dokumentasi referensi | Sampel Tambahan pada GitHub

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Memilih bahasa dan suara sintesis

Fitur teks ke ucapan dalam layanan Ucapan mendukung lebih dari 400 suara dan lebih dari 140 bahasa dan varian. Anda bisa mendapatkan daftar lengkap atau mencobanya di Galeri Suara.

Tentukan bahasa atau suara SpeechConfig agar sesuai dengan teks input Anda dan gunakan suara yang ditentukan. Cuplikan kode berikut menunjukkan cara kerja teknik ini:

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

Semua suara saraf multibahasa dan fasih dalam bahasa dan bahasa Inggris mereka sendiri. Misalnya, jika teks input dalam bahasa Inggris adalah, "Saya senang mencoba teks ke ucapan," dan Anda memilih es-ES-ElviraNeural, teks diucapkan dalam bahasa Inggris dengan aksen Spanyol.

Jika suara tidak berbicara bahasa teks input, layanan Ucapan tidak membuat audio yang disintesis. Untuk daftar lengkap suara saraf yang didukung, lihat Dukungan bahasa dan suara untuk layanan Ucapan.

Catatan

Suara default adalah suara pertama yang dikembalikan per lokal dari API Daftar Suara.

Suara yang berbicara ditentukan dalam urutan prioritas sebagai berikut:

  • Jika Anda tidak mengatur SpeechSynthesisVoiceName atau SpeechSynthesisLanguage, suara default untuk en-US berbicara.
  • Jika Anda hanya mengatur SpeechSynthesisLanguage, suara default untuk lokal yang ditentukan akan berbicara.
  • Jika keduanya SpeechSynthesisVoiceName dan SpeechSynthesisLanguage diatur, SpeechSynthesisLanguage pengaturan diabaikan. Suara yang Anda tentukan dengan menggunakan SpeechSynthesisVoiceName ucapan.
  • Jika elemen suara diatur dengan menggunakan Speech Synthesis Markup Language (SSML), SpeechSynthesisVoiceName pengaturan dan SpeechSynthesisLanguage akan diabaikan.

Mensintesis ucapan ke file

Buat objek SpeechSynthesizer. Objek ini menjalankan konversi teks ke ucapan dan output ke speaker, file, atau aliran output lainnya. SpeechSynthesizer menerima sebagai parameter:

  • Objek SpeechConfig yang Anda buat di langkah sebelumnya.
  • Objek AudioConfig yang menentukan bagaimana hasil output harus ditangani.
  1. AudioConfig Buat instans untuk menulis output secara otomatis ke file .wav dengan menggunakan fromWavFileOutput() fungsi statis:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    }
    
  2. SpeechSynthesizer Membuat instans instans. Teruskan objek speechConfig Anda dan objek audioConfig sebagai parameter. Untuk mensintesis ucapan dan menulis ke file, jalankan SpeakText() dengan string teks.

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

Saat Anda menjalankan program, program akan membuat file .wav yang disintesis, yang ditulis ke lokasi yang Anda tentukan. Hasil ini adalah contoh yang baik dari penggunaan yang paling mendasar. Selanjutnya, Anda dapat menyesuaikan output dan menangani respons output sebagai aliran dalam memori untuk bekerja dengan skenario kustom.

Mensintesis ke output speaker

Anda mungkin menginginkan lebih banyak wawasan tentang pemrosesan dan hasil teks ke ucapan. Misalnya, Anda mungkin ingin tahu kapan synthesizer dimulai dan berhenti, atau Anda mungkin ingin tahu tentang peristiwa lain yang ditemui selama sintesis.

Untuk menghasilkan ucapan yang disintesis ke perangkat output aktif saat ini seperti speaker, buat instans AudioConfig dengan menggunakan fromDefaultSpeakerOutput() fungsi statis. Berikut contohnya:

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

Dapatkan hasil sebagai aliran dalam memori

Anda dapat menggunakan data audio yang dihasilkan sebagai aliran dalam memori daripada langsung menulis ke file. Dengan aliran dalam memori, Anda dapat membangun perilaku kustom:

  • Mengacak array byte yang dihasilkan sebagai aliran yang dapat dicari untuk layanan downstream kustom.
  • Mengintegrasi hasilnya dengan API atau layanan lain.
  • Ubah data audio, tulis header .wav kustom, dan lakukan tugas terkait.

Anda dapat membuat perubahan ini ke contoh sebelumnya. Pertama, hapus AudioConfig blok, karena Anda mengelola perilaku output secara manual dari titik ini dan seterusnya untuk peningkatan kontrol. Kemudian teruskan null untuk AudioConfig pada konstruktor SpeechSynthesizer.

Catatan

Meneruskan null untuk AudioConfig, daripada menghilangkannya seperti yang Anda lakukan dalam contoh output speaker sebelumnya, tidak memutar audio secara default pada perangkat output aktif saat ini.

Simpan hasilnya ke SpeechSynthesisResult variabel. Fungsi SpeechSynthesisResult.getAudioData() menghasilkan instans byte [] ke data output. Anda dapat bekerja dengan instans byte [] secara manual, atau Anda dapat menggunakan kelas AudioDataStream untuk mengelola aliran dalam memori.

Dalam contoh ini, gunakan AudioDataStream.fromResult() fungsi statis untuk mendapatkan aliran dari hasilnya:

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

Pada titik ini, Anda dapat menerapkan perilaku kustom apa pun dengan menggunakan objek yang stream dihasilkan.

Menyesuaikan format audio

Anda dapat menyesuaikan atribut output audio, termasuk:

  • Jenis file audio
  • Tingkat sampel
  • Kedalaman bit

Untuk mengubah format audio, Anda menggunakan fungsi setSpeechSynthesisOutputFormat() pada objek SpeechConfig. Fungsi ini mengharapkan instans enum jenis SpeechSynthesisOutputFormat. enum Gunakan untuk memilih format output. Untuk format yang tersedia, lihat daftar format audio.

Ada berbagai opsi untuk berbagai jenis file tergantung pada kebutuhan Anda. Menurut definisi, format mentah seperti Raw24Khz16BitMonoPcm tidak menyertakan header audio. Gunakan format mentah hanya dalam salah satu situasi ini:

  • Anda tahu bahwa implementasi downstream Anda dapat memecahkan kode bitstream mentah.
  • Anda berencana untuk membuat header secara manual berdasarkan faktor-faktor seperti kedalaman bit, laju sampel, dan jumlah saluran.

Contoh ini menentukan format Riff24Khz16BitMonoPcm RIFF dengan fidelitas tinggi dengan mengatur SpeechSynthesisOutputFormat pada SpeechConfig objek. Mirip dengan contoh di bagian sebelumnya, Anda menggunakan AudioDataStream untuk mendapatkan aliran dalam memori dari hasil, lalu menulisnya ke file.

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

Ketika Anda menjalankan program, ia menulis file .wav ke jalur yang ditentukan.

Menggunakan SSML untuk menyesuaikan karakteristik ucapan

Anda dapat menggunakan SSML untuk menyempurnakan nada, pengucapan, laju bicara, volume, dan aspek lain dalam output teks ke ucapan dengan mengirimkan permintaan Anda dari skema XML. Sesi ini menunjukkan contoh mengubah suara. Untuk informasi selengkapnya, lihat artikel panduan SSML.

Untuk mulai menggunakan SSML untuk kustomisasi, Anda membuat perubahan kecil yang mengalihkan suara.

  1. Buat file XML baru untuk konfigurasi SSML di direktori proyek akar Anda.

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

    Dalam contoh ini, file ssml.xml. Elemen root selalu <speak>. Membungkus teks dalam elemen <voice> memungkinkan Anda untuk mengubah suara menggunakan parameter name. Untuk daftar lengkap suara saraf yang didukung, lihat Bahasa yang didukung.

  2. Ubah permintaan sintesis ucapan untuk mereferensikan file XML Anda. Permintaan sebagian besar sama. Alih-alih menggunakan SpeakText() fungsi , Anda menggunakan SpeakSsml(). Fungsi ini mengharapkan string XML, jadi pertama-tama buat fungsi untuk memuat file XML dan mengembalikannya sebagai string:

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

    Pada titik ini, objek hasil sama persis dengan contoh sebelumnya:

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

Catatan

Untuk mengubah suara tanpa menggunakan SSML, atur properti SpeechConfig dengan menggunakan SpeechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");.

Berlangganan peristiwa synthesizer

Anda mungkin menginginkan lebih banyak wawasan tentang pemrosesan dan hasil teks ke ucapan. Misalnya, Anda mungkin ingin tahu kapan synthesizer dimulai dan berhenti, atau Anda mungkin ingin tahu tentang peristiwa lain yang ditemui selama sintesis.

Saat menggunakan SpeechSynthesizer untuk teks ke ucapan, Anda dapat berlangganan peristiwa dalam tabel ini:

Kejadian Deskripsi Gunakan huruf besar
BookmarkReached Sinyal bahwa marka buku tercapai. Untuk memicu peristiwa yang dicapai bookmark, bookmark elemen diperlukan di SSML. Kejadian ini melaporkan waktu audio output yang berlalu antara awal sintesis dan bookmark elemen . Properti peristiwa Text adalah nilai string yang Anda tetapkan di atribut bookmark mark . Elemen bookmark tidak diucapkan. Anda dapat menggunakan elemen bookmark untuk menyisipkan penanda kustom dalam SSML agar dapat mendapatkan keseimbangan setiap penanda di stream audio. Elemen bookmark dapat digunakan untuk mereferensikan lokasi tertentu dalam urutan teks atau tag.
SynthesisCanceled Sinyal bahwa sintesis ucapan dibatalkan. Anda dapat mengonfirmasi kapan sintesis dibatalkan.
SynthesisCompleted Sinyal bahwa sintesis ucapan selesai. Anda dapat mengonfirmasi kapan sintesis selesai.
SynthesisStarted Sinyal bahwa sintesis ucapan dimulai. Anda dapat mengonfirmasi kapan sintesis dimulai.
Synthesizing Sinyal bahwa sintesis ucapan sedang berlangsung. Kejadian ini diaktifkan setiap kali SDK menerima gugus audio dari layanan Ucapan. Anda dapat mengonfirmasi kapan sintesis sedang berlangsung.
VisemeReceived Sinyal bahwa peristiwa viseme diterima. Visemes sering digunakan untuk mewakili pose kunci dalam pidato yang diamati. Pose utama termasuk posisi bibir, rahang, dan lidah dalam memproduksi fonem tertentu. Anda dapat menggunakan viseme untuk menganimasikan wajah karakter saat audio ucapan diputar.
WordBoundary Memberi sinyal bahwa batas kata diterima. Peristiwa ini dimunculkan di awal setiap kata, tanda baca, dan kalimat lisan baru. Peristiwa melaporkan offset waktu kata saat ini, dalam tanda centang, dari awal audio output. Kejadian ini juga melaporkan posisi karakter dalam teks input atau SSML segera sebelum kata yang akan diucapkan. Kejadian ini biasanya digunakan untuk mendapatkan posisi relatif teks dan audio yang sesuai. Anda mungkin ingin tahu tentang kata baru, lalu mengambil tindakan berdasarkan waktu. Misalnya, Anda bisa mendapatkan informasi yang dapat membantu Anda memutuskan kapan dan berapa lama untuk menyoroti kata-kata saat diucapkan.

Catatan

Peristiwa dinaikkan saat data audio output tersedia, yang lebih cepat daripada pemutaran ke perangkat output. Pemanggil harus menyinkronkan streaming dan real-time dengan tepat.

Berikut adalah contoh yang menunjukkan cara berlangganan peristiwa untuk sintesis ucapan. Anda dapat mengikuti instruksi dalam mulai cepat, tetapi mengganti konten file SpeechSynthesis.java tersebut dengan kode Java berikut:

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

Anda dapat menemukan lebih banyak sampel teks ke ucapan di GitHub.

Menggunakan titik akhir kustom

Titik akhir kustom secara fungsional identik dengan titik akhir standar yang digunakan untuk permintaan teks ke ucapan.

Salah satu perbedaannya adalah harus EndpointId ditentukan untuk menggunakan suara kustom Anda melalui Speech SDK. Anda dapat memulai dengan mulai cepat teks ke ucapan lalu memperbarui kode dengan EndpointId dan SpeechSynthesisVoiceName.

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

Untuk menggunakan suara kustom melalui Speech Synthesis Markup Language (SSML), tentukan nama model sebagai nama suara. Contoh ini menggunakan YourCustomVoiceNamesuara.

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

Menjalankan dan menggunakan kontainer

Kontainer ucapan menyediakan API titik akhir kueri berbasis websocket yang diakses melalui Speech SDK dan Speech CLI. Secara default, Speech SDK dan Speech CLI menggunakan layanan Ucapan publik. Untuk menggunakan kontainer, Anda perlu mengubah metode inisialisasi. Gunakan URL host kontainer alih-alih kunci dan wilayah.

Untuk informasi selengkapnya tentang kontainer, lihat Menginstal dan menjalankan kontainer Ucapan dengan Docker.

Dokumentasi referensi | Paket (npm) | Sampel Tambahan pada kode sumber GitHub | Library

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Memilih bahasa dan suara sintesis

Fitur teks ke ucapan dalam layanan Ucapan mendukung lebih dari 400 suara dan lebih dari 140 bahasa dan varian. Anda bisa mendapatkan daftar lengkap atau mencobanya di Galeri Suara.

Tentukan bahasa atau suara SpeechConfig untuk mencocokkan teks input Anda dan gunakan suara yang ditentukan:

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

Semua suara saraf multibahasa dan fasih dalam bahasa dan bahasa Inggris mereka sendiri. Misalnya, jika teks input dalam bahasa Inggris adalah, "Saya senang mencoba teks ke ucapan," dan Anda memilih es-ES-ElviraNeural, teks diucapkan dalam bahasa Inggris dengan aksen Spanyol.

Jika suara tidak berbicara bahasa teks input, layanan Ucapan tidak membuat audio yang disintesis. Untuk daftar lengkap suara saraf yang didukung, lihat Dukungan bahasa dan suara untuk layanan Ucapan.

Catatan

Suara default adalah suara pertama yang dikembalikan per lokal dari API Daftar Suara.

Suara yang berbicara ditentukan dalam urutan prioritas sebagai berikut:

  • Jika Anda tidak mengatur SpeechSynthesisVoiceName atau SpeechSynthesisLanguage, suara default untuk en-US berbicara.
  • Jika Anda hanya mengatur SpeechSynthesisLanguage, suara default untuk lokal yang ditentukan akan berbicara.
  • Jika keduanya SpeechSynthesisVoiceName dan SpeechSynthesisLanguage diatur, SpeechSynthesisLanguage pengaturan diabaikan. Suara yang Anda tentukan dengan menggunakan SpeechSynthesisVoiceName ucapan.
  • Jika elemen suara diatur dengan menggunakan Speech Synthesis Markup Language (SSML), SpeechSynthesisVoiceName pengaturan dan SpeechSynthesisLanguage akan diabaikan.

Mensintesis teks ke ucapan

Untuk menghasilkan ucapan yang disintesis ke perangkat output aktif saat ini seperti speaker, buat instans AudioConfig dengan menggunakan fromDefaultSpeakerOutput() fungsi statis. Berikut contohnya:

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

Saat Anda menjalankan program, audio yang disintesis diputar dari speaker. Hasil ini adalah contoh yang baik dari penggunaan yang paling mendasar. Selanjutnya, Anda dapat menyesuaikan output dan menangani respons output sebagai aliran dalam memori untuk bekerja dengan skenario kustom.

Dapatkan hasil sebagai aliran dalam memori

Anda dapat menggunakan data audio yang dihasilkan sebagai aliran dalam memori daripada langsung menulis ke file. Dengan aliran dalam memori, Anda dapat membangun perilaku kustom:

  • Mengacak array byte yang dihasilkan sebagai aliran yang dapat dicari untuk layanan downstream kustom.
  • Mengintegrasi hasilnya dengan API atau layanan lain.
  • Ubah data audio, tulis header kustom .wav, dan lakukan tugas terkait.

Anda dapat membuat perubahan ini ke contoh sebelumnya. AudioConfig Hapus blok, karena Anda mengelola perilaku output secara manual dari titik ini dan seterusnya untuk peningkatan kontrol. Kemudian teruskan null untuk AudioConfig pada konstruktor SpeechSynthesizer.

Catatan

Meneruskan null untuk AudioConfig, daripada menghilangkannya seperti yang Anda lakukan dalam contoh output speaker sebelumnya, tidak memutar audio secara default pada perangkat output aktif saat ini.

Simpan hasilnya ke variabel SpeechSynthesisResult . Properti SpeechSynthesisResult.audioData mengembalikan ArrayBuffer dari data output, jenis aliran browser default. Untuk kode sisi server, konversi ArrayBuffer ke aliran buffer.

Kode berikut berfungsi untuk sisi klien:

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

Anda dapat menerapkan perilaku kustom apa pun dengan menggunakan objek yang ArrayBuffer dihasilkan. ArrayBuffer adalah jenis umum yang diterima di browser dan diputar dari format ini.

Untuk kode berbasis server apa pun, jika Anda perlu bekerja dengan data sebagai stream, Anda perlu mengonversi objek ArrayBuffer menjadi stream:

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

Menyesuaikan format audio

Anda dapat menyesuaikan atribut output audio, termasuk:

  • Jenis file audio
  • Tingkat sampel
  • Kedalaman bit

Untuk mengubah format audio, gunakan speechSynthesisOutputFormat properti pada SpeechConfig objek . Properti ini mengharapkan instans enum jenis SpeechSynthesisOutputFormat. enum Gunakan untuk memilih format output. Untuk format yang tersedia, lihat daftar format audio.

Ada berbagai opsi untuk berbagai jenis file tergantung pada kebutuhan Anda. Menurut definisi, format mentah seperti Raw24Khz16BitMonoPcm tidak menyertakan header audio. Gunakan format mentah hanya dalam salah satu situasi ini:

  • Anda tahu bahwa implementasi downstream Anda dapat memecahkan kode bitstream mentah.
  • Anda berencana untuk membuat header secara manual berdasarkan faktor-faktor seperti kedalaman bit, laju sampel, dan jumlah saluran.

Contoh ini menentukan format Riff24Khz16BitMonoPcm RIFF dengan fidelitas tinggi dengan mengatur speechSynthesisOutputFormat pada SpeechConfig objek. Mirip dengan contoh di bagian sebelumnya, dapatkan data ArrayBuffer audio dan berinteraksi dengannya.

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

Menggunakan SSML untuk menyesuaikan karakteristik ucapan

Anda dapat menggunakan SSML untuk menyempurnakan nada, pengucapan, laju bicara, volume, dan aspek lain dalam output teks ke ucapan dengan mengirimkan permintaan Anda dari skema XML. Sesi ini menunjukkan contoh mengubah suara. Untuk informasi selengkapnya, lihat Gambaran umum Bahasa Markup Sintesis Ucapan.

Untuk mulai menggunakan SSML untuk kustomisasi, Anda membuat perubahan kecil yang mengalihkan suara.

  1. Buat file XML baru untuk konfigurasi SSML di direktori proyek akar Anda.

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

    Dalam contoh ini, ssml.xml. Elemen root selalu <speak>. Membungkus teks dalam elemen <voice> memungkinkan Anda untuk mengubah suara menggunakan parameter name. Untuk daftar lengkap suara saraf yang didukung, lihat Bahasa yang didukung.

  2. Ubah permintaan sintesis ucapan untuk mereferensikan file XML Anda. Permintaan tersebut pada dasarnya sama, tetapi alih-alih menggunakan fungsi speakTextAsync(), Anda menggunakan speakSsmlAsync(). Fungsi ini mengharapkan string XML. Buat fungsi untuk memuat file XML dan mengembalikannya sebagai string:

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

    Untuk informasi selengkapnya tentang readFileSync, lihat sistem file Node.js.

    Objek hasil sama persis dengan contoh sebelumnya:

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

Catatan

Untuk mengubah suara tanpa menggunakan SSML, Anda dapat mengatur properti pada SpeechConfig menggunakan SpeechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

Berlangganan peristiwa synthesizer

Anda mungkin menginginkan lebih banyak wawasan tentang pemrosesan dan hasil teks ke ucapan. Misalnya, Anda mungkin ingin tahu kapan synthesizer dimulai dan berhenti, atau Anda mungkin ingin tahu tentang peristiwa lain yang ditemui selama sintesis.

Saat menggunakan SpeechSynthesizer untuk teks ke ucapan, Anda dapat berlangganan peristiwa dalam tabel ini:

Kejadian Deskripsi Gunakan huruf besar
BookmarkReached Sinyal bahwa marka buku tercapai. Untuk memicu peristiwa yang dicapai bookmark, bookmark elemen diperlukan di SSML. Kejadian ini melaporkan waktu audio output yang berlalu antara awal sintesis dan bookmark elemen . Properti peristiwa Text adalah nilai string yang Anda tetapkan di atribut bookmark mark . Elemen bookmark tidak diucapkan. Anda dapat menggunakan elemen bookmark untuk menyisipkan penanda kustom dalam SSML agar dapat mendapatkan keseimbangan setiap penanda di stream audio. Elemen bookmark dapat digunakan untuk mereferensikan lokasi tertentu dalam urutan teks atau tag.
SynthesisCanceled Sinyal bahwa sintesis ucapan dibatalkan. Anda dapat mengonfirmasi kapan sintesis dibatalkan.
SynthesisCompleted Sinyal bahwa sintesis ucapan selesai. Anda dapat mengonfirmasi kapan sintesis selesai.
SynthesisStarted Sinyal bahwa sintesis ucapan dimulai. Anda dapat mengonfirmasi kapan sintesis dimulai.
Synthesizing Sinyal bahwa sintesis ucapan sedang berlangsung. Kejadian ini diaktifkan setiap kali SDK menerima gugus audio dari layanan Ucapan. Anda dapat mengonfirmasi kapan sintesis sedang berlangsung.
VisemeReceived Sinyal bahwa peristiwa viseme diterima. Visemes sering digunakan untuk mewakili pose kunci dalam pidato yang diamati. Pose utama termasuk posisi bibir, rahang, dan lidah dalam memproduksi fonem tertentu. Anda dapat menggunakan viseme untuk menganimasikan wajah karakter saat audio ucapan diputar.
WordBoundary Memberi sinyal bahwa batas kata diterima. Peristiwa ini dimunculkan di awal setiap kata, tanda baca, dan kalimat lisan baru. Peristiwa melaporkan offset waktu kata saat ini, dalam tanda centang, dari awal audio output. Kejadian ini juga melaporkan posisi karakter dalam teks input atau SSML segera sebelum kata yang akan diucapkan. Kejadian ini biasanya digunakan untuk mendapatkan posisi relatif teks dan audio yang sesuai. Anda mungkin ingin tahu tentang kata baru, lalu mengambil tindakan berdasarkan waktu. Misalnya, Anda bisa mendapatkan informasi yang dapat membantu Anda memutuskan kapan dan berapa lama untuk menyoroti kata-kata saat diucapkan.

Catatan

Peristiwa dinaikkan saat data audio output tersedia, yang lebih cepat daripada pemutaran ke perangkat output. Pemanggil harus menyinkronkan streaming dan real-time dengan tepat.

Berikut adalah contoh yang menunjukkan cara berlangganan peristiwa untuk sintesis ucapan. Anda dapat mengikuti instruksi dalam mulai cepat, tetapi mengganti konten file SpeechSynthesis.js tersebut dengan kode JavaScript berikut.

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

Anda dapat menemukan lebih banyak sampel teks ke ucapan di GitHub.

Menjalankan dan menggunakan kontainer

Kontainer ucapan menyediakan API titik akhir kueri berbasis websocket yang diakses melalui Speech SDK dan Speech CLI. Secara default, Speech SDK dan Speech CLI menggunakan layanan Ucapan publik. Untuk menggunakan kontainer, Anda perlu mengubah metode inisialisasi. Gunakan URL host kontainer alih-alih kunci dan wilayah.

Untuk informasi selengkapnya tentang kontainer, lihat Menginstal dan menjalankan kontainer Ucapan dengan Docker.

Dokumentasi referensi | Paket (Unduh) | Sampel Tambahan pada GitHub

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Prasyarat

  • Langganan Azure - Buat langganan gratis.
  • Buat sumber daya Ucapan di portal Azure.
  • Kunci dan wilayah sumber daya Ucapan Anda. Setelah sumber daya Azure Cognitive Service untuk Ucapan Anda disebarkan, pilih Buka sumber daya untuk melihat dan mengelola kunci. Untuk informasi selengkapnya tentang sumber daya layanan Azure AI, lihat Mendapatkan kunci untuk sumber daya Anda.

Memasang sampel dan SDK Speech

Repository Azure-Samples/cognitive-services-speech-sdk mengandung sampel tertulis dalam Objective-C untuk iOS dan Mac. Klik link untuk melihat instruksi penginstalan untuk setiap sampel:

Menggunakan titik akhir kustom

Titik akhir kustom secara fungsional identik dengan titik akhir standar yang digunakan untuk permintaan teks ke ucapan.

Salah satu perbedaannya adalah harus EndpointId ditentukan untuk menggunakan suara kustom Anda melalui Speech SDK. Anda dapat memulai dengan mulai cepat teks ke ucapan lalu memperbarui kode dengan EndpointId dan SpeechSynthesisVoiceName.

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

Untuk menggunakan suara kustom melalui Speech Synthesis Markup Language (SSML), tentukan nama model sebagai nama suara. Contoh ini menggunakan YourCustomVoiceNamesuara.

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

Menjalankan dan menggunakan kontainer

Kontainer ucapan menyediakan API titik akhir kueri berbasis websocket yang diakses melalui Speech SDK dan Speech CLI. Secara default, Speech SDK dan Speech CLI menggunakan layanan Ucapan publik. Untuk menggunakan kontainer, Anda perlu mengubah metode inisialisasi. Gunakan URL host kontainer alih-alih kunci dan wilayah.

Untuk informasi selengkapnya tentang kontainer, lihat Menginstal dan menjalankan kontainer Ucapan dengan Docker.

Dokumentasi referensi | Paket (Unduh) | Sampel Tambahan pada GitHub

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Prasyarat

  • Langganan Azure - Buat langganan gratis.
  • Buat sumber daya Ucapan di portal Azure.
  • Kunci dan wilayah sumber daya Ucapan Anda. Setelah sumber daya Azure Cognitive Service untuk Ucapan Anda disebarkan, pilih Buka sumber daya untuk melihat dan mengelola kunci. Untuk informasi selengkapnya tentang sumber daya layanan Azure AI, lihat Mendapatkan kunci untuk sumber daya Anda.

Memasang sampel dan SDK Speech

Repositori Azure-Samples/cognitive-services-speech-sdk mengandung sampel yang tertulis dalam Swift untuk iOS dan Mac. Klik link untuk melihat instruksi penginstalan untuk setiap sampel:

Menjalankan dan menggunakan kontainer

Kontainer ucapan menyediakan API titik akhir kueri berbasis websocket yang diakses melalui Speech SDK dan Speech CLI. Secara default, Speech SDK dan Speech CLI menggunakan layanan Ucapan publik. Untuk menggunakan kontainer, Anda perlu mengubah metode inisialisasi. Gunakan URL host kontainer alih-alih kunci dan wilayah.

Untuk informasi selengkapnya tentang kontainer, lihat Menginstal dan menjalankan kontainer Ucapan dengan Docker.

Dokumentasi referensi | Paket (PyPi) | Sampel Tambahan pada GitHub

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Memilih bahasa dan suara sintesis

Fitur teks ke ucapan dalam layanan Ucapan mendukung lebih dari 400 suara dan lebih dari 140 bahasa dan varian. Anda bisa mendapatkan daftar lengkap atau mencobanya di Galeri Suara.

Tentukan bahasa atau suara SpeechConfig untuk mencocokkan teks input Anda dan gunakan suara yang ditentukan:

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

Semua suara saraf multibahasa dan fasih dalam bahasa dan bahasa Inggris mereka sendiri. Misalnya, jika teks input dalam bahasa Inggris adalah, "Saya senang mencoba teks ke ucapan," dan Anda memilih es-ES-ElviraNeural, teks diucapkan dalam bahasa Inggris dengan aksen Spanyol.

Jika suara tidak berbicara bahasa teks input, layanan Ucapan tidak membuat audio yang disintesis. Untuk daftar lengkap suara saraf yang didukung, lihat Dukungan bahasa dan suara untuk layanan Ucapan.

Catatan

Suara default adalah suara pertama yang dikembalikan per lokal dari API Daftar Suara.

Suara yang berbicara ditentukan dalam urutan prioritas sebagai berikut:

  • Jika Anda tidak mengatur SpeechSynthesisVoiceName atau SpeechSynthesisLanguage, suara default untuk en-US berbicara.
  • Jika Anda hanya mengatur SpeechSynthesisLanguage, suara default untuk lokal yang ditentukan akan berbicara.
  • Jika keduanya SpeechSynthesisVoiceName dan SpeechSynthesisLanguage diatur, SpeechSynthesisLanguage pengaturan diabaikan. Suara yang Anda tentukan dengan menggunakan SpeechSynthesisVoiceName ucapan.
  • Jika elemen suara diatur dengan menggunakan Speech Synthesis Markup Language (SSML), SpeechSynthesisVoiceName pengaturan dan SpeechSynthesisLanguage akan diabaikan.

Mensintesis ucapan ke file

Buat objek SpeechSynthesizer . Objek ini menjalankan konversi teks ke ucapan dan output ke speaker, file, atau aliran output lainnya. SpeechSynthesizer menerima sebagai parameter:

  1. AudioOutputConfig Buat instans untuk menulis output secara otomatis ke file .wav dengan menggunakan filename parameter konstruktor:

    audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
    
  2. SpeechSynthesizer Buat instans dengan meneruskan objek Anda speech_config dan audio_config objek sebagai parameter. Untuk mensintesis ucapan dan menulis ke file, jalankan speak_text_async() dengan string teks.

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

Saat Anda menjalankan program, program akan membuat file .wav yang disintesis, yang ditulis ke lokasi yang Anda tentukan. Hasil ini adalah contoh yang baik dari penggunaan yang paling mendasar. Selanjutnya, Anda dapat menyesuaikan output dan menangani respons output sebagai aliran dalam memori untuk bekerja dengan skenario kustom.

Mensintesis ke output speaker

Untuk menghasilkan ucapan yang disintesis ke perangkat output aktif saat ini seperti speaker, atur use_default_speaker parameter saat Anda membuat AudioOutputConfig instans. Berikut contohnya:

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

Dapatkan hasil sebagai aliran dalam memori

Anda dapat menggunakan data audio yang dihasilkan sebagai aliran dalam memori daripada langsung menulis ke file. Dengan aliran dalam memori, Anda dapat membangun perilaku kustom:

  • Mengacak array byte yang dihasilkan sebagai aliran yang dapat dicari untuk layanan downstream kustom.
  • Mengintegrasi hasilnya dengan API atau layanan lain.
  • Ubah data audio, tulis header .wav kustom, dan lakukan tugas terkait.

Anda dapat membuat perubahan ini ke contoh sebelumnya. Pertama, hapus AudioConfig, karena Anda mengelola perilaku output secara manual dari titik ini dan seterusnya untuk peningkatan kontrol. Teruskan None untuk AudioConfig di SpeechSynthesizer konstruktor.

Catatan

Meneruskan None untuk AudioConfig, daripada menghilangkannya seperti yang Anda lakukan dalam contoh output speaker sebelumnya, tidak memutar audio secara default pada perangkat output aktif saat ini.

Simpan hasilnya ke SpeechSynthesisResult variabel. Properti audio_data berisi objek bytes data output. Anda dapat bekerja dengan objek ini secara manual, atau Anda dapat menggunakan kelas AudioDataStream untuk mengelola aliran dalam memori.

Dalam contoh ini, gunakan AudioDataStream konstruktor untuk mendapatkan aliran dari hasilnya:

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

Pada titik ini, Anda dapat menerapkan perilaku kustom apa pun dengan menggunakan objek yang stream dihasilkan.

Menyesuaikan format audio

Anda dapat menyesuaikan atribut output audio, termasuk:

  • Jenis file audio
  • Tingkat sampel
  • Kedalaman bit

Untuk mengubah format audio, gunakan set_speech_synthesis_output_format() fungsi pada SpeechConfig objek. Fungsi ini mengharapkan instans enum jenis SpeechSynthesisOutputFormat. enum Gunakan untuk memilih format output. Untuk format yang tersedia, lihat daftar format audio.

Ada berbagai opsi untuk berbagai jenis file tergantung pada kebutuhan Anda. Menurut definisi, format mentah seperti Raw24Khz16BitMonoPcm tidak menyertakan header audio. Gunakan format mentah hanya dalam salah satu situasi ini:

  • Anda tahu bahwa implementasi downstream Anda dapat memecahkan kode bitstream mentah.
  • Anda berencana untuk membuat header secara manual berdasarkan faktor-faktor seperti kedalaman bit, laju sampel, dan jumlah saluran.

Contoh ini menentukan format Riff24Khz16BitMonoPcm RIFF dengan fidelitas tinggi dengan mengatur SpeechSynthesisOutputFormat pada SpeechConfig objek. Mirip dengan contoh di bagian sebelumnya, Anda menggunakan AudioDataStream untuk mendapatkan aliran dalam memori dari hasil, lalu menulisnya ke file.

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

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

Ketika Anda menjalankan program, ia menulis file .wav ke jalur yang ditentukan.

Menggunakan SSML untuk menyesuaikan karakteristik ucapan

Anda dapat menggunakan SSML untuk menyempurnakan nada, pengucapan, laju bicara, volume, dan aspek lain dalam output teks ke ucapan dengan mengirimkan permintaan Anda dari skema XML. Sesi ini menunjukkan contoh mengubah suara. Untuk informasi selengkapnya, lihat Gambaran umum Bahasa Markup Sintesis Ucapan.

Untuk mulai menggunakan SSML untuk kustomisasi, buat perubahan kecil yang mengalihkan suara.

  1. Buat file XML baru untuk konfigurasi SSML di direktori proyek akar Anda.

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

    Dalam contoh ini, file ssml.xml. Elemen root selalu <speak>. Membungkus teks dalam elemen <voice> memungkinkan Anda untuk mengubah suara menggunakan parameter name. Untuk daftar lengkap suara saraf yang didukung, lihat Bahasa yang didukung.

  2. Ubah permintaan sintesis ucapan untuk mereferensikan file XML Anda. Permintaan sebagian besar sama. Alih-alih menggunakan speak_text_async() fungsi , gunakan speak_ssml_async(). Fungsi ini mengharapkan string XML. Pertama-tama baca konfigurasi SSML Anda sebagai string. Dari titik ini, objek hasil sama persis dengan contoh sebelumnya.

    Catatan

    Jika ssml_string Anda berisi  di awal string, Anda perlu menanggalkan format BOM atau layanan akan mengembalikan kesalahan. Anda melakukan ini dengan mengatur parameter encoding sebagai berikut: open("ssml.xml", "r", encoding="utf-8-sig").

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

Catatan

Untuk mengubah suara tanpa menggunakan SSML, Anda dapat mengatur properti pada SpeechConfig menggunakan speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural".

Berlangganan peristiwa synthesizer

Anda mungkin menginginkan lebih banyak wawasan tentang pemrosesan dan hasil teks ke ucapan. Misalnya, Anda mungkin ingin tahu kapan synthesizer dimulai dan berhenti, atau Anda mungkin ingin tahu tentang peristiwa lain yang ditemui selama sintesis.

Saat menggunakan SpeechSynthesizer untuk teks ke ucapan, Anda dapat berlangganan peristiwa dalam tabel ini:

Kejadian Deskripsi Gunakan huruf besar
BookmarkReached Sinyal bahwa marka buku tercapai. Untuk memicu peristiwa yang dicapai bookmark, bookmark elemen diperlukan di SSML. Kejadian ini melaporkan waktu audio output yang berlalu antara awal sintesis dan bookmark elemen . Properti peristiwa Text adalah nilai string yang Anda tetapkan di atribut bookmark mark . Elemen bookmark tidak diucapkan. Anda dapat menggunakan elemen bookmark untuk menyisipkan penanda kustom dalam SSML agar dapat mendapatkan keseimbangan setiap penanda di stream audio. Elemen bookmark dapat digunakan untuk mereferensikan lokasi tertentu dalam urutan teks atau tag.
SynthesisCanceled Sinyal bahwa sintesis ucapan dibatalkan. Anda dapat mengonfirmasi kapan sintesis dibatalkan.
SynthesisCompleted Sinyal bahwa sintesis ucapan selesai. Anda dapat mengonfirmasi kapan sintesis selesai.
SynthesisStarted Sinyal bahwa sintesis ucapan dimulai. Anda dapat mengonfirmasi kapan sintesis dimulai.
Synthesizing Sinyal bahwa sintesis ucapan sedang berlangsung. Kejadian ini diaktifkan setiap kali SDK menerima gugus audio dari layanan Ucapan. Anda dapat mengonfirmasi kapan sintesis sedang berlangsung.
VisemeReceived Sinyal bahwa peristiwa viseme diterima. Visemes sering digunakan untuk mewakili pose kunci dalam pidato yang diamati. Pose utama termasuk posisi bibir, rahang, dan lidah dalam memproduksi fonem tertentu. Anda dapat menggunakan viseme untuk menganimasikan wajah karakter saat audio ucapan diputar.
WordBoundary Memberi sinyal bahwa batas kata diterima. Peristiwa ini dimunculkan di awal setiap kata, tanda baca, dan kalimat lisan baru. Peristiwa melaporkan offset waktu kata saat ini, dalam tanda centang, dari awal audio output. Kejadian ini juga melaporkan posisi karakter dalam teks input atau SSML segera sebelum kata yang akan diucapkan. Kejadian ini biasanya digunakan untuk mendapatkan posisi relatif teks dan audio yang sesuai. Anda mungkin ingin tahu tentang kata baru, lalu mengambil tindakan berdasarkan waktu. Misalnya, Anda bisa mendapatkan informasi yang dapat membantu Anda memutuskan kapan dan berapa lama untuk menyoroti kata-kata saat diucapkan.

Catatan

Peristiwa dinaikkan saat data audio output tersedia, yang lebih cepat daripada pemutaran ke perangkat output. Pemanggil harus menyinkronkan streaming dan real-time dengan tepat.

Berikut adalah contoh yang menunjukkan cara berlangganan peristiwa untuk sintesis ucapan. Anda dapat mengikuti instruksi dalam mulai cepat, tetapi mengganti konten file speech-synthesis.py tersebut dengan kode Python berikut:

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

Anda dapat menemukan lebih banyak sampel teks ke ucapan di GitHub.

Menggunakan titik akhir kustom

Titik akhir kustom secara fungsional identik dengan titik akhir standar yang digunakan untuk permintaan teks ke ucapan.

Salah satu perbedaannya adalah harus endpoint_id ditentukan untuk menggunakan suara kustom Anda melalui Speech SDK. Anda dapat memulai dengan mulai cepat teks ke ucapan lalu memperbarui kode dengan endpoint_id dan 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"

Untuk menggunakan suara kustom melalui Speech Synthesis Markup Language (SSML), tentukan nama model sebagai nama suara. Contoh ini menggunakan YourCustomVoiceNamesuara.

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

Menjalankan dan menggunakan kontainer

Kontainer ucapan menyediakan API titik akhir kueri berbasis websocket yang diakses melalui Speech SDK dan Speech CLI. Secara default, Speech SDK dan Speech CLI menggunakan layanan Ucapan publik. Untuk menggunakan kontainer, Anda perlu mengubah metode inisialisasi. Gunakan URL host kontainer alih-alih kunci dan wilayah.

Untuk informasi selengkapnya tentang kontainer, lihat Menginstal dan menjalankan kontainer Ucapan dengan Docker.

Ucapan ke teks REST API referensi | Ucapan ke teks REST API untuk referensi | audio singkat Sampel Tambahan di GitHub

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Prasyarat

  • Langganan Azure - Buat langganan gratis.
  • Buat sumber daya Ucapan di portal Azure.
  • Kunci dan wilayah sumber daya Ucapan Anda. Setelah sumber daya Azure Cognitive Service untuk Ucapan Anda disebarkan, pilih Buka sumber daya untuk melihat dan mengelola kunci. Untuk informasi selengkapnya tentang sumber daya layanan Azure AI, lihat Mendapatkan kunci untuk sumber daya Anda.

Mengonversi teks menjadi ucapan

Pada perintah, jalankan perintah berikut ini. Masukkan nilai-nilai ini ke dalam perintah:

  • Kunci sumber daya Ucapan Anda
  • Wilayah sumber daya Ucapan Anda

Anda mungkin juga ingin mengubah nilai berikut ini:

  • Nilai X-Microsoft-OutputFormat header, yang mengontrol format output audio. Anda dapat menemukan daftar format output audio yang didukung dalam referensi REST API teks ke ucapan.
  • Suara keluaran. Untuk mendapatkan daftar suara yang tersedia untuk titik akhir layanan Ucapan Anda, lihat API Daftar Suara.
  • File keluaran. Dalam contoh ini, kami mengarahkan respons dari server ke file bernama 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

Dalam panduan cara ini, Anda mempelajari pola desain umum untuk melakukan sintesis teks ke ucapan.

Untuk informasi selengkapnya tentang area berikut ini, lihat Apa itu teks ke ucapan?

  • Mendapatkan respons sebagai aliran dalam memori.
  • Menyesuaikan laju sampel output dan laju bit.
  • Mengirimkan permintaan sintesis dengan menggunakan Speech Synthesis Markup Language (SSML).
  • Menggunakan suara neural.
  • Berlangganan peristiwa dan bertindak berdasarkan hasil.

Prasyarat

  • Langganan Azure - Buat langganan gratis.
  • Buat sumber daya Ucapan di portal Azure.
  • Kunci dan wilayah sumber daya Ucapan Anda. Setelah sumber daya Azure Cognitive Service untuk Ucapan Anda disebarkan, pilih Buka sumber daya untuk melihat dan mengelola kunci. Untuk informasi selengkapnya tentang sumber daya layanan Azure AI, lihat Mendapatkan kunci untuk sumber daya Anda.

Unduh dan instal

Ikuti langkah-langkah ini dan lihat mulai cepat Speech CLI untuk persyaratan lain untuk platform Anda.

  1. Jalankan perintah .NET CLI berikut untuk menginstal Speech CLI:

    dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
    
  2. Jalankan perintah berikut untuk mengonfigurasi kunci dan wilayah sumber daya Ucapan Anda. Ganti SUBSCRIPTION-KEY dengan kunci sumber daya Ucapan Anda dan ganti REGION dengan wilayah sumber daya Ucapan Anda.

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

Mensintesis ucapan ke pembicara

Sekarang Anda siap untuk menjalankan Speech CLI untuk mensintesis ucapan dari teks.

  • Di jendela konsol, ubah ke direktori yang berisi file biner Speech CLI. Kemudian, jalankan perintah berikut:

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

Speech CLI menghasilkan bahasa alami dalam bahasa Inggris melalui speaker komputer.

Mensintesis ucapan ke file

  • Jalankan perintah berikut untuk mengubah output dari speaker Anda ke file .wav :

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

Speech CLI menghasilkan bahasa alami dalam bahasa Inggris ke file audio greetings.wav .

Menjalankan dan menggunakan kontainer

Kontainer ucapan menyediakan API titik akhir kueri berbasis websocket yang diakses melalui Speech SDK dan Speech CLI. Secara default, Speech SDK dan Speech CLI menggunakan layanan Ucapan publik. Untuk menggunakan kontainer, Anda perlu mengubah metode inisialisasi. Gunakan URL host kontainer alih-alih kunci dan wilayah.

Untuk informasi selengkapnya tentang kontainer, lihat Menginstal dan menjalankan kontainer Ucapan dengan Docker.

Langkah berikutnya