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 ayrıca sesleri görsel olarak ve animasyonlu bir yüz üzerinde vizemeler gösteren "dudak okuma" konuşma içeriklerini 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:

Viseme'nin genel iş akışının diyagramı.

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 s zü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ı Fonetik 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 Sessizlik Viseme kimliği 0 olduğunda ağız konumu
1 æ, ə, ʌ Viseme kimliği 1 olduğunda ağız konumu
2 ɑ Viseme kimliği 2 olduğunda ağız konumu
3 ɔ Viseme kimliği 3 olduğunda ağız konumu
4 ɛ, ʊ Viseme kimliği 4 olduğunda ağız konumu
5 ɝ Viseme kimliği 5 olduğunda ağız konumu
6 j, i, ɪ Viseme kimliği 6 olduğunda ağız konumu
7 w, u Viseme kimliği 7 olduğunda ağız konumu
8 o Viseme kimliği 8 olduğunda ağız konumu
9 Viseme kimliği 9 olduğunda ağız konumu
10 ɔɪ Viseme kimliği 10 olduğunda ağız konumu
11 Viseme kimliği 11 olduğunda ağız konumu
12 h Viseme kimliği 12 olduğunda ağız konumu
13 ɹ Viseme kimliği 13 olduğunda ağız konumu
14 l Viseme kimliği 14 olduğunda ağız konumu
15 s, z Viseme kimliği 15 olduğunda ağız konumu
16 ʃ, , , ʒ Viseme kimliği 16 olduğunda ağız konumu
17 ð Viseme kimliği 17 olduğunda ağız konumu
18 f, v Viseme kimliği 18 olduğunda ağız konumu
19 d, t, n, θ Viseme kimliği 19 olduğunda ağız konumu
20 k, g, ŋ Viseme kimliği 20 olduğunda ağız konumu
21 p, b, m Viseme kimliği 21 olduğunda ağız konumu

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.

Her biri bir foneme karşılık gelen farklı bir viseme kimliğini temsil eden dört kırmızı uçlu ağzın 2B işleme örneğini gösteren ekran görüntüsü.

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