Rive एनीमेशन पाइपलाइन: अरबी पात्रों को जीवंत बनाना
5 मिनट पढ़ेंMohammad Shaker

Rive एनीमेशन पाइपलाइन: अरबी पात्रों को जीवंत बनाना

Amal ऐप में Rive का उपयोग करके अरबी पात्रों की लिप-सिंक और अनुकूलन सहित एनिमेशन बनाई जाती है।

Engineering

त्वरित उत्तर

Amal ऐप में Rive का उपयोग करके अरबी पात्रों की लिप-सिंक और अनुकूलन सहित एनिमेशन बनाई जाती है।

हमारी Rive एनीमेशन पाइपलाइन: अरबी पात्रों को जीवंत बनाना

Amal ऐप में सभी पात्र एनिमेशन के लिए Rive (पूर्व में Flare) का उपयोग किया जाता है — लिप-सिंक स्पीच, अवतार अनुकूलन, प्रतिक्रिया अभिव्यक्तियाँ, और गेम पात्र। हमने Lottie या स्प्राइट शीट्स के बजाय Rive चुना क्योंकि यह रनटाइम स्टेट मशीनों, प्रोग्रामैटिक मैनिपुलेशन, और GPU-तीव्र रेंडरिंग (60fps) का समर्थन करता है, और प्रत्येक पात्र के लिए एक कॉम्पैक्ट फाइल प्रदान करता है।

एनीमेशन एसेट लाइब्रेरी

कोर पात्र

  • lip-sync-amal-01.riv
    • मुख्य Amal पात्र (पूर्ण शरीर और केवल चेहरे के वेरिएंट)
    • प्रत्येक मुँह की स्थिति के लिए कई आर्टबोर्ड (फोनिम मैपिंग के लिए)
    • स्टेट्स: निष्क्रिय, बोलना, त्रुटि, उत्सव, सोना
    • फाइल साइज: 1.2 एमबी (स्प्राइट शीट्स के 50+ एमबी के मुकाबले)
  • avatar.riv
    • कस्टमाइज़ेबल उपयोगकर्ता अवतार (3 आर्टबोर्ड)
      1. पूर्ण शरीर: सिर, धड़, अंगों सहित कपड़े
      2. सिर्फ सिर: डैशबोर्ड और पैरेंट ऐप के लिए
      3. तितली साथी: इनाम एनिमेशन
    • कॉम्पोनेन्ट-आधारित: सिर की आकृति, बाल, आंखें, कपड़े, सहायक उपकरण, रंग
    • फाइल साइज: 2.4 एमबी
  • coin-01.riv एवं coins-01.riv
    • इनाम एनिमेशन (सिक्के तैरते और इकट्ठे होते)
    • एक सिक्का: 150 केबी
    • कई सिक्के: 300 केबी
  • cute-monster-final.riv
    • प्रतिक्रिया वर्ण जिसमें कई भावात्मक अवस्थाएँ शामिल हैं
    • स्टेट्स: खुश (सही उत्तर), उलझन में (गलत), सोच रहा (प्रोसेसिंग), जश्न मना रहा (स्ट्रिक)
    • फाइल साइज: 1.8 एमबी

एंड्रॉइड-विशिष्ट अनुकूलन

  • कस्टम NDK बिल्ड (Rive NDK-r28) 16KB पेज संरेखण कम्प्लायंस के लिए
  • स्टैंडर्ड बिल्ड के मुकाबले बाइनरी साइज 8% कम
  • Android 12+ की सख्त मेमोरी प्रबंधन के साथ संगतता सुनिश्चित करता है

लिप-सिंक पाइपलाइन (तकनीकी विवरण)

चरण 1: TTS ऑडियो जनरेशन और स्पीच मार्क्स एक्सट्रैक्शन

# src/services/tts_client.py
from google.cloud import texttospeech

def generate_speech_with_marks(text: str, language: str = 'ar-SA'):
    client = texttospeech.TextToSpeechClient()
    
    synthesis_input = texttospeech.SynthesisInput(text=text)
    voice = texttospeech.VoiceSelectionParams(
        language_code=language,
        name='ar-SA-Neural2-A'  # WaveNet voice
    )
    audio_config = texttospeech.AudioConfig(
        audio_encoding=texttospeech.AudioEncoding.MP3,
        effects_profile_id=['small-bluetooth-speaker-class-device']  # बच्चे के स्पीकर
    )
    
    # स्पीच मार्क्स का अनुरोध (फोनिम टाइमिंग)
    request = texttospeech.SynthesizeSpeechRequest(
        input=synthesis_input,
        voice=voice,
        audio_config=audio_config,
        enable_text_to_speech_as_cloud_service=True
    )
    
    response = client.synthesize_speech(request=request)
    
    # प्रतिक्रिया में शामिल हैं:
    # - audio_content: MP3 बाइट्स
    # - timepoints: [{character, byte_pos, time_ms}, ...]
    
    return {
        'audio': response.audio_content,
        'speech_marks': response.timepoints  # फोनिम स्तर के टाइमस्टैम्प
    }

चरण 2: फोनिम को Rive के मुँह की अवस्थाओं से मैप करना

lip_sync_avatar.json अरबी फोनिम्स को मुँह की स्थिति से मेप करता है:

{
  "phoneme_map": {
    "ا": { "rive_state": "mouth_a_open", "duration_ms": 200 },
    "ب": { "rive_state": "mouth_lips_closed", "duration_ms": 150 },
    "ع": { "rive_state": "mouth_pharyngeal", "duration_ms": 250 },
    "ق": { "rive_state": "mouth_uvular", "duration_ms": 180 },
    ...
  },
  "mouth_positions": [
    { "id": "mouth_a_open", "blend_values": { "jaw_open": 0.8, "lips_rounded": 0.2 } },
    { "id": "mouth_lips_closed", "blend_values": { "jaw_open": 0.1, "lips_rounded": 0.9 } },
    ...
  ]
}

चरण 3: LipSyncController प्लेबैक को नियंत्रित करता है

// lib/src/modules/animations/controllers/lip_sync_controller.dart
class LipSyncController extends GetxController {
  late Rive riveCharacter;
  late AudioPlayer audioPlayer;
  late LipSyncMapper mapper;
  
  void playWithLipSync(String text, String audioPath) {
    // चरण 1: Rive पात्र लोड करें
    riveCharacter.loadRiveFile('lip-sync-amal-01.riv');
    
    // चरण 2: TTS आउटपुट से स्पीच मार्क्स लोड करें
    mapper = LipSyncMapper.fromJson(loadJsonAsset('lip_sync_avatar.json'));
    
    // चरण 3: मुँह की एनिमेशन ड्राइव करते हुए ऑडियो चलाएं
    audioPlayer.play(AudioSource.file(audioPath));
    
    // चरण 4: हर ऑडियो फ्रेम पर मुँह की स्थिति अपडेट करें
    audioPlayer.onPositionChanged.listen((Duration position) {
      String phoneme = mapper.phonemeAtTime(position.inMilliseconds);
      String riveState = mapper.riveStateForPhoneme(phoneme);
      
      riveCharacter.setStateInput('mouth_state', riveState);
    });
  }
}

चरण 4: RiveCharacterController जीवनचक्र प्रबंधित करता है

// केवल मुँह नहीं, बल्कि पूरे पात्र की एनिमेशन स्थिति प्रबंधन
class RiveCharacterController extends GetxController {
  States: idle → prepare → speaking → idle → error/celebration
  
  void startExercise() {
    // पात्र संक्रमण: idle → prepare (सुनने के लिए तैयार)
    character.setStateInput('state_machine', 'prepare');
  }
  
  void childSpeaks(String recognizedText, double accuracy) {
    character.setStateInput('state_machine', 'speaking');
    lipSyncController.playFeedback(recognizedText);
  }
  
  void onFeedbackComplete(bool wasCorrect) {
    if (wasCorrect) {
      character.setStateInput('state_machine', 'celebrate');
      playRewardAnimation();
    } else {
      character.setStateInput('state_machine', 'error');
      playEncouragingPhrase();
    }
  }
}

अवतार कस्टमाइजेशन सिस्टम

कंपोनेंट-आधारित आर्किटेक्चर

बच्चे अपने अवतार को इन पार्ट्स से कस्टमाइज़ करते हैं:

{
  "avatar_customization": {
    "head_shapes": [
      { "id": "round", "rive_element": "head_round" },
      { "id": "oval", "rive_element": "head_oval" },
      { "id": "square", "rive_element": "head_square" }
    ],
    "hair_styles": [
      { "id": "ponytail", "rive_element": "hair_ponytail" },
      { "id": "braids", "rive_element": "hair_braids" },
      { "id": "straight", "rive_element": "hair_straight" }
    ],
    "colors": {
      "skin_tone": ["light", "medium", "dark"],
      "hair_color": ["black", "brown", "blonde", "red"],
      "shirt_color": ["blue", "pink", "green", "yellow", "purple"],
      "accent_color": ["red", "orange", "green", "blue"]
    }
  }
}

Rive Named Elements Mapping (avatar_customization_rive_names.dart)

const avatarRiveNames = {
  'head_round': 'Head_Round',
  'head_oval': 'Head_Oval',
  'hair_ponytail': 'Hair_Ponytail',
  'shirt_blue': 'Shirt_Blue',
  'shirt_pink': 'Shirt_Pink',
  // ... 50+ तत्व मैपिंग
};

जब बच्चा "गोल सिर + नीली शर्ट" चुनता है, तो ऐप:

  1. Rive एलिमेंट Head_Round को सक्षम करता है
  2. Rive एलिमेंट Shirt_Blue को सक्षम करता है
  3. अन्य सभी सिर के आकार और शर्ट रंगों को अक्षम करता है
  4. बच्चा का व्यक्तिगत अवतार पूरी ऐप में दिखता है

क्यों Rive दूसरों से बेहतर है?

विशेषताRiveLottieस्प्राइट शीट्सवीडियो
स्टेट मशीनें
रनटाइम कंट्रोलपूर्णआंशिकमैनुअलनहीं
फाइल साइज1-2 MB2-3 MB50+ MB100+ MB
परफॉर्मेंस60fps GPU30fps CPU60fps GPUपरिवर्तनीय
इंटरैक्टिविटीपूर्णआंशिकपूर्णनहीं
लर्निंग कर्वमध्यमआसानआसानआसान
मेंटेनेंसएक .riv फाइलएक JSONसैंकड़ों इमेजएक वीडियो

Rive इसलिए बेहतर है क्योंकि हमें प्रोग्रामैटिक कंट्रोल, स्टेट मशीन, और मोबाइल ऐप के लिए कॉम्पैक्ट फाइल की जरूरत है।

प्रदर्शन अनुकूलन

  • पात्र प्रीलोड करें: ऐप स्टार्टअप पर .riv फाइलें लोड करें, प्रत्येक अभ्यास पर नहीं।
  • GPU रेंडरिंग: Rive उपलब्ध GPUs का उपयोग करता है, पुराने डिवाइसों पर CPU पर चलते हैं।
  • मेमोरी पूलिंग: स्क्रीन के बीच Rive कंट्रोलर्स को पुन: उपयोग करें ताकि गारबेज संग्रहण रोका जा सके।
  • कंप्रेशन: Rive फाइलें पहले से ही संपीड़ित होती हैं; अतिरिक्त ऑप्टिमाइज़ेशन की ज़रूरत नहीं।

नतीजा: Snapdragon 662+ (2019 के मिड-रेंज फोन) पर 60fps एनिमेशन।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

प्रश्न: क्या Adobe Animate से Rive में सीधे एनिमेशन निर्यात कर सकते हैं?
उत्तर: नहीं। हम Rive का देशी एडिटर (rive.app) उपयोग करते हैं। एनिमेटर Rive में डिजाइन करते हैं, Animate या After Effects में नहीं। वर्कफ़्लो है: Rive में पात्र डिज़ाइन करें → .riv एक्सपोर्ट करें → Flutter ऐप में इंटीग्रेट करें।

प्रश्न: अलग-अलग शरीर प्रकार या विकलांगताएं कैसे संभालते हैं?
उत्तर: अवतार कस्टमाइजेशन में शरीर के प्रकार (पतला, मजबूत, गोल), चश्मा, सुनने के उपकरण, और मोबिलिटी एड्स जैसे सहायक उपकरण शामिल हैं ताकि सभी बच्चे प्रतिनिधित्व देख सकें।

प्रश्न: अगर बच्चे को अपना अवतार पसंद न आए तो?
उत्तर: वे कभी भी अनुकूलित कर सकते हैं। ऐप बच्चों को रचनात्मक पूरी स्वतंत्रता देता है, कोई ज़बरदस्ती नहीं।

साझा करेंTwitterLinkedInWhatsApp

संबंधित लेख