كيفية تجميع الكلام من النص

حزمة الوثائق المرجعية | (NuGet) | عينات إضافية على GitHub

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

حدد اللغة والصوت الاصطناعيين

تدعم ميزة تحويل النص إلى كلام في خدمة الكلام أكثر من 400 صوت وأكثر من 140 لغة ومتغيرا. يمكنك الحصول على القائمة الكاملة أو تجربتها في معرض الصوت.

حدد لغة أو صوت SpeechConfig لمطابقة نص الإدخال واستخدام الصوت المحدد. توضح القصاصة البرمجية التالية كيفية عمل هذه التقنية:

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

جميع الأصوات العصبية هي متعددة اللغات وطلاقة في لغتهم الخاصة والإنجليزية. على سبيل المثال، إذا كان نص الإدخال باللغة الإنجليزية، هو "أنا متحمس لتجربة النص إلى كلام"، وحددت es-ES-ElviraNeural، يتم التحدث بالنص باللغة الإنجليزية بلكنة إسبانية.

إذا كان الصوت لا يتحدث لغة نص الإدخال، فلن تنشئ خدمة الكلام الصوت المركب. للحصول على قائمة كاملة بالأصوات العصبية المدعومة، راجع دعم اللغة والصوت لخدمة الكلام.

إشعار

الصوت الافتراضي هو أول صوت يتم إرجاعه لكل لغة من واجهة برمجة تطبيقات القائمة الصوتية.

يتم تحديد الصوت الذي يتحدث بترتيب الأولوية كما يلي:

  • إذا لم تقم بتعيين SpeechSynthesisVoiceName أو SpeechSynthesisLanguage، فإن الصوت الافتراضي للتحدث en-US .
  • إذا قمت بتعيين SpeechSynthesisLanguageفقط ، فإن الصوت الافتراضي للإعدادات المحلية المحددة يتحدث.
  • إذا تم تعيين كل من SpeechSynthesisVoiceName وSpeechSynthesisLanguage، SpeechSynthesisLanguage يتم تجاهل الإعداد. الصوت الذي تحدده باستخدام SpeechSynthesisVoiceName يتحدث.
  • إذا تم تعيين عنصر الصوت باستخدام لغة ترميز تركيب الكلام (SSML)،SpeechSynthesisVoiceName يتم تجاهل الإعدادات وSpeechSynthesisLanguage.

تجميع الكلام إلى ملف

إنشاء كائن SpeechSynthesizer . يقوم هذا الكائن الموضح في القصاصات البرمجية التالية بتشغيل تحويلات النص إلى الكلام والمخرجات إلى السماعات أو الملفات أو تدفقات الإخراج الأخرى. SpeechSynthesizer يقبل كمعلمات:

  • كائن SpeechConfig الذي قمت بإنشائه في الخطوة السابقة.
  • كائن AudioConfig الذي يحدد كيفية معالجة نتائج الإخراج.
  1. إنشاء مثيل AudioConfig لكتابة الإخراج تلقائيا إلى ملف .wav باستخدام الدالة FromWavFileOutput() . إنشاء مثيل له باستخدام عبارة using.

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

    تقوم عبارة using في هذا السياق تلقائيًا بالتخلص من الموارد غير المدارة وتؤدي بالكائن إلى الخروج عن النطاق بعد التخلص.

  2. إنشاء مثيل مع SpeechSynthesizer عبارة أخرى using . تمرير العنصر speechConfig الخاص بك والعنصر audioConfig كمعلمات. لتجميع الكلام والكتابة إلى ملف، قم بتشغيل SpeakTextAsync() بسلسلة نصية.

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

عند تشغيل البرنامج، فإنه ينشئ ملف .wav مركب، والذي تتم كتابته إلى الموقع الذي تحدده. هذه النتيجة هي مثال جيد على الاستخدام الأساسي. بعد ذلك، يمكنك تخصيص الإخراج ومعالجة استجابة الإخراج كتدفق في الذاكرة للعمل مع سيناريوهات مخصصة.

توليف لإخراج مكبر الصوت

لإخراج الكلام المركب إلى جهاز الإخراج النشط الحالي مثل مكبر الصوت، احذف المعلمة AudioConfig عند إنشاء المثيل SpeechSynthesizer . إليك مثال:

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

الحصول على نتيجة كتيار في الذاكرة

يمكنك استخدام البيانات الصوتية الناتجة كتدفق في الذاكرة بدلا من الكتابة مباشرة إلى ملف. مع دفق الذاكرة، يمكنك إنشاء سلوك مخصص:

  • تلخيص مصفوفة البايت الناتجة كدفق يمكن البحث عنه لخدمات المصب المخصصة.
  • دمج النتيجة مع API أو الخدمات الأخرى.
  • تعديل البيانات الصوتية، وكتابة عناوين .wav مخصصة، والقيام بالمهام ذات الصلة.

يمكنك إجراء هذا التغيير على المثال السابق. أولا، قم بإزالة AudioConfig الكتلة، لأنك تدير سلوك الإخراج يدويا من هذه النقطة فصاعدا لزيادة التحكم. تمرير null ل AudioConfig في الدالة SpeechSynthesizer الإنشائية.

إشعار

nullAudioConfigلا يؤدي تمرير ، بدلا من حذفه كما في مثال إخراج السماعة السابق، إلى تشغيل الصوت بشكل افتراضي على جهاز الإخراج النشط الحالي.

احفظ النتيجة إلى متغير SpeechSynthesisResult . تحتوي الخاصية AudioDataعلى مثيل byte []لبيانات الإخراج. يمكنك العمل مع هذا byte [] المثيل يدويا، أو يمكنك استخدام فئة AudioDataStream لإدارة دفق الذاكرة.

في هذا المثال، يمكنك استخدام الوظيفة الثابتة AudioDataStream.FromResult() للحصول على دفق من النتيجة:

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

في هذه المرحلة، يمكنك تنفيذ أي سلوك مخصص باستخدام الكائن الناتج stream .

تخصيص تنسيق الصوت

يمكنك تخصيص سمات إخراج الصوت، بما في ذلك:

  • نوع ملف الصوت
  • معدل العينة
  • عمق البت

لتغيير تنسيق الصوت، يمكنك استخدام الدالة SetSpeechSynthesisOutputFormat() المخصصة للكائن SpeechConfig. تتوقع هذه الدالة مثيلا enum من النوع SpeechSynthesisOutputFormat. enum استخدم لتحديد تنسيق الإخراج. للحصول على التنسيقات المتوفرة ، راجع قائمة تنسيقات الصوت.

هناك خيارات مختلفة لأنواع الملفات المختلفة اعتمادًا على المتطلبات الخاصة بك. حسب التعريف، لا تتضمن التنسيقات البسيطة مثل Raw24Khz16BitMonoPcm رؤوس الصوت. استخدم التنسيقات الأولية فقط في إحدى هذه الحالات:

  • أنت تعلم أن تنفيذ انتقال البيانات من الخادم الخاص بك يمكن أن يفك تشفير bitstream الخام.
  • تخطط لإنشاء رؤوس يدويا استنادا إلى عوامل مثل عمق البت ومعدل العينة وعدد القنوات.

يحدد هذا المثال تنسيق Riff24Khz16BitMonoPcm RIFF عالي الدقة عن طريق تعيين SpeechSynthesisOutputFormat على SpeechConfig العنصر . على غرار المثال في القسم السابق، يمكنك استخدام AudioDataStream للحصول على دفق في الذاكرة للنتيجة، ثم كتابتها في ملف.

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

عند تشغيل البرنامج، فإنه يكتب ملف .wav إلى المسار المحدد.

استخدام لغة ترميز تركيب الكلام (SSML) لتخصيص خصائص الكلام

يمكنك استخدام SSML لضبط درجة الصوت والنطق ومعدل التحدث والحجم والجوانب الأخرى في إخراج النص إلى الكلام عن طريق إرسال طلباتك من مخطط XML. يعرض هذا القسم مثالاً على تغيير الصوت. لمزيد من المعلومات، راجع نظرة عامة على لغة ترميز تركيب الكلام.

لبدء استخدام SSML للتخصيص، يمكنك إجراء تغيير طفيف يقوم بتبديل الصوت.

  1. إنشاء ملف XML جديد لتكوين SSML في دليل المشروع الجذر الخاص بك.

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

    في هذا المثال، يتم ssml.xml الملف. العنصر الجذر هو دائمًا <speak>. يتيح لك التفاف النص في عنصر <voice> تغيير الصوت باستخدام المعلمة name. للحصول على القائمة الكاملة للأصوات العصبية المدعومة، راجع اللغات المدعومة.

  2. قم بتغيير طلب تركيب الكلام للإشارة إلى ملف XML الخاص بك. سيكون الطلب هو نفسه في الغالب، ولكن بدلاً من استخدام دالةSpeakTextAsync()، يمكنك استخدام SpeakSsmlAsync(). تتوقع هذه الدالة سلسلة XML. أولا، قم بتحميل تكوين SSML كسلسلة باستخدام File.ReadAllText(). من هذه النقطة، كائن النتيجة هو بالضبط نفس الأمثلة السابقة.

    إشعار

    إذا كنت تستخدم Visual Studio، فمن المحتمل ألا يعثر تكوين البناء الخاص بك على ملف XML بشكل افتراضي. انقر بزر الماوس الأيمن فوق ملف XML وحدد خصائص. تغيير إجراء الإنشاء إلى محتوى. تغيير نسخ إلى دليل الإخراج إلى نسخ دائما.

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

إشعار

لتغيير الصوت دون استخدام لغة ترميز تركيب الكلام (SSML)، يمكنك تعيين الخاصية على SpeechConfig باستخدام SpeechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

الاشتراك في أحداث synthesizer

قد تحتاج إلى مزيد من الرؤى حول معالجة النص إلى الكلام والنتائج. على سبيل المثال، قد ترغب في معرفة متى يبدأ التركيب ويتوقف، أو قد ترغب في معرفة الأحداث الأخرى التي تمت مواجهتها أثناء التركيب.

أثناء استخدام SpeechSynthesizer لتحويل النص إلى كلام، يمكنك الاشتراك في الأحداث في هذا الجدول:

حدث ‏‏الوصف حالة الاستخدام
BookmarkReached إشارات إلى أنه تم الوصول إلى إشارة مرجعية. لتشغيل حدث تم الوصول إليه بإشارة مرجعية، يلزم وجود bookmark عنصر في SSML. يبلغ هذا الحدث عن الوقت المنقضي لصوت الإخراج بين بداية التركيب والعنصر bookmark . خاصية الحدث Text هي قيمة السلسلة التي قمت بتعيينها في سمة الإشارة المرجعية mark . bookmark العناصر غير منطوقة. يمكنك استخدام العنصر bookmark لإدراج علامات مخصصة في SSML للحصول على إزاحة كل علامة في دفق الصوت. يمكن استخدام العنصر bookmark للإشارة إلى موقع معين في تسلسل العلامة أو النص.
SynthesisCanceled إشارات إلى إلغاء تركيب الكلام. يمكنك التأكيد عند إلغاء التركيب.
SynthesisCompleted إشارات إلى اكتمال تركيب الكلام. يمكنك تأكيد عند اكتمال التركيب.
SynthesisStarted إشارات إلى أن تركيب الكلام بدأ. يمكنك التأكيد عند بدء التركيب.
Synthesizing إشارات إلى أن تركيب الكلام مستمر. يتم تشغيل هذا الحدث في كل مرة يتلقى فيها SDK مجموعة صوتية من خدمة الكلام. يمكنك تأكيد وقت التركيب قيد التقدم.
VisemeReceived إشارات إلى تلقي حدث viseme. Visemes غالبا ما تستخدم لتمثيل الأوضاع الرئيسية في الكلام الملاحظ. تشمل الأوضاع الرئيسية موضع الشفاه والفك واللسان في إنتاج مقطع صوتي معين. يمكنك استخدام visemes لتحريك وجه الحرف أثناء تشغيل صوت الكلام.
WordBoundary يشير إلى تلقي حد كلمة. يتم رفع هذا الحدث في بداية كل كلمة منطوقة جديدة وعلامات ترقيم وجملة. يبلغ الحدث عن إزاحة وقت الكلمة الحالية، في علامات التجزئة، من بداية صوت الإخراج. يقوم هذا الحدث أيضا بالإبلاغ عن موضع الحرف في نص الإدخال أو SSML مباشرة قبل الكلمة التي على وشك التحدث بها. يستخدم هذا الحدث بشكل شائع للحصول على المواضع النسبية للنص والصوت المقابل. قد ترغب في معرفة كلمة جديدة، ثم اتخاذ إجراء بناء على التوقيت. على سبيل المثال، يمكنك الحصول على معلومات يمكن أن تساعدك في تحديد متى ومدة تمييز الكلمات أثناء نطقها.

إشعار

يتم رفع الأحداث مع توفر بيانات صوت الإخراج، وهو أسرع من التشغيل على جهاز إخراج. يجب على المتصل مزامنة الدفق وفي الوقت الحقيقي بشكل مناسب.

فيما يلي مثال يوضح كيفية الاشتراك في أحداث تركيب الكلام. يمكنك اتباع الإرشادات الموجودة في التشغيل السريع، ولكن استبدال محتويات هذا الملف Program.cs بالتعليمة البرمجية C# التالية:

using Microsoft.CognitiveServices.Speech;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

يمكنك العثور على المزيد من النص إلى عينات الكلام في GitHub.

استخدم نقطة نهاية مخصصة

نقطة النهاية المخصصة مطابقة وظيفيا لنقطة النهاية القياسية المستخدمة لطلبات النص إلى الكلام.

أحد الاختلافات هو أنه EndpointId يجب تحديد لاستخدام صوتك المخصص عبر Speech SDK. يمكنك البدء بالنص إلى التشغيل السريع للكلام ثم تحديث التعليمات البرمجية باستخدام EndpointId و SpeechSynthesisVoiceName.

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

لاستخدام صوت مخصص عبر Speech Synthesis Markup Language (SSML)، حدد اسم النموذج كاسم صوتي. يستخدم هذا المثال الصوت YourCustomVoiceName.

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

تشغيل حاوية واستخدامها

توفر حاويات الكلام واجهات برمجة تطبيقات نقطة نهاية الاستعلام المستندة إلى websocket التي يتم الوصول إليها من خلال Speech SDK و Speech CLI. بشكل افتراضي، يستخدم Speech SDK و Speech CLI خدمة Speech العامة. لاستخدام الحاوية، تحتاج إلى تغيير أسلوب التهيئة. استخدم عنوان URL لمضيف الحاوية بدلا من المفتاح والمنطقة.

لمزيد من المعلومات حول الحاويات، راجع تثبيت حاويات الكلام وتشغيلها باستخدام Docker.

حزمة الوثائق المرجعية | (NuGet) | عينات إضافية على GitHub

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

حدد اللغة والصوت الاصطناعيين

تدعم ميزة تحويل النص إلى كلام في خدمة الكلام أكثر من 400 صوت وأكثر من 140 لغة ومتغيرا. راجع القائمة الكاملة للنص المعتمد إلى إعدادات الكلام المحلية أو جربها في معرض الصوت.

حدد لغة أو صوت فئة SpeechConfig لمطابقة نص الإدخال واستخدام الصوت المحدد. توضح القصاصة البرمجية التالية كيفية عمل هذه التقنية:

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

جميع الأصوات العصبية هي متعددة اللغات وطلاقة في لغتهم الخاصة والإنجليزية. على سبيل المثال، إذا كان نص الإدخال باللغة الإنجليزية هو ، "أنا متحمس لتجربة النص إلى كلام"، وحددت es-ES-ElviraNeural، يتم التحدث بالنص باللغة الإنجليزية بلكنة إسبانية.

إذا كان الصوت لا يتحدث لغة نص الإدخال، فلن تنشئ خدمة الكلام الصوت المركب. للحصول على قائمة كاملة بالأصوات العصبية المدعومة، راجع دعم اللغة والصوت لخدمة الكلام.

إشعار

الصوت الافتراضي هو أول صوت يتم إرجاعه لكل لغة من واجهة برمجة تطبيقات القائمة الصوتية.

يتم تحديد الصوت الذي يتحدث بترتيب الأولوية كما يلي:

  • إذا لم تقم بتعيين SpeechSynthesisVoiceName أو SpeechSynthesisLanguage، فإن الصوت الافتراضي للتحدث en-US .
  • إذا قمت بتعيين SpeechSynthesisLanguageفقط ، فإن الصوت الافتراضي للإعدادات المحلية المحددة يتحدث.
  • إذا تم تعيين كل من SpeechSynthesisVoiceName وSpeechSynthesisLanguage، SpeechSynthesisLanguage يتم تجاهل الإعداد. الصوت الذي تحدده باستخدام SpeechSynthesisVoiceName يتحدث.
  • إذا تم تعيين عنصر الصوت باستخدام لغة ترميز تركيب الكلام (SSML)،SpeechSynthesisVoiceName يتم تجاهل الإعدادات وSpeechSynthesisLanguage.

تجميع الكلام إلى ملف

إنشاء كائن SpeechSynthesizer . يقوم هذا الكائن الموضح في القصاصات البرمجية التالية بتشغيل تحويلات النص إلى الكلام والمخرجات إلى السماعات أو الملفات أو تدفقات الإخراج الأخرى. SpeechSynthesizer يقبل كمعلمات:

  • كائن SpeechConfig الذي قمت بإنشائه في الخطوة السابقة.
  • كائن AudioConfig الذي يحدد كيفية معالجة نتائج الإخراج.
  1. إنشاء مثيل AudioConfig لكتابة الإخراج تلقائيا إلى ملف .wav باستخدام الدالة FromWavFileOutput() :

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
    }
    
  2. SpeechSynthesizer إنشاء مثيل. تمرير العنصر speechConfig الخاص بك والعنصر audioConfig كمعلمات. لتجميع الكلام والكتابة إلى ملف، قم بتشغيل SpeakTextAsync() بسلسلة نصية.

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

عند تشغيل البرنامج، فإنه ينشئ ملف .wav مركب، والذي تتم كتابته إلى الموقع الذي تحدده. هذه النتيجة هي مثال جيد على الاستخدام الأساسي. بعد ذلك، يمكنك تخصيص الإخراج ومعالجة استجابة الإخراج كتدفق في الذاكرة للعمل مع سيناريوهات مخصصة.

توليف لإخراج مكبر الصوت

لإخراج الكلام المركب إلى جهاز الإخراج النشط الحالي مثل مكبر الصوت، احذف المعلمة AudioConfig عند إنشاء المثيل SpeechSynthesizer . إليك مثال:

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

الحصول على نتيجة كتيار في الذاكرة

يمكنك استخدام البيانات الصوتية الناتجة كتدفق في الذاكرة بدلا من الكتابة مباشرة إلى ملف. مع دفق الذاكرة، يمكنك إنشاء سلوك مخصص:

  • تلخيص مصفوفة البايت الناتجة كدفق يمكن البحث عنه لخدمات المصب المخصصة.
  • دمج النتيجة مع API أو الخدمات الأخرى.
  • تعديل البيانات الصوتية، وكتابة عناوين .wav مخصصة، والقيام بالمهام ذات الصلة.

يمكنك إجراء هذا التغيير على المثال السابق. أولا، قم بإزالة AudioConfig الكتلة، لأنك تدير سلوك الإخراج يدويا من هذه النقطة فصاعدا لزيادة التحكم. تمرير NULL ل AudioConfig في الدالة SpeechSynthesizer الإنشائية.

إشعار

NULLAudioConfigلا يؤدي تمرير ، بدلا من حذفه كما في مثال إخراج السماعة السابق، إلى تشغيل الصوت بشكل افتراضي على جهاز الإخراج النشط الحالي.

احفظ النتيجة إلى متغير SpeechSynthesisResult . يقوم المحصل GetAudioData بإرجاع مثيل byte [] لبيانات الإخراج. يمكنك العمل مع هذا byte [] المثيل يدويا، أو يمكنك استخدام فئة AudioDataStream لإدارة دفق الذاكرة.

في هذا المثال، استخدم الدالة AudioDataStream.FromResult() الثابتة للحصول على دفق من النتيجة:

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

في هذه المرحلة، يمكنك تنفيذ أي سلوك مخصص باستخدام الكائن الناتج stream .

تخصيص تنسيق الصوت

يمكنك تخصيص سمات إخراج الصوت، بما في ذلك:

  • نوع ملف الصوت
  • معدل العينة
  • عمق البت

لتغيير تنسيق الصوت، استخدم الدالة SetSpeechSynthesisOutputFormat() الموجودة على SpeechConfig الكائن. تتوقع هذه الدالة مثيلا enum من النوع SpeechSynthesisOutputFormat. enum استخدم لتحديد تنسيق الإخراج. للحصول على التنسيقات المتوفرة ، راجع قائمة تنسيقات الصوت.

هناك خيارات مختلفة لأنواع الملفات المختلفة اعتمادًا على المتطلبات الخاصة بك. حسب التعريف، لا تتضمن التنسيقات البسيطة مثل Raw24Khz16BitMonoPcm رؤوس الصوت. استخدم التنسيقات الأولية فقط في إحدى هذه الحالات:

  • أنت تعلم أن تنفيذ انتقال البيانات من الخادم الخاص بك يمكن أن يفك تشفير bitstream الخام.
  • تخطط لإنشاء رؤوس يدويا استنادا إلى عوامل مثل عمق البت ومعدل العينة وعدد القنوات.

يحدد هذا المثال تنسيق Riff24Khz16BitMonoPcm RIFF عالي الدقة عن طريق تعيين SpeechSynthesisOutputFormat على SpeechConfig العنصر . على غرار المثال الوارد في القسم السابق، يمكنك استخدام AudioDataStream للحصول على دفق في الذاكرة من النتيجة، ومن ثم كتابته إلى ملف.

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

عند تشغيل البرنامج، فإنه يكتب ملف .wav إلى المسار المحدد.

استخدام لغة ترميز تركيب الكلام (SSML) لتخصيص خصائص الكلام

يمكنك استخدام SSML لضبط درجة الصوت والنطق ومعدل التحدث والحجم والجوانب الأخرى في إخراج النص إلى الكلام عن طريق إرسال طلباتك من مخطط XML. يعرض هذا القسم مثالاً على تغيير الصوت. لمزيد من المعلومات، راجع نظرة عامة على لغة ترميز تركيب الكلام.

لبدء استخدام SSML للتخصيص، قم بإجراء تغيير طفيف يقوم بتبديل الصوت.

  1. إنشاء ملف XML جديد لتكوين SSML في دليل المشروع الجذر الخاص بك.

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

    في هذا المثال، يتم ssml.xml الملف. العنصر الجذر هو دائمًا <speak>. يتيح لك التفاف النص في عنصر <voice> تغيير الصوت باستخدام المعلمة name. للحصول على القائمة الكاملة للأصوات العصبية المدعومة، راجع اللغات المدعومة.

  2. قم بتغيير طلب تركيب الكلام للإشارة إلى ملف XML الخاص بك. الطلب هو نفسه في الغالب. بدلا من استخدام الدالة SpeakTextAsync() ، يمكنك استخدام SpeakSsmlAsync(). تتوقع هذه الدالة سلسلة XML. أولا، قم بتحميل تكوين SSML كسلسلة. من هذه النقطة، كائن النتيجة هو بالضبط نفس الأمثلة السابقة.

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

إشعار

لتغيير الصوت دون استخدام لغة ترميز تركيب الكلام (SSML)، يمكنك تعيين الخاصية على SpeechConfig باستخدام SpeechConfig.SetSpeechSynthesisVoiceName("en-US-AndrewMultilingualNeural").

الاشتراك في أحداث synthesizer

قد تحتاج إلى مزيد من الرؤى حول معالجة النص إلى الكلام والنتائج. على سبيل المثال، قد ترغب في معرفة متى يبدأ التركيب ويتوقف، أو قد ترغب في معرفة الأحداث الأخرى التي تمت مواجهتها أثناء التركيب.

أثناء استخدام SpeechSynthesizer لتحويل النص إلى كلام، يمكنك الاشتراك في الأحداث في هذا الجدول:

حدث ‏‏الوصف حالة الاستخدام
BookmarkReached إشارات إلى أنه تم الوصول إلى إشارة مرجعية. لتشغيل حدث تم الوصول إليه بإشارة مرجعية، يلزم وجود bookmark عنصر في SSML. يبلغ هذا الحدث عن الوقت المنقضي لصوت الإخراج بين بداية التركيب والعنصر bookmark . خاصية الحدث Text هي قيمة السلسلة التي قمت بتعيينها في سمة الإشارة المرجعية mark . bookmark العناصر غير منطوقة. يمكنك استخدام العنصر bookmark لإدراج علامات مخصصة في SSML للحصول على إزاحة كل علامة في دفق الصوت. يمكن استخدام العنصر bookmark للإشارة إلى موقع معين في تسلسل العلامة أو النص.
SynthesisCanceled إشارات إلى إلغاء تركيب الكلام. يمكنك التأكيد عند إلغاء التركيب.
SynthesisCompleted إشارات إلى اكتمال تركيب الكلام. يمكنك تأكيد عند اكتمال التركيب.
SynthesisStarted إشارات إلى أن تركيب الكلام بدأ. يمكنك التأكيد عند بدء التركيب.
Synthesizing إشارات إلى أن تركيب الكلام مستمر. يتم تشغيل هذا الحدث في كل مرة يتلقى فيها SDK مجموعة صوتية من خدمة الكلام. يمكنك تأكيد وقت التركيب قيد التقدم.
VisemeReceived إشارات إلى تلقي حدث viseme. Visemes غالبا ما تستخدم لتمثيل الأوضاع الرئيسية في الكلام الملاحظ. تشمل الأوضاع الرئيسية موضع الشفاه والفك واللسان في إنتاج مقطع صوتي معين. يمكنك استخدام visemes لتحريك وجه الحرف أثناء تشغيل صوت الكلام.
WordBoundary يشير إلى تلقي حد كلمة. يتم رفع هذا الحدث في بداية كل كلمة منطوقة جديدة وعلامات ترقيم وجملة. يبلغ الحدث عن إزاحة وقت الكلمة الحالية، في علامات التجزئة، من بداية صوت الإخراج. يقوم هذا الحدث أيضا بالإبلاغ عن موضع الحرف في نص الإدخال أو SSML مباشرة قبل الكلمة التي على وشك التحدث بها. يستخدم هذا الحدث بشكل شائع للحصول على المواضع النسبية للنص والصوت المقابل. قد ترغب في معرفة كلمة جديدة، ثم اتخاذ إجراء بناء على التوقيت. على سبيل المثال، يمكنك الحصول على معلومات يمكن أن تساعدك في تحديد متى ومدة تمييز الكلمات أثناء نطقها.

إشعار

يتم رفع الأحداث مع توفر بيانات صوت الإخراج، وهو أسرع من التشغيل على جهاز إخراج. يجب على المتصل مزامنة الدفق وفي الوقت الحقيقي بشكل مناسب.

فيما يلي مثال يوضح كيفية الاشتراك في أحداث تركيب الكلام. يمكنك اتباع الإرشادات الواردة في التشغيل السريع، ولكن استبدال محتويات ملف main.cpp بالتعليمات البرمجية التالية:

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

يمكنك العثور على المزيد من النص إلى عينات الكلام في GitHub.

استخدم نقطة نهاية مخصصة

نقطة النهاية المخصصة مطابقة وظيفيا لنقطة النهاية القياسية المستخدمة لطلبات النص إلى الكلام.

أحد الاختلافات هو أنه EndpointId يجب تحديد لاستخدام صوتك المخصص عبر Speech SDK. يمكنك البدء بالنص إلى التشغيل السريع للكلام ثم تحديث التعليمات البرمجية باستخدام EndpointId و SpeechSynthesisVoiceName.

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

لاستخدام صوت مخصص عبر Speech Synthesis Markup Language (SSML)، حدد اسم النموذج كاسم صوتي. يستخدم هذا المثال الصوت YourCustomVoiceName.

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

تشغيل حاوية واستخدامها

توفر حاويات الكلام واجهات برمجة تطبيقات نقطة نهاية الاستعلام المستندة إلى websocket التي يتم الوصول إليها من خلال Speech SDK و Speech CLI. بشكل افتراضي، يستخدم Speech SDK و Speech CLI خدمة Speech العامة. لاستخدام الحاوية، تحتاج إلى تغيير أسلوب التهيئة. استخدم عنوان URL لمضيف الحاوية بدلا من المفتاح والمنطقة.

لمزيد من المعلومات حول الحاويات، راجع تثبيت حاويات الكلام وتشغيلها باستخدام Docker.

الوثائق المرجعية | حزمة (Go) | عينات إضافية على GitHub

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

المتطلبات الأساسية

قم بتثبيت Speech SDK

قبل أن تتمكن من القيام بأي شيء، ستحتاج إلى تثبيت Speech SDK for Go.

تحويل النص إلى كلام إلى مكبر الصوت

استخدم نموذج التعليمة البرمجية التالية لتشغيل تركيب الكلام لجهاز الإخراج الصوتي الافتراضي. استبدل المتغيراتsubscription وregion مفتاح الكلام والموقع/المنطقة. يؤدي تشغيل البرنامج النصي إلى نطق نص الإدخال إلى السماعة الافتراضية.

package main

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

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

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

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

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

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

func main() {
    subscription := "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)
            }
        }
    }
}

تشغيل الأوامر التالية لإنشاء ملف go.mod الذي يرتبط بالمكونات المستضافة على GitHub:

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

الآن أنشئ التعليمة البرمجية وشغّلها:

go build
go run quickstart

للحصول على معلومات مفصلة حول الفئات، راجع SpeechConfig المستندات والمراجع SpeechSynthesizer.

تحويل النص إلى كلام إلى دفق في الذاكرة

يمكنك استخدام البيانات الصوتية الناتجة كتدفق في الذاكرة بدلا من الكتابة مباشرة إلى ملف. مع دفق الذاكرة، يمكنك إنشاء سلوك مخصص:

  • تلخيص مصفوفة البايت الناتجة كدفق يمكن البحث عنه لخدمات المصب المخصصة.
  • دمج النتيجة مع API أو الخدمات الأخرى.
  • تعديل البيانات الصوتية، وكتابة عناوين .wav مخصصة، والقيام بالمهام ذات الصلة.

يمكنك إجراء هذا التغيير على المثال السابق. قم بإزالة AudioConfig الكتلة، لأنك تدير سلوك الإخراج يدويا من هذه النقطة فصاعدا لزيادة التحكم. ثم مرر nil لـAudioConfig في الدالة الإنشائية SpeechSynthesizer.

إشعار

لن يؤدي تمرير nil لـ AudioConfig، فبدلاً من حذفه كما فعلت في مثال إخراج مكبر الصوت السابق، إلى تشغيل الصوت افتراضيًا على جهاز الإخراج النشط الحالي.

حفظ النتيجة إلى SpeechSynthesisResult متغير. تقوم الخاصية AudioData بإرجاع مثيل []byte لبيانات الإخراج. يمكنك العمل مع مثيل []byte هذا يدويًا، أو يمكنك استخدام فئة AudioDataStream لإدارة التدفق داخل الذاكرة. في هذا المثال، يمكنك استخدام الدالة NewAudioDataStreamFromSpeechSynthesisResult() الثابتة للحصول على دفق من النتيجة.

استبدل المتغيراتsubscription وregion مفتاح الكلام والموقع/المنطقة:

package main

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

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

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

تشغيل الأوامر التالية لإنشاء ملف go.mod الذي يرتبط بالمكونات المستضافة على GitHub:

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

الآن أنشئ التعليمة البرمجية وشغّلها:

go build
go run quickstart

للحصول على معلومات مفصلة حول الفئات، راجع SpeechConfig المستندات والمراجع SpeechSynthesizer.

حدد اللغة والصوت الاصطناعيين

تدعم ميزة تحويل النص إلى كلام في خدمة الكلام أكثر من 400 صوت وأكثر من 140 لغة ومتغيرا. يمكنك الحصول على القائمة الكاملة أو تجربتها في معرض الصوت.

حدد لغة أو صوت SpeechConfig لمطابقة نص الإدخال واستخدام الصوت المحدد:

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

جميع الأصوات العصبية هي متعددة اللغات وطلاقة في لغتهم الخاصة والإنجليزية. على سبيل المثال، إذا كان نص الإدخال باللغة الإنجليزية هو ، "أنا متحمس لتجربة النص إلى كلام"، وحددت es-ES-ElviraNeural، يتم التحدث بالنص باللغة الإنجليزية بلكنة إسبانية.

إذا كان الصوت لا يتحدث لغة نص الإدخال، فلن تنشئ خدمة الكلام الصوت المركب. للحصول على قائمة كاملة بالأصوات العصبية المدعومة، راجع دعم اللغة والصوت لخدمة الكلام.

إشعار

الصوت الافتراضي هو أول صوت يتم إرجاعه لكل لغة من واجهة برمجة تطبيقات القائمة الصوتية.

يتم تحديد الصوت الذي يتحدث بترتيب الأولوية كما يلي:

  • إذا لم تقم بتعيين SpeechSynthesisVoiceName أو SpeechSynthesisLanguage، فإن الصوت الافتراضي للتحدث en-US .
  • إذا قمت بتعيين SpeechSynthesisLanguageفقط ، فإن الصوت الافتراضي للإعدادات المحلية المحددة يتحدث.
  • إذا تم تعيين كل من SpeechSynthesisVoiceName وSpeechSynthesisLanguage، SpeechSynthesisLanguage يتم تجاهل الإعداد. الصوت الذي تحدده باستخدام SpeechSynthesisVoiceName يتحدث.
  • إذا تم تعيين عنصر الصوت باستخدام لغة ترميز تركيب الكلام (SSML)،SpeechSynthesisVoiceName يتم تجاهل الإعدادات وSpeechSynthesisLanguage.

استخدام لغة ترميز تركيب الكلام (SSML) لتخصيص خصائص الكلام

يمكنك استخدام لغة ترميز تركيب الكلام (SSML) لضبط درجة الصوت والنطق ومعدل التحدث ومستوى الصوت والمزيد في النص إلى إخراج الكلام عن طريق إرسال طلباتك من مخطط XML. يعرض هذا القسم مثالاً على تغيير الصوت. لمزيد من المعلومات، راجع نظرة عامة على لغة ترميز تركيب الكلام.

لبدء استخدام SSML للتخصيص، يمكنك إجراء تغيير طفيف يقوم بتبديل الصوت.

أولاً، قم بإنشاء ملف XML جديد لتهيئة SSML في دليل المشروع الأساسي الخاص بك. في هذا المثال، هو ssml.xml. العنصر الجذر هو دائمًا <speak>. يتيح لك التفاف النص في عنصر <voice> تغيير الصوت باستخدام المعلمة name. للحصول على القائمة الكاملة للأصوات العصبية المدعومة، راجع اللغات المدعومة.

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

بعد ذلك، تحتاج إلى تغيير طلب تركيب الكلام للإشارة إلى ملف XML الخاص بك. سيكون الطلب هو نفسه في الغالب، ولكن بدلاً من استخدام دالةSpeakTextAsync()، يمكنك استخدام SpeakSsmlAsync(). تتوقع هذه الوظيفة سلسلة XML، لذلك تقوم أولاً بتحميل تكوين SSML كسلسلة. من هذه النقطة، كائن النتيجة هو بالضبط نفس الأمثلة السابقة.

إشعار

لضبط الصوت دون استخدام لغة ترميز تركيب الكلام (SSML)، يمكنك تعيين الخاصية على SpeechConfig باستخدام speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural").

الاشتراك في أحداث synthesizer

قد تحتاج إلى مزيد من الرؤى حول معالجة النص إلى الكلام والنتائج. على سبيل المثال، قد ترغب في معرفة متى يبدأ التركيب ويتوقف، أو قد ترغب في معرفة الأحداث الأخرى التي تمت مواجهتها أثناء التركيب.

أثناء استخدام SpeechSynthesizer لتحويل النص إلى كلام، يمكنك الاشتراك في الأحداث في هذا الجدول:

حدث ‏‏الوصف حالة الاستخدام
BookmarkReached إشارات إلى أنه تم الوصول إلى إشارة مرجعية. لتشغيل حدث تم الوصول إليه بإشارة مرجعية، يلزم وجود bookmark عنصر في SSML. يبلغ هذا الحدث عن الوقت المنقضي لصوت الإخراج بين بداية التركيب والعنصر bookmark . خاصية الحدث Text هي قيمة السلسلة التي قمت بتعيينها في سمة الإشارة المرجعية mark . bookmark العناصر غير منطوقة. يمكنك استخدام العنصر bookmark لإدراج علامات مخصصة في SSML للحصول على إزاحة كل علامة في دفق الصوت. يمكن استخدام العنصر bookmark للإشارة إلى موقع معين في تسلسل العلامة أو النص.
SynthesisCanceled إشارات إلى إلغاء تركيب الكلام. يمكنك التأكيد عند إلغاء التركيب.
SynthesisCompleted إشارات إلى اكتمال تركيب الكلام. يمكنك تأكيد عند اكتمال التركيب.
SynthesisStarted إشارات إلى أن تركيب الكلام بدأ. يمكنك التأكيد عند بدء التركيب.
Synthesizing إشارات إلى أن تركيب الكلام مستمر. يتم تشغيل هذا الحدث في كل مرة يتلقى فيها SDK مجموعة صوتية من خدمة الكلام. يمكنك تأكيد وقت التركيب قيد التقدم.
VisemeReceived إشارات إلى تلقي حدث viseme. Visemes غالبا ما تستخدم لتمثيل الأوضاع الرئيسية في الكلام الملاحظ. تشمل الأوضاع الرئيسية موضع الشفاه والفك واللسان في إنتاج مقطع صوتي معين. يمكنك استخدام visemes لتحريك وجه الحرف أثناء تشغيل صوت الكلام.
WordBoundary يشير إلى تلقي حد كلمة. يتم رفع هذا الحدث في بداية كل كلمة منطوقة جديدة وعلامات ترقيم وجملة. يبلغ الحدث عن إزاحة وقت الكلمة الحالية، في علامات التجزئة، من بداية صوت الإخراج. يقوم هذا الحدث أيضا بالإبلاغ عن موضع الحرف في نص الإدخال أو SSML مباشرة قبل الكلمة التي على وشك التحدث بها. يستخدم هذا الحدث بشكل شائع للحصول على المواضع النسبية للنص والصوت المقابل. قد ترغب في معرفة كلمة جديدة، ثم اتخاذ إجراء بناء على التوقيت. على سبيل المثال، يمكنك الحصول على معلومات يمكن أن تساعدك في تحديد متى ومدة تمييز الكلمات أثناء نطقها.

إشعار

يتم رفع الأحداث مع توفر بيانات صوت الإخراج، وهو أسرع من التشغيل على جهاز إخراج. يجب على المتصل مزامنة الدفق وفي الوقت الحقيقي بشكل مناسب.

فيما يلي مثال يوضح كيفية الاشتراك في أحداث تركيب الكلام. يمكنك اتباع الإرشادات الموجودة في التشغيل السريع، ولكن استبدل محتويات هذا speech-synthesis.go الملف بالتعليمة البرمجية Go التالية:

package main

import (
    "fmt"
    "os"
    "time"

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

func bookmarkReachedHandler(event speech.SpeechSynthesisBookmarkEventArgs) {
    defer event.Close()
    fmt.Println("BookmarkReached event")
}

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

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

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

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

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

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

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

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

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

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

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

    speechSynthesisVoiceName := "en-US-AvaMultilingualNeural"

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

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

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

    if outcome.Result.Reason == common.SynthesizingAudioCompleted {
        fmt.Println("SynthesizingAudioCompleted result")
    } else {
        cancellation, _ := speech.NewCancellationDetailsFromSpeechSynthesisResult(outcome.Result)
        fmt.Printf("CANCELED: Reason=%d.\n", cancellation.Reason)

        if cancellation.Reason == common.Error {
            fmt.Printf("CANCELED: ErrorCode=%d\nCANCELED: ErrorDetails=[%s]\nCANCELED: Did you set the speech resource key and region values?\n",
                cancellation.ErrorCode,
                cancellation.ErrorDetails)
        }
    }
}

يمكنك العثور على المزيد من النص إلى عينات الكلام في GitHub.

تشغيل حاوية واستخدامها

توفر حاويات الكلام واجهات برمجة تطبيقات نقطة نهاية الاستعلام المستندة إلى websocket التي يتم الوصول إليها من خلال Speech SDK و Speech CLI. بشكل افتراضي، يستخدم Speech SDK و Speech CLI خدمة Speech العامة. لاستخدام الحاوية، تحتاج إلى تغيير أسلوب التهيئة. استخدم عنوان URL لمضيف الحاوية بدلا من المفتاح والمنطقة.

لمزيد من المعلومات حول الحاويات، راجع تثبيت حاويات الكلام وتشغيلها باستخدام Docker.

وثائق مرجعية | نماذج إضافية على GitHub

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

حدد اللغة والصوت الاصطناعيين

تدعم ميزة تحويل النص إلى كلام في خدمة الكلام أكثر من 400 صوت وأكثر من 140 لغة ومتغيرا. يمكنك الحصول على القائمة الكاملة أو تجربتها في معرض الصوت.

حدد لغة SpeechConfig أو صوته لمطابقة نص الإدخال واستخدام الصوت المحدد. توضح القصاصة البرمجية التالية كيفية عمل هذه التقنية:

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

جميع الأصوات العصبية هي متعددة اللغات وطلاقة في لغتهم الخاصة والإنجليزية. على سبيل المثال، إذا كان نص الإدخال باللغة الإنجليزية هو ، "أنا متحمس لتجربة النص إلى كلام"، وحددت es-ES-ElviraNeural، يتم التحدث بالنص باللغة الإنجليزية بلكنة إسبانية.

إذا كان الصوت لا يتحدث لغة نص الإدخال، فلن تنشئ خدمة الكلام الصوت المركب. للحصول على قائمة كاملة بالأصوات العصبية المدعومة، راجع دعم اللغة والصوت لخدمة الكلام.

إشعار

الصوت الافتراضي هو أول صوت يتم إرجاعه لكل لغة من واجهة برمجة تطبيقات القائمة الصوتية.

يتم تحديد الصوت الذي يتحدث بترتيب الأولوية كما يلي:

  • إذا لم تقم بتعيين SpeechSynthesisVoiceName أو SpeechSynthesisLanguage، فإن الصوت الافتراضي للتحدث en-US .
  • إذا قمت بتعيين SpeechSynthesisLanguageفقط ، فإن الصوت الافتراضي للإعدادات المحلية المحددة يتحدث.
  • إذا تم تعيين كل من SpeechSynthesisVoiceName وSpeechSynthesisLanguage، SpeechSynthesisLanguage يتم تجاهل الإعداد. الصوت الذي حددته باستخدام SpeechSynthesisVoiceName يتحدث.
  • إذا تم تعيين عنصر الصوت باستخدام لغة ترميز تركيب الكلام (SSML)،SpeechSynthesisVoiceName يتم تجاهل الإعدادات وSpeechSynthesisLanguage.

تجميع الكلام إلى ملف

إنشاء كائن SpeechSynthesizer . يقوم هذا الكائن بتشغيل تحويلات النص إلى الكلام والمخرجات إلى السماعات أو الملفات أو تدفقات الإخراج الأخرى. SpeechSynthesizer يقبل كمعلمات:

  • SpeechConfig الكائن الذي قمت بإنشائه في الخطوة السابقة.
  • كائن AudioConfig يحدد كيفية معالجة نتائج الإخراج.
  1. إنشاء مثيل AudioConfig لكتابة الإخراج تلقائيا إلى ملف .wav باستخدام الدالة fromWavFileOutput() الثابتة:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    }
    
  2. SpeechSynthesizer إنشاء مثيل. تمرير العنصر speechConfig الخاص بك والعنصر audioConfig كمعلمات. لتجميع الكلام والكتابة إلى ملف، قم بتشغيل SpeakText() بسلسلة نصية.

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

عند تشغيل البرنامج، فإنه ينشئ ملف .wav مركب، والذي تتم كتابته إلى الموقع الذي تحدده. هذه النتيجة هي مثال جيد على الاستخدام الأساسي. بعد ذلك، يمكنك تخصيص الإخراج ومعالجة استجابة الإخراج كتدفق في الذاكرة للعمل مع سيناريوهات مخصصة.

توليف لإخراج مكبر الصوت

قد تحتاج إلى مزيد من الرؤى حول معالجة النص إلى الكلام والنتائج. على سبيل المثال، قد ترغب في معرفة متى يبدأ التركيب ويتوقف، أو قد ترغب في معرفة الأحداث الأخرى التي تمت مواجهتها أثناء التركيب.

لإخراج الكلام المركب إلى جهاز الإخراج النشط الحالي مثل مكبر الصوت، قم بإنشاء AudioConfig مثيل باستخدام الدالة fromDefaultSpeakerOutput() الثابتة. إليك مثال:

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

الحصول على نتيجة كتيار في الذاكرة

يمكنك استخدام البيانات الصوتية الناتجة كتدفق في الذاكرة بدلا من الكتابة مباشرة إلى ملف. مع دفق الذاكرة، يمكنك إنشاء سلوك مخصص:

  • تلخيص مصفوفة البايت الناتجة كدفق يمكن البحث عنه لخدمات المصب المخصصة.
  • دمج النتيجة مع API أو الخدمات الأخرى.
  • تعديل البيانات الصوتية، وكتابة عناوين .wav مخصصة، والقيام بالمهام ذات الصلة.

يمكنك إجراء هذا التغيير على المثال السابق. أولا، قم بإزالة AudioConfig الكتلة، لأنك تدير سلوك الإخراج يدويا من هذه النقطة فصاعدا لزيادة التحكم. ثم مرر null لـAudioConfig في الدالة الإنشائية SpeechSynthesizer.

إشعار

nullAudioConfigلا يؤدي تمرير ل ، بدلا من حذفه كما فعلت في مثال إخراج السماعة السابق، إلى تشغيل الصوت بشكل افتراضي على جهاز الإخراج النشط الحالي.

حفظ النتيجة إلى SpeechSynthesisResult متغير. ترجع الوظيفة SpeechSynthesisResult.getAudioData() مثيل byte [] لبيانات الإخراج. يمكنك العمل مع مثيل byte [] هذا يدويًا، أو يمكنك استخدام فئة AudioDataStream لإدارة التدفق داخل الذاكرة.

في هذا المثال، استخدم الدالة AudioDataStream.fromResult() الثابتة للحصول على دفق من النتيجة:

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

في هذه المرحلة، يمكنك تنفيذ أي سلوك مخصص باستخدام الكائن الناتج stream .

تخصيص تنسيق الصوت

يمكنك تخصيص سمات إخراج الصوت، بما في ذلك:

  • نوع ملف الصوت
  • معدل العينة
  • عمق البت

لتغيير تنسيق الصوت، يمكنك استخدام الدالة setSpeechSynthesisOutputFormat() المخصصة للكائن SpeechConfig. تتوقع هذه الدالة مثيلا enum من النوع SpeechSynthesisOutputFormat. enum استخدم لتحديد تنسيق الإخراج. للحصول على التنسيقات المتوفرة ، راجع قائمة تنسيقات الصوت.

هناك خيارات مختلفة لأنواع الملفات المختلفة اعتمادًا على المتطلبات الخاصة بك. حسب التعريف، لا تتضمن التنسيقات البسيطة مثل Raw24Khz16BitMonoPcm رؤوس الصوت. استخدم التنسيقات الأولية فقط في إحدى هذه الحالات:

  • أنت تعلم أن تنفيذ انتقال البيانات من الخادم الخاص بك يمكن أن يفك تشفير bitstream الخام.
  • تخطط لإنشاء رؤوس يدويا استنادا إلى عوامل مثل عمق البت ومعدل العينة وعدد القنوات.

يحدد هذا المثال تنسيق Riff24Khz16BitMonoPcm RIFF عالي الدقة عن طريق تعيين SpeechSynthesisOutputFormat على SpeechConfig العنصر . على غرار المثال الوارد في القسم السابق، يمكنك استخدام AudioDataStream للحصول على دفق في الذاكرة من النتيجة، ومن ثم كتابته إلى ملف.

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

عند تشغيل البرنامج، فإنه يكتب ملف .wav إلى المسار المحدد.

استخدام لغة ترميز تركيب الكلام (SSML) لتخصيص خصائص الكلام

يمكنك استخدام SSML لضبط درجة الصوت والنطق ومعدل التحدث والحجم والجوانب الأخرى في إخراج النص إلى الكلام عن طريق إرسال طلباتك من مخطط XML. يعرض هذا القسم مثالاً على تغيير الصوت. لمزيد من المعلومات، راجع مقالة كيفية SSML.

لبدء استخدام SSML للتخصيص، يمكنك إجراء تغيير طفيف يقوم بتبديل الصوت.

  1. إنشاء ملف XML جديد لتكوين SSML في دليل المشروع الجذر الخاص بك.

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

    في هذا المثال، يتم ssml.xml الملف. العنصر الجذر هو دائمًا <speak>. يتيح لك التفاف النص في عنصر <voice> تغيير الصوت باستخدام المعلمة name. للحصول على القائمة الكاملة للأصوات العصبية المدعومة، راجع اللغات المدعومة.

  2. قم بتغيير طلب تركيب الكلام للإشارة إلى ملف XML الخاص بك. الطلب هو نفسه في الغالب. بدلا من استخدام الدالة SpeakText() ، يمكنك استخدام SpeakSsml(). تتوقع هذه الدالة سلسلة XML، لذا قم أولا بإنشاء دالة لتحميل ملف XML وإعادته كسلسلة:

    private static String xmlToString(String filePath) {
        File file = new File(filePath);
        StringBuilder fileContents = new StringBuilder((int)file.length());
    
        try (Scanner scanner = new Scanner(file)) {
            while(scanner.hasNextLine()) {
                fileContents.append(scanner.nextLine() + System.lineSeparator());
            }
            return fileContents.toString().trim();
        } catch (FileNotFoundException ex) {
            return "File not found.";
        }
    }
    

    عند هذه النقطة، كائن النتيجة هو بالضبط نفس الأمثلة السابقة:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("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");
    }
    

إشعار

لتغيير الصوت دون استخدام SSML، قم بتعيين الخاصية على SpeechConfig باستخدام SpeechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");.

الاشتراك في أحداث synthesizer

قد تحتاج إلى مزيد من الرؤى حول معالجة النص إلى الكلام والنتائج. على سبيل المثال، قد ترغب في معرفة متى يبدأ التركيب ويتوقف، أو قد ترغب في معرفة الأحداث الأخرى التي تمت مواجهتها أثناء التركيب.

أثناء استخدام SpeechSynthesizer لتحويل النص إلى كلام، يمكنك الاشتراك في الأحداث في هذا الجدول:

حدث ‏‏الوصف حالة الاستخدام
BookmarkReached إشارات إلى أنه تم الوصول إلى إشارة مرجعية. لتشغيل حدث تم الوصول إليه بإشارة مرجعية، يلزم وجود bookmark عنصر في SSML. يبلغ هذا الحدث عن الوقت المنقضي لصوت الإخراج بين بداية التركيب والعنصر bookmark . خاصية الحدث Text هي قيمة السلسلة التي قمت بتعيينها في سمة الإشارة المرجعية mark . bookmark العناصر غير منطوقة. يمكنك استخدام العنصر bookmark لإدراج علامات مخصصة في SSML للحصول على إزاحة كل علامة في دفق الصوت. يمكن استخدام العنصر bookmark للإشارة إلى موقع معين في تسلسل العلامة أو النص.
SynthesisCanceled إشارات إلى إلغاء تركيب الكلام. يمكنك التأكيد عند إلغاء التركيب.
SynthesisCompleted إشارات إلى اكتمال تركيب الكلام. يمكنك تأكيد عند اكتمال التركيب.
SynthesisStarted إشارات إلى أن تركيب الكلام بدأ. يمكنك التأكيد عند بدء التركيب.
Synthesizing إشارات إلى أن تركيب الكلام مستمر. يتم تشغيل هذا الحدث في كل مرة يتلقى فيها SDK مجموعة صوتية من خدمة الكلام. يمكنك تأكيد وقت التركيب قيد التقدم.
VisemeReceived إشارات إلى تلقي حدث viseme. Visemes غالبا ما تستخدم لتمثيل الأوضاع الرئيسية في الكلام الملاحظ. تشمل الأوضاع الرئيسية موضع الشفاه والفك واللسان في إنتاج مقطع صوتي معين. يمكنك استخدام visemes لتحريك وجه الحرف أثناء تشغيل صوت الكلام.
WordBoundary يشير إلى تلقي حد كلمة. يتم رفع هذا الحدث في بداية كل كلمة منطوقة جديدة وعلامات ترقيم وجملة. يبلغ الحدث عن إزاحة وقت الكلمة الحالية، في علامات التجزئة، من بداية صوت الإخراج. يقوم هذا الحدث أيضا بالإبلاغ عن موضع الحرف في نص الإدخال أو SSML مباشرة قبل الكلمة التي على وشك التحدث بها. يستخدم هذا الحدث بشكل شائع للحصول على المواضع النسبية للنص والصوت المقابل. قد ترغب في معرفة كلمة جديدة، ثم اتخاذ إجراء بناء على التوقيت. على سبيل المثال، يمكنك الحصول على معلومات يمكن أن تساعدك في تحديد متى ومدة تمييز الكلمات أثناء نطقها.

إشعار

يتم رفع الأحداث مع توفر بيانات صوت الإخراج، وهو أسرع من التشغيل على جهاز إخراج. يجب على المتصل مزامنة الدفق وفي الوقت الحقيقي بشكل مناسب.

فيما يلي مثال يوضح كيفية الاشتراك في أحداث تركيب الكلام. يمكنك اتباع الإرشادات الواردة في التشغيل السريع، ولكن استبدال محتويات ملف SpeechSynthesis.java هذا برمز Java التالي:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        System.exit(0);
    }
}

يمكنك العثور على المزيد من النص إلى عينات الكلام في GitHub.

استخدم نقطة نهاية مخصصة

نقطة النهاية المخصصة مطابقة وظيفيا لنقطة النهاية القياسية المستخدمة لطلبات النص إلى الكلام.

أحد الاختلافات هو أنه EndpointId يجب تحديد لاستخدام صوتك المخصص عبر Speech SDK. يمكنك البدء بالنص إلى التشغيل السريع للكلام ثم تحديث التعليمات البرمجية باستخدام EndpointId و SpeechSynthesisVoiceName.

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

لاستخدام صوت مخصص عبر Speech Synthesis Markup Language (SSML)، حدد اسم النموذج كاسم صوتي. يستخدم هذا المثال الصوت YourCustomVoiceName.

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

تشغيل حاوية واستخدامها

توفر حاويات الكلام واجهات برمجة تطبيقات نقطة نهاية الاستعلام المستندة إلى websocket التي يتم الوصول إليها من خلال Speech SDK و Speech CLI. بشكل افتراضي، يستخدم Speech SDK و Speech CLI خدمة Speech العامة. لاستخدام الحاوية، تحتاج إلى تغيير أسلوب التهيئة. استخدم عنوان URL لمضيف الحاوية بدلا من المفتاح والمنطقة.

لمزيد من المعلومات حول الحاويات، راجع تثبيت حاويات الكلام وتشغيلها باستخدام Docker.

حزمة | الوثائق المرجعية (npm) | عينات إضافية على GitHub | التعليمة البرمجية لمصدر المكتبة

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

حدد اللغة والصوت الاصطناعيين

تدعم ميزة تحويل النص إلى كلام في خدمة الكلام أكثر من 400 صوت وأكثر من 140 لغة ومتغيرا. يمكنك الحصول على القائمة الكاملة أو تجربتها في معرض الصوت.

حدد لغة أو صوت SpeechConfig لمطابقة نص الإدخال واستخدام الصوت المحدد:

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

جميع الأصوات العصبية هي متعددة اللغات وطلاقة في لغتهم الخاصة والإنجليزية. على سبيل المثال، إذا كان نص الإدخال باللغة الإنجليزية هو ، "أنا متحمس لتجربة النص إلى كلام"، وحددت es-ES-ElviraNeural، يتم التحدث بالنص باللغة الإنجليزية بلكنة إسبانية.

إذا كان الصوت لا يتحدث لغة نص الإدخال، فلن تنشئ خدمة الكلام الصوت المركب. للحصول على قائمة كاملة بالأصوات العصبية المدعومة، راجع دعم اللغة والصوت لخدمة الكلام.

إشعار

الصوت الافتراضي هو أول صوت يتم إرجاعه لكل لغة من واجهة برمجة تطبيقات القائمة الصوتية.

يتم تحديد الصوت الذي يتحدث بترتيب الأولوية كما يلي:

  • إذا لم تقم بتعيين SpeechSynthesisVoiceName أو SpeechSynthesisLanguage، فإن الصوت الافتراضي للتحدث en-US .
  • إذا قمت بتعيين SpeechSynthesisLanguageفقط ، فإن الصوت الافتراضي للإعدادات المحلية المحددة يتحدث.
  • إذا تم تعيين كل من SpeechSynthesisVoiceName وSpeechSynthesisLanguage، SpeechSynthesisLanguage يتم تجاهل الإعداد. الصوت الذي تحدده باستخدام SpeechSynthesisVoiceName يتحدث.
  • إذا تم تعيين عنصر الصوت باستخدام لغة ترميز تركيب الكلام (SSML)،SpeechSynthesisVoiceName يتم تجاهل الإعدادات وSpeechSynthesisLanguage.

تجميع النص إلى كلام

لإخراج الكلام المركب إلى جهاز الإخراج النشط الحالي مثل مكبر الصوت، قم بإنشاء AudioConfig مثيل باستخدام الدالة fromDefaultSpeakerOutput() الثابتة. إليك مثال:

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

عند تشغيل البرنامج، يتم تشغيل الصوت المركب من السماعة. هذه النتيجة هي مثال جيد على الاستخدام الأساسي. بعد ذلك، يمكنك تخصيص الإخراج ومعالجة استجابة الإخراج كتدفق في الذاكرة للعمل مع سيناريوهات مخصصة.

الحصول على نتيجة كتيار في الذاكرة

يمكنك استخدام البيانات الصوتية الناتجة كتدفق في الذاكرة بدلا من الكتابة مباشرة إلى ملف. مع دفق الذاكرة، يمكنك إنشاء سلوك مخصص:

  • تلخيص مصفوفة البايت الناتجة كدفق يمكن البحث عنه لخدمات المصب المخصصة.
  • دمج النتيجة مع API أو الخدمات الأخرى.
  • تعديل البيانات الصوتية، وكتابة عناوين .wav مخصصة، والقيام بالمهام ذات الصلة.

يمكنك إجراء هذا التغيير على المثال السابق. قم بإزالة AudioConfig الكتلة، لأنك تدير سلوك الإخراج يدويا من هذه النقطة فصاعدا لزيادة التحكم. ثم مرر null لـAudioConfig في الدالة الإنشائية SpeechSynthesizer.

إشعار

nullAudioConfigلا يؤدي تمرير ل ، بدلا من حذفه كما فعلت في مثال إخراج السماعة السابق، إلى تشغيل الصوت بشكل افتراضي على جهاز الإخراج النشط الحالي.

احفظ النتيجة إلى متغير SpeechSynthesisResult . تقوم خاصية SpeechSynthesisResult.audioData بإرجاع قيمة ArrayBuffer من بيانات الإخراج، نوع تدفق المستعرض الافتراضي. بالنسبة للتعليمات البرمجية من جانب الخادم، قم بتحويل ArrayBuffer إلى دفق مخزن مؤقت.

تعمل التعليمات البرمجية التالية لصالح العميل:

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

يمكنك تنفيذ أي سلوك مخصص باستخدام الكائن الناتج ArrayBuffer . ArrayBuffer هو نوع شائع لتلقيه في المستعرض والتشغيل من هذا التنسيق.

لأي رمز مستند إلى الخادم، إذا كنت بحاجة إلى العمل مع البيانات كتدفق، فأنت بحاجة إلى تحويل عنصر ArrayBuffer إلى دفق:

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

تخصيص تنسيق الصوت

يمكنك تخصيص سمات إخراج الصوت، بما في ذلك:

  • نوع ملف الصوت
  • معدل العينة
  • عمق البت

لتغيير تنسيق الصوت، استخدم الخاصية الموجودة speechSynthesisOutputFormat على SpeechConfig الكائن. تتوقع هذه الخاصية مثيلا enum من النوع SpeechSynthesisOutputFormat. enum استخدم لتحديد تنسيق الإخراج. للحصول على التنسيقات المتوفرة ، راجع قائمة تنسيقات الصوت.

هناك خيارات مختلفة لأنواع الملفات المختلفة اعتمادًا على المتطلبات الخاصة بك. حسب التعريف، لا تتضمن التنسيقات البسيطة مثل Raw24Khz16BitMonoPcm رؤوس الصوت. استخدم التنسيقات الأولية فقط في إحدى هذه الحالات:

  • أنت تعلم أن تنفيذ انتقال البيانات من الخادم الخاص بك يمكن أن يفك تشفير bitstream الخام.
  • تخطط لإنشاء رؤوس يدويا استنادا إلى عوامل مثل عمق البت ومعدل العينة وعدد القنوات.

يحدد هذا المثال تنسيق Riff24Khz16BitMonoPcm RIFF عالي الدقة عن طريق تعيين speechSynthesisOutputFormat على SpeechConfig العنصر . على غرار المثال في القسم السابق، احصل على بيانات ArrayBuffer الصوتية وتفاعل معها.

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

استخدام لغة ترميز تركيب الكلام (SSML) لتخصيص خصائص الكلام

يمكنك استخدام SSML لضبط درجة الصوت والنطق ومعدل التحدث والحجم والجوانب الأخرى في إخراج النص إلى الكلام عن طريق إرسال طلباتك من مخطط XML. يعرض هذا القسم مثالاً على تغيير الصوت. لمزيد من المعلومات، راجع نظرة عامة على لغة ترميز تركيب الكلام.

لبدء استخدام SSML للتخصيص، يمكنك إجراء تغيير طفيف يقوم بتبديل الصوت.

  1. إنشاء ملف XML جديد لتكوين SSML في دليل المشروع الجذر الخاص بك.

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

    في هذا المثال، ssml.xml. العنصر الجذر هو دائمًا <speak>. يتيح لك التفاف النص في عنصر <voice> تغيير الصوت باستخدام المعلمة name. للحصول على القائمة الكاملة للأصوات العصبية المدعومة، راجع اللغات المدعومة.

  2. قم بتغيير طلب تركيب الكلام للإشارة إلى ملف XML الخاص بك. سيكون الطلب هو نفسه في الغالب، ولكن بدلاً من استخدام دالةspeakTextAsync()، يمكنك استخدام speakSsmlAsync(). تتوقع هذه الدالة سلسلة XML. إنشاء دالة لتحميل ملف XML وإعادته كسلسلة:

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

    لمزيد من المعلومات حول readFileSync، راجع نظام ملفات Node.js.

    كائن النتيجة هو بالضبط نفس الأمثلة السابقة:

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

إشعار

لتغيير الصوت دون استخدام لغة ترميز تركيب الكلام (SSML)، يمكنك تعيين الخاصية على SpeechConfig باستخدام SpeechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

الاشتراك في أحداث synthesizer

قد تحتاج إلى مزيد من الرؤى حول معالجة النص إلى الكلام والنتائج. على سبيل المثال، قد ترغب في معرفة متى يبدأ التركيب ويتوقف، أو قد ترغب في معرفة الأحداث الأخرى التي تمت مواجهتها أثناء التركيب.

أثناء استخدام SpeechSynthesizer لتحويل النص إلى كلام، يمكنك الاشتراك في الأحداث في هذا الجدول:

حدث ‏‏الوصف حالة الاستخدام
BookmarkReached إشارات إلى أنه تم الوصول إلى إشارة مرجعية. لتشغيل حدث تم الوصول إليه بإشارة مرجعية، يلزم وجود bookmark عنصر في SSML. يبلغ هذا الحدث عن الوقت المنقضي لصوت الإخراج بين بداية التركيب والعنصر bookmark . خاصية الحدث Text هي قيمة السلسلة التي قمت بتعيينها في سمة الإشارة المرجعية mark . bookmark العناصر غير منطوقة. يمكنك استخدام العنصر bookmark لإدراج علامات مخصصة في SSML للحصول على إزاحة كل علامة في دفق الصوت. يمكن استخدام العنصر bookmark للإشارة إلى موقع معين في تسلسل العلامة أو النص.
SynthesisCanceled إشارات إلى إلغاء تركيب الكلام. يمكنك التأكيد عند إلغاء التركيب.
SynthesisCompleted إشارات إلى اكتمال تركيب الكلام. يمكنك تأكيد عند اكتمال التركيب.
SynthesisStarted إشارات إلى أن تركيب الكلام بدأ. يمكنك التأكيد عند بدء التركيب.
Synthesizing إشارات إلى أن تركيب الكلام مستمر. يتم تشغيل هذا الحدث في كل مرة يتلقى فيها SDK مجموعة صوتية من خدمة الكلام. يمكنك تأكيد وقت التركيب قيد التقدم.
VisemeReceived إشارات إلى تلقي حدث viseme. Visemes غالبا ما تستخدم لتمثيل الأوضاع الرئيسية في الكلام الملاحظ. تشمل الأوضاع الرئيسية موضع الشفاه والفك واللسان في إنتاج مقطع صوتي معين. يمكنك استخدام visemes لتحريك وجه الحرف أثناء تشغيل صوت الكلام.
WordBoundary يشير إلى تلقي حد كلمة. يتم رفع هذا الحدث في بداية كل كلمة منطوقة جديدة وعلامات ترقيم وجملة. يبلغ الحدث عن إزاحة وقت الكلمة الحالية، في علامات التجزئة، من بداية صوت الإخراج. يقوم هذا الحدث أيضا بالإبلاغ عن موضع الحرف في نص الإدخال أو SSML مباشرة قبل الكلمة التي على وشك التحدث بها. يستخدم هذا الحدث بشكل شائع للحصول على المواضع النسبية للنص والصوت المقابل. قد ترغب في معرفة كلمة جديدة، ثم اتخاذ إجراء بناء على التوقيت. على سبيل المثال، يمكنك الحصول على معلومات يمكن أن تساعدك في تحديد متى ومدة تمييز الكلمات أثناء نطقها.

إشعار

يتم رفع الأحداث مع توفر بيانات صوت الإخراج، وهو أسرع من التشغيل على جهاز إخراج. يجب على المتصل مزامنة الدفق وفي الوقت الحقيقي بشكل مناسب.

فيما يلي مثال يوضح كيفية الاشتراك في أحداث تركيب الكلام. يمكنك اتباع الإرشادات في التشغيل السريع، ولكن استبدال محتويات هذا الملف SpeechSynthesis.js بالتعليمة البرمجية JavaScript التالية.

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

يمكنك العثور على المزيد من النص إلى عينات الكلام في GitHub.

تشغيل حاوية واستخدامها

توفر حاويات الكلام واجهات برمجة تطبيقات نقطة نهاية الاستعلام المستندة إلى websocket التي يتم الوصول إليها من خلال Speech SDK و Speech CLI. بشكل افتراضي، يستخدم Speech SDK و Speech CLI خدمة Speech العامة. لاستخدام الحاوية، تحتاج إلى تغيير أسلوب التهيئة. استخدم عنوان URL لمضيف الحاوية بدلا من المفتاح والمنطقة.

لمزيد من المعلومات حول الحاويات، راجع تثبيت حاويات الكلام وتشغيلها باستخدام Docker.

الوثائق المرجعية | حزمة (التنزيل) | نماذج إضافية على GitHub

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

المتطلبات الأساسية

تثبيت Speech SDK والعينات

يحتوي مستودع Azure-Samples/cognitive-services-speech-sdk على عينات مكتوبة في Objective-C لنظامي التشغيل iOS وMac. حدد ارتباطاً للاطلاع على إرشادات التثبيت لكل نموذج:

استخدم نقطة نهاية مخصصة

نقطة النهاية المخصصة مطابقة وظيفيا لنقطة النهاية القياسية المستخدمة لطلبات النص إلى الكلام.

أحد الاختلافات هو أنه EndpointId يجب تحديد لاستخدام صوتك المخصص عبر Speech SDK. يمكنك البدء بالنص إلى التشغيل السريع للكلام ثم تحديث التعليمات البرمجية باستخدام EndpointId و SpeechSynthesisVoiceName.

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

لاستخدام صوت مخصص عبر Speech Synthesis Markup Language (SSML)، حدد اسم النموذج كاسم صوتي. يستخدم هذا المثال الصوت YourCustomVoiceName.

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

تشغيل حاوية واستخدامها

توفر حاويات الكلام واجهات برمجة تطبيقات نقطة نهاية الاستعلام المستندة إلى websocket التي يتم الوصول إليها من خلال Speech SDK و Speech CLI. بشكل افتراضي، يستخدم Speech SDK و Speech CLI خدمة Speech العامة. لاستخدام الحاوية، تحتاج إلى تغيير أسلوب التهيئة. استخدم عنوان URL لمضيف الحاوية بدلا من المفتاح والمنطقة.

لمزيد من المعلومات حول الحاويات، راجع تثبيت حاويات الكلام وتشغيلها باستخدام Docker.

الوثائق المرجعية | حزمة (التنزيل) | نماذج إضافية على GitHub

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

المتطلبات الأساسية

تثبيت Speech SDK والعينات

يحتوي مستودع Azure-Samples / cognitive-services-speech-sdk على عينات مكتوبة في Swift لنظامي التشغيل iOS و Mac. حدد ارتباطاً للاطلاع على إرشادات التثبيت لكل نموذج:

تشغيل حاوية واستخدامها

توفر حاويات الكلام واجهات برمجة تطبيقات نقطة نهاية الاستعلام المستندة إلى websocket التي يتم الوصول إليها من خلال Speech SDK و Speech CLI. بشكل افتراضي، يستخدم Speech SDK و Speech CLI خدمة Speech العامة. لاستخدام الحاوية، تحتاج إلى تغيير أسلوب التهيئة. استخدم عنوان URL لمضيف الحاوية بدلا من المفتاح والمنطقة.

لمزيد من المعلومات حول الحاويات، راجع تثبيت حاويات الكلام وتشغيلها باستخدام Docker.

حزمة الوثائق المرجعية | (PyPi) | عينات إضافية على GitHub

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

حدد اللغة والصوت الاصطناعيين

تدعم ميزة تحويل النص إلى كلام في خدمة الكلام أكثر من 400 صوت وأكثر من 140 لغة ومتغيرا. يمكنك الحصول على القائمة الكاملة أو تجربتها في معرض الصوت.

حدد لغة أو صوت SpeechConfig لمطابقة نص الإدخال واستخدام الصوت المحدد:

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

جميع الأصوات العصبية هي متعددة اللغات وطلاقة في لغتهم الخاصة والإنجليزية. على سبيل المثال، إذا كان نص الإدخال باللغة الإنجليزية هو ، "أنا متحمس لتجربة النص إلى كلام"، وحددت es-ES-ElviraNeural، يتم التحدث بالنص باللغة الإنجليزية بلكنة إسبانية.

إذا كان الصوت لا يتحدث لغة نص الإدخال، فلن تنشئ خدمة الكلام الصوت المركب. للحصول على قائمة كاملة بالأصوات العصبية المدعومة، راجع دعم اللغة والصوت لخدمة الكلام.

إشعار

الصوت الافتراضي هو أول صوت يتم إرجاعه لكل لغة من واجهة برمجة تطبيقات القائمة الصوتية.

يتم تحديد الصوت الذي يتحدث بترتيب الأولوية كما يلي:

  • إذا لم تقم بتعيين SpeechSynthesisVoiceName أو SpeechSynthesisLanguage، فإن الصوت الافتراضي للتحدث en-US .
  • إذا قمت بتعيين SpeechSynthesisLanguageفقط ، فإن الصوت الافتراضي للإعدادات المحلية المحددة يتحدث.
  • إذا تم تعيين كل من SpeechSynthesisVoiceName وSpeechSynthesisLanguage، SpeechSynthesisLanguage يتم تجاهل الإعداد. الصوت الذي تحدده باستخدام SpeechSynthesisVoiceName يتحدث.
  • إذا تم تعيين عنصر الصوت باستخدام لغة ترميز تركيب الكلام (SSML)،SpeechSynthesisVoiceName يتم تجاهل الإعدادات وSpeechSynthesisLanguage.

تجميع الكلام إلى ملف

إنشاء كائن SpeechSynthesizer . يقوم هذا الكائن بتشغيل تحويلات النص إلى الكلام والمخرجات إلى السماعات أو الملفات أو تدفقات الإخراج الأخرى. SpeechSynthesizer يقبل كمعلمات:

  • SpeechConfig الكائن الذي قمت بإنشائه في الخطوة السابقة.
  • كائن AudioOutputConfig يحدد كيفية معالجة نتائج الإخراج.
  1. إنشاء مثيل AudioOutputConfig لكتابة الإخراج تلقائيا إلى ملف .wav باستخدام معلمة الدالة filename الإنشائية:

    audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
    
  2. إنشاء SpeechSynthesizer مثيل عن طريق تمرير الكائن الخاص بك speech_config والعنصر audio_config كمعلمات. لتجميع الكلام والكتابة إلى ملف، قم بتشغيل speak_text_async() بسلسلة نصية.

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

عند تشغيل البرنامج، فإنه ينشئ ملف .wav مركب، والذي تتم كتابته إلى الموقع الذي تحدده. هذه النتيجة هي مثال جيد على الاستخدام الأساسي. بعد ذلك، يمكنك تخصيص الإخراج ومعالجة استجابة الإخراج كتدفق في الذاكرة للعمل مع سيناريوهات مخصصة.

توليف لإخراج مكبر الصوت

لإخراج الكلام المركب إلى جهاز الإخراج النشط الحالي مثل مكبر الصوت، قم بتعيين المعلمة use_default_speaker عند إنشاء المثيل AudioOutputConfig . إليك مثال:

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

الحصول على نتيجة كتيار في الذاكرة

يمكنك استخدام البيانات الصوتية الناتجة كتدفق في الذاكرة بدلا من الكتابة مباشرة إلى ملف. مع دفق الذاكرة، يمكنك إنشاء سلوك مخصص:

  • تلخيص مصفوفة البايت الناتجة كدفق يمكن البحث عنه لخدمات المصب المخصصة.
  • دمج النتيجة مع API أو الخدمات الأخرى.
  • تعديل البيانات الصوتية وكتابة عناوين .wav مخصصة وتنفيذ المهام ذات الصلة.

يمكنك إجراء هذا التغيير على المثال السابق. أولا، قم بإزالة AudioConfig، لأنك تدير سلوك الإخراج يدويا من هذه النقطة فصاعدا لزيادة التحكم. تمرير None ل AudioConfig في الدالة SpeechSynthesizer الإنشائية.

إشعار

NoneAudioConfigلا يؤدي تمرير ل ، بدلا من حذفه كما فعلت في مثال إخراج السماعة السابق، إلى تشغيل الصوت بشكل افتراضي على جهاز الإخراج النشط الحالي.

حفظ النتيجة إلى SpeechSynthesisResult متغير. تحتوي خاصية audio_data على كائن bytes من بيانات الإخراج. يمكنك التعاون مع كائن يدويًا أو يمكنك استخدام الفئة AudioDataStream لإدارة التدفق داخل الذاكرة.

في هذا المثال، استخدم الدالة AudioDataStream الإنشائية للحصول على دفق من النتيجة:

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)

في هذه المرحلة، يمكنك تنفيذ أي سلوك مخصص باستخدام الكائن الناتج stream .

تخصيص تنسيق الصوت

يمكنك تخصيص سمات إخراج الصوت، بما في ذلك:

  • نوع ملف الصوت
  • معدل العينة
  • عمق البت

لتغيير تنسيق الصوت، استخدم الدالة set_speech_synthesis_output_format() الموجودة على SpeechConfig الكائن. تتوقع هذه الدالة مثيلا enum من النوع SpeechSynthesisOutputFormat. enum استخدم لتحديد تنسيق الإخراج. للحصول على التنسيقات المتوفرة ، راجع قائمة تنسيقات الصوت.

هناك خيارات مختلفة لأنواع الملفات المختلفة اعتمادًا على المتطلبات الخاصة بك. حسب التعريف، لا تتضمن التنسيقات البسيطة مثل Raw24Khz16BitMonoPcm رؤوس الصوت. استخدم التنسيقات الأولية فقط في إحدى هذه الحالات:

  • أنت تعلم أن تنفيذ انتقال البيانات من الخادم الخاص بك يمكن أن يفك تشفير bitstream الخام.
  • تخطط لإنشاء رؤوس يدويا استنادا إلى عوامل مثل عمق البت ومعدل العينة وعدد القنوات.

يحدد هذا المثال تنسيق Riff24Khz16BitMonoPcm RIFF عالي الدقة عن طريق تعيين SpeechSynthesisOutputFormat على SpeechConfig العنصر . على غرار المثال الوارد في القسم السابق، يمكنك استخدام AudioDataStream للحصول على دفق في الذاكرة من النتيجة، ومن ثم كتابته إلى ملف.

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

عند تشغيل البرنامج، فإنه يكتب ملف .wav إلى المسار المحدد.

استخدام لغة ترميز تركيب الكلام (SSML) لتخصيص خصائص الكلام

يمكنك استخدام SSML لضبط درجة الصوت والنطق ومعدل التحدث والحجم والجوانب الأخرى في إخراج النص إلى الكلام عن طريق إرسال طلباتك من مخطط XML. يعرض هذا القسم مثالاً على تغيير الصوت. لمزيد من المعلومات، راجع نظرة عامة على لغة ترميز تركيب الكلام.

لبدء استخدام SSML للتخصيص، قم بإجراء تغيير طفيف يقوم بتبديل الصوت.

  1. إنشاء ملف XML جديد لتكوين SSML في دليل المشروع الجذر الخاص بك.

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

    في هذا المثال، يتم ssml.xml الملف. العنصر الجذر هو دائمًا <speak>. يتيح لك التفاف النص في عنصر <voice> تغيير الصوت باستخدام المعلمة name. للحصول على القائمة الكاملة للأصوات العصبية المدعومة، راجع اللغات المدعومة.

  2. قم بتغيير طلب تركيب الكلام للإشارة إلى ملف XML الخاص بك. الطلب هو نفسه في الغالب. بدلا من استخدام الدالة speak_text_async() ، استخدم speak_ssml_async(). تتوقع هذه الدالة سلسلة XML. اقرأ أولا تكوين SSML كسلسلة. من هذه النقطة، كائن النتيجة هو بالضبط نفس الأمثلة السابقة.

    إشعار

    إذا كان يحتوي ssml_string لديك على  في بداية السلسلة، فأنت بحاجة إلى إزالة تنسيق BOM وإلا سيؤدي ذلك إلى حدوث خطأ في الخدمة. يمكنك القيام بذلك عن طريق تعيين معلمة encoding على النحو التالي: 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")
    

إشعار

لتغيير الصوت دون استخدام لغة ترميز تركيب الكلام (SSML)، يمكنك تعيين الخاصية على SpeechConfig باستخدام speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural".

الاشتراك في أحداث synthesizer

قد تحتاج إلى مزيد من الرؤى حول معالجة النص إلى الكلام والنتائج. على سبيل المثال، قد ترغب في معرفة متى يبدأ التركيب ويتوقف، أو قد ترغب في معرفة الأحداث الأخرى التي تمت مواجهتها أثناء التركيب.

أثناء استخدام SpeechSynthesizer لتحويل النص إلى كلام، يمكنك الاشتراك في الأحداث في هذا الجدول:

حدث ‏‏الوصف حالة الاستخدام
BookmarkReached إشارات إلى أنه تم الوصول إلى إشارة مرجعية. لتشغيل حدث تم الوصول إليه بإشارة مرجعية، يلزم وجود bookmark عنصر في SSML. يبلغ هذا الحدث عن الوقت المنقضي لصوت الإخراج بين بداية التركيب والعنصر bookmark . خاصية الحدث Text هي قيمة السلسلة التي قمت بتعيينها في سمة الإشارة المرجعية mark . bookmark العناصر غير منطوقة. يمكنك استخدام العنصر bookmark لإدراج علامات مخصصة في SSML للحصول على إزاحة كل علامة في دفق الصوت. يمكن استخدام العنصر bookmark للإشارة إلى موقع معين في تسلسل العلامة أو النص.
SynthesisCanceled إشارات إلى إلغاء تركيب الكلام. يمكنك التأكيد عند إلغاء التركيب.
SynthesisCompleted إشارات إلى اكتمال تركيب الكلام. يمكنك تأكيد عند اكتمال التركيب.
SynthesisStarted إشارات إلى أن تركيب الكلام بدأ. يمكنك التأكيد عند بدء التركيب.
Synthesizing إشارات إلى أن تركيب الكلام مستمر. يتم تشغيل هذا الحدث في كل مرة يتلقى فيها SDK مجموعة صوتية من خدمة الكلام. يمكنك تأكيد وقت التركيب قيد التقدم.
VisemeReceived إشارات إلى تلقي حدث viseme. Visemes غالبا ما تستخدم لتمثيل الأوضاع الرئيسية في الكلام الملاحظ. تشمل الأوضاع الرئيسية موضع الشفاه والفك واللسان في إنتاج مقطع صوتي معين. يمكنك استخدام visemes لتحريك وجه الحرف أثناء تشغيل صوت الكلام.
WordBoundary يشير إلى تلقي حد كلمة. يتم رفع هذا الحدث في بداية كل كلمة منطوقة جديدة وعلامات ترقيم وجملة. يبلغ الحدث عن إزاحة وقت الكلمة الحالية، في علامات التجزئة، من بداية صوت الإخراج. يقوم هذا الحدث أيضا بالإبلاغ عن موضع الحرف في نص الإدخال أو SSML مباشرة قبل الكلمة التي على وشك التحدث بها. يستخدم هذا الحدث بشكل شائع للحصول على المواضع النسبية للنص والصوت المقابل. قد ترغب في معرفة كلمة جديدة، ثم اتخاذ إجراء بناء على التوقيت. على سبيل المثال، يمكنك الحصول على معلومات يمكن أن تساعدك في تحديد متى ومدة تمييز الكلمات أثناء نطقها.

إشعار

يتم رفع الأحداث مع توفر بيانات صوت الإخراج، وهو أسرع من التشغيل على جهاز إخراج. يجب على المتصل مزامنة الدفق وفي الوقت الحقيقي بشكل مناسب.

فيما يلي مثال يوضح كيفية الاشتراك في أحداث تركيب الكلام. يمكنك اتباع الإرشادات الموجودة في التشغيل السريع، ولكن استبدال محتويات هذا الملف speech-synthesis.py برمز Python التالي:

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

يمكنك العثور على المزيد من النص إلى عينات الكلام في GitHub.

استخدم نقطة نهاية مخصصة

نقطة النهاية المخصصة مطابقة وظيفيا لنقطة النهاية القياسية المستخدمة لطلبات النص إلى الكلام.

أحد الاختلافات هو أنه endpoint_id يجب تحديد لاستخدام صوتك المخصص عبر Speech SDK. يمكنك البدء بالنص إلى التشغيل السريع للكلام ثم تحديث التعليمات البرمجية باستخدام endpoint_id و 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"

لاستخدام صوت مخصص عبر Speech Synthesis Markup Language (SSML)، حدد اسم النموذج كاسم صوتي. يستخدم هذا المثال الصوت YourCustomVoiceName.

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

تشغيل حاوية واستخدامها

توفر حاويات الكلام واجهات برمجة تطبيقات نقطة نهاية الاستعلام المستندة إلى websocket التي يتم الوصول إليها من خلال Speech SDK و Speech CLI. بشكل افتراضي، يستخدم Speech SDK و Speech CLI خدمة Speech العامة. لاستخدام الحاوية، تحتاج إلى تغيير أسلوب التهيئة. استخدم عنوان URL لمضيف الحاوية بدلا من المفتاح والمنطقة.

لمزيد من المعلومات حول الحاويات، راجع تثبيت حاويات الكلام وتشغيلها باستخدام Docker.

يشير | Speech to text REST API إلى Speech to text REST API for short audio reference | Additional Samples on GitHub

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

المتطلبات الأساسية

تحويل النص إلى كلام

في موجه الأوامر، أدخل الأمر التالي. إدراج هذه القيم في الأمر:

  • مفتاح مورد الكلام
  • منطقة مورد الكلام

قد ترغب أيضًا في تغيير القيم التالية:

  • X-Microsoft-OutputFormat قيمة الرأس، التي تتحكم في تنسيق إخراج الصوت. يمكنك العثور على قائمة بتنسيقات إخراج الصوت المعتمدة في مرجع واجهة برمجة تطبيقات REST لتحويل النص إلى كلام.
  • صوت الإخراج. للحصول على قائمة بالأصوات المتوفرة لنقطة نهاية خدمة الكلام، راجع واجهة برمجة تطبيقات القائمة الصوتية.
  • ملف الإخراج. في هذا المثال، نقوم بتوجيه الاستجابة من الخادم إلى ملف يسمى 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

في هذا الدليل الإرشادي، ستتعلم أنماط تصميم شائعة للقيام بتركيب النص إلى كلام.

لمزيد من المعلومات حول المناطق التالية، راجع ما هو النص إلى كلام؟

  • الحصول على الاستجابات كتيارات في الذاكرة.
  • تخصيص معدل عينة الإخراج ومعدل البت.
  • إرسال طلبات التركيب باستخدام لغة ترميز تركيب الكلام (SSML).
  • استخدام الأصوات العصبية.
  • الاشتراك في الأحداث والعمل بناء على النتائج.

المتطلبات الأساسية

التنزيل والتثبيت

اتبع هذه الخطوات وشاهد التشغيل السريع ل Speech CLI لمعرفة المتطلبات الأخرى للنظام الأساسي الخاص بك.

  1. قم بتشغيل الأمر .NET CLI التالي لتثبيت Speech CLI:

    dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
    
  2. قم بتشغيل الأوامر التالية لتكوين مفتاح مورد الكلام والمنطقة. استبدل SUBSCRIPTION-KEY بمفتاح مورد Speech واستبدل REGION بمنطقة مورد Speech.

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

تجميع الكلام إلى أحد المتحدثين

أنت الآن جاهز لتشغيل Speech CLI لتجميع الكلام من النص.

  • في نافذة وحدة التحكم، قم بالتغيير إلى الدليل الذي يحتوي على الملف الثنائي Speech CLI. ثم شغَّل الأمر التالي:

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

تنتج Speech CLI لغة طبيعية باللغة الإنجليزية من خلال مكبر صوت الكمبيوتر.

تجميع الكلام إلى ملف

  • قم بتشغيل الأمر التالي لتغيير الإخراج من السماعة إلى ملف .wav :

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

تنتج Speech CLI لغة طبيعية باللغة الإنجليزية إلى ملف الصوت greetings.wav .

تشغيل حاوية واستخدامها

توفر حاويات الكلام واجهات برمجة تطبيقات نقطة نهاية الاستعلام المستندة إلى websocket التي يتم الوصول إليها من خلال Speech SDK و Speech CLI. بشكل افتراضي، يستخدم Speech SDK و Speech CLI خدمة Speech العامة. لاستخدام الحاوية، تحتاج إلى تغيير أسلوب التهيئة. استخدم عنوان URL لمضيف الحاوية بدلا من المفتاح والمنطقة.

لمزيد من المعلومات حول الحاويات، راجع تثبيت حاويات الكلام وتشغيلها باستخدام Docker.

الخطوات التالية