روند انیمیشن Rive در آموزش کاراکترهای عربی
5 دقیقه مطالعهMohammad Shaker

روند انیمیشن Rive در آموزش کاراکترهای عربی

Amal با استفاده از Rive شخصیت‌های عربی را انیمیشن‌سازی می‌کند؛ شامل هماهنگی لب‌ها، سفارشی‌سازی آواتار و حرکات پاسخ‌دهی.

Engineering

پاسخ سریع

Amal با استفاده از Rive شخصیت‌های عربی را انیمیشن‌سازی می‌کند؛ شامل هماهنگی لب‌ها، سفارشی‌سازی آواتار و حرکات پاسخ‌دهی.

Amal از Rive (قبلاً Flare) برای تمام انیمیشن‌های شخصیت‌ها استفاده می‌کند — شامل هماهنگی لب‌ها با گفتار، سفارشی‌سازی آواتار، واکنش‌های بازخوردی و شخصیت‌های بازی. ما Rive را به جای Lottie یا شیپت‌های اسپریتی انتخاب کردیم زیرا از ماشین حالت زمان اجرا، دستکاری برنامه‌ای و رندر شتاب‌یافته با GPU با نرخ ۶۰ فریم بر ثانیه به صورت یک فایل فشرده به ازای هر شخصیت پشتیبانی می‌کند.

کتابخانه دارایی‌های انیمیشن

شخصیت‌های اصلی

  • lip-sync-amal-01.riv
    • شخصیت اصلی Amal (نسخه‌های تمام‌قد و فقط صورت)
    • چند تخته هنری به ازای هر حالت دهان (برای نگاشت فونم)
    • حالت‌ها: آرام، صحبت کردن، خطا، جشن، خواب
    • حجم فایل: ۱.۲ مگابایت (در مقابل بیش از ۵۰ مگابایت برای شیپت‌های اسپریتی)
  • avatar.riv
    • آواتار قابل سفارشی‌سازی کاربر (۳ تخته هنری)
      1. تمام‌قد: سر، تنه، اندام‌ها با لباس
      2. فقط سر: برای داشبورد و اپ والدین
      3. همراه پروانه: انیمیشن پاداش
    • معماری مبتنی بر اجزا: شکل سر، مو، چشم‌ها، لباس‌ها، لوازم، رنگ‌ها
    • حجم فایل: ۲.۴ مگابایت
  • coin-01.riv و coins-01.riv
    • انیمیشن‌های پاداش (شناور و جمع‌آوری کردن سکه‌ها)
    • سکه تکی: ۱۵۰ کیلوبایت
    • چند سکه: ۳۰۰ کیلوبایت
  • cute-monster-final.riv
    • شخصیت بازخورد با چند حالت احساسی
    • حالت‌ها: خوشحال (جواب درست)، سردرگم (اشتباه)، تفکر (در حال پردازش)، جشن گرفتن (سلسله پیروزی‌ها)
    • حجم فایل: ۱.۸ مگابایت

بهینه‌سازی مخصوص اندروید

  • ساخت NDK سفارشی (نسخه Rive NDK-r28) برای تطابق با ترازبندی صفحه ۱۶ کیلوبایتی
  • کاهش حجم باینری ۸٪ در مقابل ساخت استاندارد
  • تضمین سازگاری با مدیریت حافظه تهاجمی در اندروید ۱۲ و بالاتر

روند هماهنگی لب‌ها (توضیح فنی)

مرحله ۱: تولید صوت 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
    )
    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  # زمان‌های دقیق فونم‌ها
    }

مرحله ۲: نگاشت فونم‌ها به حالت‌های دهان در 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 } },
    ...
  ]
}

مرحله ۳: کنترل‌کننده LipSync برای هماهنگی پخش

// 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) {
    // مرحله ۱: بارگذاری شخصیت Rive
    riveCharacter.loadRiveFile('lip-sync-amal-01.riv');
    
    // مرحله ۲: بارگذاری نشانه‌های گفتار از خروجی TTS
    mapper = LipSyncMapper.fromJson(loadJsonAsset('lip_sync_avatar.json'));
    
    // مرحله ۳: پخش صوت و کنترل انیمیشن دهان
    audioPlayer.play(AudioSource.file(audioPath));
    
    // مرحله ۴: به‌روزرسانی موقعیت دهان در هر فریم صوتی
    audioPlayer.onPositionChanged.listen((Duration position) {
      String phoneme = mapper.phonemeAtTime(position.inMilliseconds);
      String riveState = mapper.riveStateForPhoneme(phoneme);
      
      riveCharacter.setStateInput('mouth_state', riveState);
    });
  }
}

مرحله ۴: کنترل‌کننده شخصیت Rive مدیریت چرخه عمر

// مدیریت وضعیت کامل انیمیشن شخصیت (نه فقط دهان)
class RiveCharacterController extends GetxController {
  States: idle → prepare → speaking → idle → error/celebration
  
  void startExercise() {
    // انتقال به حالت آماده به شنیدن
    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 (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',
  // ... بیش از ۵۰ نگاشت عناصر دیگر
};

وقتی کودک "سر گرد + پیراهن آبی" را انتخاب می‌کند، اپلیکیشن:

  1. عنصر Rive Head_Round را فعال می‌کند
  2. عنصر Rive Shirt_Blue را فعال می‌کند
  3. تمام شکل‌های دیگر سر و رنگ‌های پیراهن را غیرفعال می‌کند
  4. آواتار شخصی‌سازی شده کودک در سراسر اپ ظاهر می‌شود

چرا Rive را به جای گزینه‌های دیگر انتخاب کردیم

ویژگیRiveLottieشیپت‌های اسپریتیویدئو
ماشین‌های حالت
کنترل زمان اجرا✓ (کامل)جزئیدستی✗ (غیرفعال)
حجم فایل۱-۲ مگابایت۲-۳ مگابایت۵۰+ مگابایت۱۰۰+ مگابایت
کارایی۶۰fps با GPU۳۰fps با CPU۶۰fps با GPUمتغیر
تعامل✓ کامل✓ جزئی✓ کامل✗ ندارد
چالش یادگیریمتوسطآسانآسانآسان
نگهدارییک فایل .rivیک JSONصدها تصویریک ویدئو

با این مقایسه Rive برنده است چون ما نیاز به کنترل برنامه‌ای، ماشین‌های حالت و فشردگی برای اپ موبایل داریم.

بهینه‌سازی عملکرد

  • بارگذاری پیش‌بار: فایل‌های .riv هنگام شروع اپ بارگذاری می‌شوند، نه برای هر تمرین
  • رندر GPU: Rive به صورت خودکار از GPU استفاده می‌کند و روی دستگاه‌های قدیمی‌تر با CPU ادامه می‌دهد
  • حوضچه حافظه: استفاده مجدد از کنترلرهای Rive بین صفحات برای جلوگیری از توقف‌های جمع‌آوری زباله
  • فشرده‌سازی: فایل‌های Rive به طور ذاتی فشرده هستند و نیاز به بهینه‌سازی اضافه ندارند

نتیجه: انیمیشن ۶۰ فریم بر ثانیه روی پردازنده Snapdragon 662 و بالاتر (گوشی‌های میان‌رده ۲۰۱۹).

سؤالات متداول

سؤال: آیا می‌توان انیمیشن‌ها را از Adobe Animate به Rive صادر کرد؟
خیر، مستقیم خیر. ما از ویرایشگر بومی Rive (rive.app) استفاده می‌کنیم. انیماتورها در Rive طراحی می‌کنند و خروجی .riv را در اپلیکیشن Flutter استفاده می‌کنیم.

سؤال: چه طور انواع بدن یا معلولیت‌ها را مدیریت می‌کنید؟
سفارشی‌سازی آواتار شامل گزینه‌های انواع بدن (لاغر، ورزشی، گرد) و لوازم جانبی (عینک، سمعک، کمک‌های حرکتی) است تا همه کودکان احساس نمایندگی داشته باشند.

سؤال: اگر کودکی از آواتار خود خوشش نیاید چه؟
آنها هر زمان می‌توانند آواتار خود را تغییر دهند. اپ هیچ نمای خاصی را تحمیل نمی‌کند — کنترل خلاقیت کامل با کودکان است.

اشتراک‌گذاریTwitterLinkedInWhatsApp

مقالات مرتبط