Share via


Viseme ile yüz konumunu alma

Not

Viseme kimliği ve karışım şekilleri için desteklenen yerel ayarları keşfetmek için desteklenen tüm yerel ayarların listesine bakın. Ölçeklenebilir Vektör Grafikleri (SVG) yalnızca yerel ayar için en-US desteklenir.

Vizeme, bir fonenin konuşma dilindeki görsel açıklamasıdır. Bir kişi konuşurken yüzün ve ağzın konumunu tanımlar. Her vizeme, belirli bir fonem kümesi için yüz pozlarının tuşlarını gösterir.

2B ve 3B avatar modellerinin hareketini kontrol etmek için visemeleri kullanabilirsiniz, böylece yüz konumları sentetik konuşmayla en iyi şekilde hizalanır. Örneğin, şunları yapabilirsiniz:

  • Müşterileriniz için çok modlu tümleşik hizmetler oluşturarak akıllı bilgi noktaları için animasyonlu bir sanal sesli yardımcı oluşturun.
  • Çevreleyici haber yayınları oluşturun ve doğal yüz ve ağız hareketleri ile izleyici deneyimlerini geliştirin.
  • Dinamik içerikle konuşabilen daha etkileşimli oyun avatarları ve çizgi film karakterleri oluşturun.
  • Dil öğrenenlerin her sözcüğün ve telefonun ağız davranışını anlamasına yardımcı olan daha etkili dil öğretim videoları yapın.
  • İşitme engelli Kişiler sesleri görsel olarak ve animasyonlu bir yüz üzerinde visemeleri gösteren "dudak okuma" konuşma içeriği de alabilir.

Visemes hakkında daha fazla bilgi için bu giriş videosunu görüntüleyin.

Konuşma ile viseme üretmenin genel iş akışı

Nöral Metin okuma (Nöral TTS), giriş metnini veya SSML'yi (Konuşma Sentezi İşaretlemesi Dili) canlı gibi sentezlenmiş konuşmaya dönüştürür. Konuşma sesi çıkışına viseme kimliği, Ölçeklenebilir Vektör Grafikleri (SVG) veya karışım şekilleri eşlik edebilir. Bir 2B veya 3B işleme altyapısı kullanarak avatarınıza animasyon eklemek için bu viseme olaylarını kullanabilirsiniz.

Viseme'nin genel iş akışı aşağıdaki akış çizelgesinde gösterilir:

Diagram of the overall workflow of viseme.

Viseme Kimliği

Viseme Kimliği, viseme belirten bir tamsayıya başvurur. Her biri belirli bir fonem kümesi için ağız konumunu gösteren 22 farklı vizeme sunuyoruz. Vizemelerle fonemler arasında birebir bir yazışma yoktur. Çoğu zaman, birkaç fonem tek bir vizemeye karşılık gelir, çünkü ve gibi szüretildiğinde konuşmacının yüzünde aynı görünürlerdi. Daha ayrıntılı bilgi için , fonemleri viseme kimlikleriyle eşleme tablosuna bakın.

Konuşma sesi çıkışına viseme kimlikleri ve Audio offseteşlik edebilir. , Audio offset her vizemenin başlangıç zamanını gösteren uzaklık zaman damgasını değer değerlerinde (100 nanosaniye) gösterir.

Fonemleri visemes ile eşleme

Visemes, dile ve yerel ayara göre farklılık gösterir. Her yerel ayarın belirli fonemlerine karşılık gelen bir dizi viseme vardır. SSML fonetik alfabe belgeleri viseme kimliklerini ilgili Uluslararası Telefon tik Alfabe (IPA) fonemleriyle eşler. Bu bölümdeki tabloda, viseme kimlikleri ile ağız konumları arasındaki eşleme ilişkisi gösterilir ve her viseme kimliği için tipik IPA fonemleri listelenir.

Viseme Kimliği IPA Ağız konumu
0 Sessiz -lik The mouth position when viseme ID is 0
1 æ, ə, ʌ 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, b, m The mouth position when viseme ID is 21

2B SVG animasyonu

2B karakterler için senaryonuza uygun bir karakter tasarlayabilir ve zaman tabanlı yüz konumu elde etmek için her viseme kimliği için Ölçeklenebilir Vektör Grafiği (SVG) kullanabilirsiniz.

Bir viseme olayında sağlanan zamansal etiketlerle, bu iyi tasarlanmış SVG'ler düzeltme değişiklikleriyle işlenir ve kullanıcılara sağlam animasyon sağlar. Örneğin, aşağıdaki çizimde dil öğrenmesi için tasarlanmış kırmızı sıkıştırılmış bir karakter gösterilmektedir.

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

3B blend şekilleri animasyonu

Tasarladığınız bir 3B karakterin yüz hareketlerini yönlendirmek için blend şekillerini kullanabilirsiniz.

Karıştırma şekilleri JSON dizesi 2 boyutlu matris olarak temsil edilir. Her satır bir çerçeveyi temsil eder. Her kare (60 FPS'de) 55 yüz pozisyonundan oluşan bir dizi içerir.

Konuşma SDK'sı ile viseme olayları alma

Sentezlenmiş konuşmanızla viseme elde etmek için VisemeReceived Konuşma SDK'sında olaya abone olun.

Not

SVG veya karıştırma şekilleri çıkışı istemek için SSML'de öğesini kullanmanız mstts:viseme gerekir. Ayrıntılar için bkz . SSML'de viseme öğesini kullanma.

Aşağıdaki kod parçacığı viseme olayına nasıl abone olundığını gösterir:

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

Burada viseme çıkışının bir örneği verilmişti.

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

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

……

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

Viseme çıkışını aldıktan sonra, karakter animasyonunu yönlendirmek için bu olayları kullanabilirsiniz. Kendi karakterlerinizi oluşturabilir ve bunlara otomatik olarak animasyon ekleyebilirsiniz.

Sonraki adımlar