Archelyzet lekérése a viseme használatával

Feljegyzés

A viseme-azonosítóhoz és az alakzatok keveréséhez támogatott területi beállítások megismeréséhez tekintse meg az összes támogatott területi beállítás listáját. A skálázható vektorgrafika (SVG) csak a en-US területi beállításhoz támogatott.

A viseme egy beszélt nyelvű telefonkép vizuális leírása. Meghatározza az arc és a száj helyzetét, miközben egy személy beszél. Minden viseme egy adott fonálkészlet fő arcpózait ábrázolja.

A visemek segítségével szabályozhatja a 2D és a 3D avatarmodellek mozgását, hogy az arcpozíciók a legjobban igazodjanak a szintetikus beszédhez. Lehetőség van például a következőkre:

  • Animált virtuális hangsegéd létrehozása intelligens kioszkokhoz, több módú integrált szolgáltatások létrehozása az ügyfelek számára.
  • Modern hírközvetítéseket készíthet, és természetes arc- és szájmozgásokkal javíthatja a közönség élményét.
  • Interaktívabb játék avatárokat és rajzfilmfigurákat hozhat létre, amelyek dinamikus tartalommal beszélnek.
  • Hatékonyabb nyelvtanítási videók készítése, amelyek segítenek a nyelvtanulóknak megérteni az egyes szavak és fotelek szájhasználatát.
  • Kapcsolatok hallássérültek vizuálisan is fel tudják venni a hangokat és az "ajak-olvasás" beszédtartalmakat, amelyek animált arcon jelenítik meg a viszemeket.

A visemekkel kapcsolatos további információkért tekintse meg ezt a bevezető videót.

A viseme beszéddel történő előállításának általános munkafolyamata

A neurális szövegről beszédre (neurális TTS) a bemeneti szöveget vagy az SSML-t (Beszédszintézisi korrektúranyelvet) élethű szintetizált beszédgé alakítja. A beszédhangkimenetet a viseme-azonosító, a méretezhető vektorgrafika (SVG) vagy az alakzatok keverése is kísérheti. 2D vagy 3D renderelő motor használatával ezeket a viseme eseményeket használhatja az avatar animálásához.

A viseme teljes munkafolyamatát a következő folyamatábra mutatja be:

Diagram of the overall workflow of viseme.

Viseme-azonosító

A Viseme-azonosító egy egész számra utal, amely egy viseme-et határoz meg. 22 különböző visemát kínálunk, amelyek mindegyike egy adott fonefonkészlet szájpozícióját ábrázolja. Nincs egy-az-egyhez levelezés a visemes és a fonefonok között. Gyakran előfordul, hogy több telefon egyetlen viseme-nek felel meg, mert ugyanúgy néztek ki a beszélő arcán, amikor elő lettek hozva, például s és z. További információkért tekintse meg a fonémák viseme azonosítókra való leképezését ismertető táblázatot.

A beszédhangkimenetet a viseme azonosítók és Audio offseta . Az Audio offset eltolás időbélyegét jelzi, amely az egyes viseme-ek kezdési időpontját jelöli kullancsokban (100 nanoszekundum).

Fonefonok leképezése visemesre

A Visemes nyelv és területi beállítások szerint változik. Minden területi beállításhoz tartoznak olyan visemek, amelyek megfelelnek az adott foneumoknak. Az SSML fonetikus ábécék dokumentációja a megfelelő Nemzetközi Telefon tikus Ábécé (IPA) fonetikai fonetikai azonosítókhoz rendeli a viseme azonosítókat. Az ebben a szakaszban található táblázat a viseme azonosítók és a szájpozíciók közötti leképezési kapcsolatot mutatja be, és felsorolja az egyes viseme-azonosítók tipikus IPA-fonémáit.

Viseme-azonosító IPA Száj helyzete
0 Csend The mouth position when viseme ID is 0
0 æ, , əʌ The mouth position when viseme ID is 1
2 ɑ The mouth position when viseme ID is 2
3 ɔ The mouth position when viseme ID is 3
4 ɛ, ʊ The mouth position when viseme ID is 4
5 ɝ The mouth position when viseme ID is 5
6 j, , iɪ The mouth position when viseme ID is 6
7 w, u The mouth position when viseme ID is 7
8 o The mouth position when viseme ID is 8
9 The mouth position when viseme ID is 9
10 ɔɪ The mouth position when viseme ID is 10
11 The mouth position when viseme ID is 11
12 h The mouth position when viseme ID is 12
13 ɹ The mouth position when viseme ID is 13
14 l The mouth position when viseme ID is 14
15 s, z The mouth position when viseme ID is 15
16 ʃ, , ʒ The mouth position when viseme ID is 16
17 ð The mouth position when viseme ID is 17
18 f, v The mouth position when viseme ID is 18
19 d, t, nθ The mouth position when viseme ID is 19
20 k, , gŋ The mouth position when viseme ID is 20
21 p, , bm The mouth position when viseme ID is 21

2D SVG animáció

2D karakterek esetén a forgatókönyvnek megfelelő karaktert tervezhet, és a skálázható vektorgrafika (SVG) használatával minden viseme-azonosítóhoz időalapú arcpozíciót kaphat.

A viseme eseményben megadott időbeli címkékkel ezeket a jól megtervezett SVG-ket simító módosításokkal dolgozzák fel, és robusztus animációt biztosítanak a felhasználóknak. Az alábbi ábrán például egy nyelvtanuláshoz tervezett piros ajakú karakter látható.

Screenshot showing a 2D rendering example of four red-lipped mouths, each representing a different viseme ID that corresponds to a phoneme.

Térhatású keverési alakzatok animációja

Kevert alakzatokkal vezérelheti az Ön által tervezett 3D karakter arcmozdulatait.

A keverékalakzatok JSON-sztringje kétdimenziós mátrixként jelenik meg. Minden sor egy keretet jelöl. Minden keret (60 FPS- ben) 55 arcpozícióból álló tömböt tartalmaz.

Viseme-események lekérése a Speech SDK-val

A szintetizált beszédtel való ismerkedéshez iratkozzon fel az VisemeReceived eseményre a Speech SDK-ban.

Feljegyzés

SvG-kimenet kéréséhez vagy alakzatok keveréséhez használja az mstts:viseme SSML elemét. További részletekért tekintse meg , hogyan használható a viseme elem az SSML-ben.

Az alábbi kódrészlet bemutatja, hogyan iratkozhat fel a viseme eseményre:

using (var synthesizer = new SpeechSynthesizer(speechConfig, audioConfig))
{
    // Subscribes to viseme received event
    synthesizer.VisemeReceived += (s, e) =>
    {
        Console.WriteLine($"Viseme event received. Audio offset: " +
            $"{e.AudioOffset / 10000}ms, viseme id: {e.VisemeId}.");

        // `Animation` is an xml string for SVG or a json string for blend shapes
        var animation = e.Animation;
    };

    // If VisemeID is the only thing you want, you can also use `SpeakTextAsync()`
    var result = await synthesizer.SpeakSsmlAsync(ssml);
}

auto synthesizer = SpeechSynthesizer::FromConfig(speechConfig, audioConfig);

// Subscribes to viseme received event
synthesizer->VisemeReceived += [](const SpeechSynthesisVisemeEventArgs& e)
{
    cout << "viseme event received. "
        // The unit of e.AudioOffset is tick (1 tick = 100 nanoseconds), divide by 10,000 to convert to milliseconds.
        << "Audio offset: " << e.AudioOffset / 10000 << "ms, "
        << "viseme id: " << e.VisemeId << "." << endl;

    // `Animation` is an xml string for SVG or a json string for blend shapes
    auto animation = e.Animation;
};

// If VisemeID is the only thing you want, you can also use `SpeakTextAsync()`
auto result = synthesizer->SpeakSsmlAsync(ssml).get();
SpeechSynthesizer synthesizer = new SpeechSynthesizer(speechConfig, audioConfig);

// Subscribes to viseme received event
synthesizer.VisemeReceived.addEventListener((o, e) -> {
    // The unit of e.AudioOffset is tick (1 tick = 100 nanoseconds), divide by 10,000 to convert to milliseconds.
    System.out.print("Viseme event received. Audio offset: " + e.getAudioOffset() / 10000 + "ms, ");
    System.out.println("viseme id: " + e.getVisemeId() + ".");

    // `Animation` is an xml string for SVG or a json string for blend shapes
    String animation = e.getAnimation();
});

// If VisemeID is the only thing you want, you can also use `SpeakTextAsync()`
SpeechSynthesisResult result = synthesizer.SpeakSsmlAsync(ssml).get();
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)

def viseme_cb(evt):
    print("Viseme event received: audio offset: {}ms, viseme id: {}.".format(
        evt.audio_offset / 10000, evt.viseme_id))

    # `Animation` is an xml string for SVG or a json string for blend shapes
    animation = evt.animation

# Subscribes to viseme received event
speech_synthesizer.viseme_received.connect(viseme_cb)

# If VisemeID is the only thing you want, you can also use `speak_text_async()`
result = speech_synthesizer.speak_ssml_async(ssml).get()
var synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, audioConfig);

// Subscribes to viseme received event
synthesizer.visemeReceived = function (s, e) {
    window.console.log("(Viseme), Audio offset: " + e.audioOffset / 10000 + "ms. Viseme ID: " + e.visemeId);

    // `Animation` is an xml string for SVG or a json string for blend shapes
    var animation = e.animation;
}

// If VisemeID is the only thing you want, you can also use `speakTextAsync()`
synthesizer.speakSsmlAsync(ssml);
SPXSpeechSynthesizer *synthesizer =
    [[SPXSpeechSynthesizer alloc] initWithSpeechConfiguration:speechConfig
                                           audioConfiguration:audioConfig];

// Subscribes to viseme received event
[synthesizer addVisemeReceivedEventHandler: ^ (SPXSpeechSynthesizer *synthesizer, SPXSpeechSynthesisVisemeEventArgs *eventArgs) {
    NSLog(@"Viseme event received. Audio offset: %fms, viseme id: %lu.", eventArgs.audioOffset/10000., eventArgs.visemeId);

    // `Animation` is an xml string for SVG or a json string for blend shapes
    NSString *animation = eventArgs.Animation;
}];

// If VisemeID is the only thing you want, you can also use `SpeakText`
[synthesizer speakSsml:ssml];

Íme egy példa a viseme kimenetére.

(Viseme), Viseme ID: 1, Audio offset: 200ms.

(Viseme), Viseme ID: 5, Audio offset: 850ms.

……

(Viseme), Viseme ID: 13, Audio offset: 2350ms.

Miután beszerezte a viseme-kimenetet, ezek az események a karakteranimációt is vezérelhetik. Létrehozhat saját karaktereket, és automatikusan animálhatja őket.

Következő lépések