Flujo TTS de síntesis de voz SSML de Azure Microsoft C# de Unity para obtener datos de audio y disposición simple de expresión y animación de la boca

Flujo TTS de síntesis de voz SSML de Azure Microsoft C# de Unity para obtener datos de audio y disposición simple de expresión y animación de la boca

Tabla de contenido

Flujo TTS de síntesis de voz SSML de Azure Microsoft C# de Unity para obtener datos de audio y disposición simple de expresión y animación de la boca

1. Breve introducción

2. Principio de implementación

3. Asuntos que requieren atención

4. Pasos de implementación

5. Código clave


1. Breve introducción

La clase de herramientas de Unity, algunos módulos que pueden usarse en el desarrollo de juegos organizados por mí , se pueden usar de forma independiente para facilitar el desarrollo de juegos.

Esta sección presenta que Microsoft Azure usa SSML para realizar audio de síntesis de voz SS y obtiene los datos de animación de boca de expresión y los guarda localmente. En ciertos casos, se usa para leer el audio y los datos de animación de boca de expresión localmente. Úselo directamente para evitar posibles retrasos causados ​​por el acceso a la red, aquí una breve explicación, si tiene un método mejor, por favor deje un mensaje para comunicarse.

El lenguaje de marcado de síntesis de voz (SSML) es un lenguaje de marcado basado en XML que se puede usar para ajustar las propiedades de salida de texto a voz, como el tono, la pronunciación, la velocidad, el volumen y más. Tiene mucho más control y flexibilidad que la entrada de texto sin formato.

Puede usar SSML para hacer lo siguiente:

  •     Define la estructura del texto de entrada, que determina la estructura, el contenido y otras características de la salida de texto a voz. Por ejemplo, SSML se puede usar para definir párrafos, oraciones, pausas/pausas o silencios. El texto se puede envolver con marcadores de eventos, como marcadores o visemas, que la aplicación puede procesar más tarde.
  •     Elige voz, idioma, nombre, estilo y rol. Se pueden usar varias voces en un solo documento SSML. Ajuste el acento, la velocidad del habla, el tono y el volumen. También puede usar SSML para insertar audio pregrabado, como efectos de sonido o notas musicales.
  •     Controla la pronunciación del audio de salida. Por ejemplo, puede usar SSML con fonemas y diccionarios personalizados para mejorar la pronunciación. SSML también se puede utilizar para definir pronunciaciones específicas de palabras o expresiones matemáticas.
     

El siguiente es un subconjunto de la estructura básica y la sintaxis de un documento SSML:

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="string">
    <mstts:backgroundaudio src="string" volume="string" fadein="string" fadeout="string"/>
    <voice name="string" effect="string">
        <audio src="string"></audio>
        <bookmark mark="string"/>
        <break strength="string" time="string" />
        <emphasis level="value"></emphasis>
        <lang xml:lang="string"></lang>
        <lexicon uri="string"/>
        <math xmlns="http://www.w3.org/1998/Math/MathML"></math>
        <mstts:audioduration value="string"/>
        <mstts:express-as style="string" styledegree="value" role="string"></mstts:express-as>
        <mstts:silence type="string" value="string"/>
        <mstts:viseme type="string"/>
        <p></p>
        <phoneme alphabet="string" ph="string"></phoneme>
        <prosody pitch="value" contour="value" range="value" rate="value" volume="value"></prosody>
        <s></s>
        <say-as interpret-as="string" format="string" detail="string"></say-as>
        <sub alias="string"></sub>
    </voice>
</speak>

 SSML Speech and Sound
Speech and Sound for Speech Synthesis Markup Language (SSML) - Speech Services - Azure AI services | Microsoft Learn

Registro en el sitio web oficial:

Azure para estudiantes: créditos de cuenta gratuitos | Microsoft Azure

URL de la documentación técnica del sitio web oficial:

Documentación técnica | Microsoft Learn

TTS del sitio web oficial:

Inicio rápido de texto a voz - Servicios de voz - Azure Cognitive Services | Microsoft Learn

Sitio web oficial del paquete Azure Unity SDK:

Instale Speech SDK: Azure Cognitive Services | Microsoft Learn

Enlace específico del SDK:

https://aka.ms/csspeech/unitypackage

 

2. Principio de implementación

1. Solicite SPEECH_KEY y SPEECH_REGION correspondientes a la síntesis de voz en el sitio web oficial

2. Luego configure el idioma y la configuración de sonido requerida en consecuencia

3. Use SSML con transmisión para obtener los datos de audio, solo reprodúzcalos o guárdelos en la fuente de sonido, la muestra es la siguiente

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

4. Guarde localmente el audio y los datos de animación de las expresiones faciales y las formas de la boca.

    // 获取到视频的数据,保存为 .wav 
    using var stream = AudioDataStream.FromResult(speechSynthesisResult);
    await stream.SaveToWaveFileAsync($"./{fileName}.wav");



    /// <summary>
    /// 嘴型 animation 数据,本地保存为 json 数据
    /// </summary>
    /// <param name="fileName">保存文件名</param>
    /// <param name="content">保存内容</param>
    /// <returns></returns>
    static async Task CommitAsync(string fileName,string content)
    {
        var bits = Encoding.UTF8.GetBytes(content);
        using (var fs = new FileStream(
            path: @$"d:\temp\{fileName}.json",
            mode: FileMode.Create,
            access: FileAccess.Write,
            share: FileShare.None,
            bufferSize: 4096,
            useAsync: true))
        {
            await fs.WriteAsync(bits, 0, bits.Length);
        }
    }

3. Asuntos que requieren atención

1. No todos los SpeechSynthesisVoiceName pueden generar los datos de animación correspondientes de la expresión y la forma de la boca.

4. Pasos de implementación

Aquí está la prueba de código directamente usando .Net VS

1. Instale el paquete Speech de Microsoft en NuGet

 2. Escriba el código para realizar la voz sintetizada SSML y guarde el archivo de audio correspondiente y los datos json de animación de la forma de la boca del emoticono localmente

3. Ejecute el código.Después de ejecutarlo, el archivo de audio correspondiente y los datos json de la animación de la forma de la boca se guardarán localmente.

 

 4. Ver datos guardados localmente

 

5. Código clave

using Microsoft.CognitiveServices.Speech;
using System.Text;

class Program
{
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    static string speechKey = "YOUR_SPEECH_KEY";
    static string speechRegion = "YOUR_SPEECH_REGION";
    static string speechSynthesisVoiceName = "zh-CN-XiaoxiaoNeural";
    static string fileName = "Test" + "Hello";
    static string InputAudioContent = "黄河之水天上来,奔流到海不复回";  // 生成的

    static int index = 0;   // 记录合成的表情口型动画的数据数组个数
    static string content="[";  // [ 是为了组成 json 数组

    async static Task Main(string[] args)
    {
        var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);

        // 根据需要可以使用更多 xml 配置,让合成的声音更加生动立体
        var ssml = @$"<speak version='1.0' xml:lang='zh-CN' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
            <voice name='{speechSynthesisVoiceName}'>
                <mstts:viseme type='FacialExpression'/>
                <mstts:express-as style='friendly'>{InputAudioContent}</mstts:express-as>
            </voice>
        </speak>";

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

        using (var speechSynthesizer = new SpeechSynthesizer(speechConfig))
        {
            // Subscribe to events
            // 注册表情嘴型数据
            speechSynthesizer.VisemeReceived += async (s, e) =>
            {
                Console.WriteLine($"VisemeReceived event:" +
                    $"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" 
                   + $"\r\n\tVisemeId: {e.VisemeId}" 
                    // + $"\r\n\tAnimation: {e.Animation}"
                    );
                if (string.IsNullOrEmpty( e.Animation)==false)
                {
                    // \r\n, 是为了组合 json 格式
                    content += e.Animation + "\r\n,";
                    index++;
                }
                
            };
            
            // 注册合成完毕的事件
            speechSynthesizer.SynthesisCompleted += async (s, e) =>
            {
                Console.WriteLine($"SynthesisCompleted event:" +
                    $"\r\n\tAudioData: {e.Result.AudioData.Length} bytes" +
                    $"\r\n\tindex: {index} " +
                    $"\r\n\tAudioDuration: {e.Result.AudioDuration}");
                content = content.Substring(0, content.Length-1);
                content += "]";
                await CommitAsync(fileName, content);
            };

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

            // 获取到视频的数据,保存为 .wav 
            using var stream = AudioDataStream.FromResult(speechSynthesisResult);
            await stream.SaveToWaveFileAsync(@$"d:\temp\{fileName}.wav");

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


    /// <summary>
    /// 嘴型 animation 数据,本地保存为 json 数据
    /// </summary>
    /// <param name="fileName">保存文件名</param>
    /// <param name="content">保存内容</param>
    /// <returns></returns>
    static async Task CommitAsync(string fileName,string content)
    {
        var bits = Encoding.UTF8.GetBytes(content);
        using (var fs = new FileStream(
            path: @$"d:\temp\{fileName}.json",
            mode: FileMode.Create,
            access: FileAccess.Write,
            share: FileShare.None,
            bufferSize: 4096,
            useAsync: true))
        {
            await fs.WriteAsync(bits, 0, bits.Length);
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/u014361280/article/details/132313878
Recomendado
Clasificación