liya_3d_avatar_widget_flutter 0.1.3
liya_3d_avatar_widget_flutter: ^0.1.3 copied to clipboard
Liya AI 3D Talking Avatar Widget for Flutter - WebView + Three.js + Native UI
Liya 3D Avatar Widget for Flutter #
A Flutter package that provides a 3D talking AI avatar widget with real-time lip-sync, voice input/output, and chat capabilities. Built with WebView + Three.js for high-quality 3D rendering.
Features #
- π 3D Avatar β High-quality 3D avatar with Ready Player Me support
- π Real-time Lip-sync β Viseme-based lip synchronization
- π€ Voice Input β Speech-to-text with native microphone support
- π Voice Output β Text-to-speech with natural voices
- π¬ Full Chat β Complete chat interface with message history
- π File Upload β Attach files to messages
- π¨ Customizable Theme β Match your app's design
- π± 3 Widget Modes β Standard, Modal Kiosk, Full Kiosk
Screenshots #
Standard Mode #
| Chat Panel | Avatar Speaking |
|---|---|
| [Standard Mode] | [Avatar Speaking] |
Kiosk Mode (Full Screen) #
| Kiosk Mode | Chat Interaction |
|---|---|
| [Kiosk Mode] | [Kiosk Chat] |
Modal Kiosk Mode #
| Modal Open | Modal Speaking |
|---|---|
| [Modal Mode] | [Modal Speaking] |
Installation #
Add to your pubspec.yaml:
dependencies:
liya_3d_avatar_widget_flutter: ^0.1.0
Then run:
flutter pub get
Platform Setup #
Android #
Add to android/app/src/main/AndroidManifest.xml:
<manifest>
<!-- Internet permission -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- Microphone permission (for voice input) -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!-- For file picker -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:usesCleartextTraffic="true"
...>
</application>
</manifest>
Set minimum SDK version in android/app/build.gradle:
android {
defaultConfig {
minSdkVersion 21
}
}
iOS #
Add to ios/Runner/Info.plist:
<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access for voice input</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app needs speech recognition for voice commands</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photo library access for file uploads</string>
Quick Start #
Basic Usage #
import 'package:liya_3d_avatar_widget_flutter/liya_3d_avatar_widget_flutter.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: LiyaAvatarWidget(
apiUrl: 'https://app-X-ai.liyalabs.com', // Your assigned backend URL (see GAR section)
apiKey: 'your_api_key',
assistantId: 'your_assistant_id',
),
),
);
}
}
Kiosk Mode (Full Screen) #
LiyaAvatarWidget(
apiUrl: 'https://app-X-ai.liyalabs.com', // Your assigned backend URL (see GAR section)
apiKey: 'your_api_key',
assistantId: 'your_assistant_id',
widgetMode: LiyaWidgetMode.kiosk,
assistantName: 'Liya AI',
welcomeMessage: 'Merhaba! Size nasΔ±l yardΔ±mcΔ± olabilirim?',
)
Modal Mode #
// Show as modal dialog
LiyaAvatarWidget.showModal(
context: context,
apiUrl: 'https://app-X-ai.liyalabs.com', // Your assigned backend URL (see GAR section)
apiKey: 'your_api_key',
assistantId: 'your_assistant_id',
);
Widget Parameters #
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
apiUrl |
String |
β | - | Backend API URL |
apiKey |
String |
β | - | API key for authentication |
assistantId |
String |
β | - | Assistant UUID |
assistantName |
String |
β | 'Liya AI' |
Display name for the assistant |
widgetMode |
LiyaWidgetMode |
β | standard |
Widget display mode |
welcomeMessage |
String |
β | null |
Initial greeting message |
avatarModelUrl |
String |
β | null |
Custom avatar GLB model URL |
theme |
LiyaTheme |
β | null |
Custom theme configuration |
enableVoice |
bool |
β | true |
Enable voice input/output |
enableFileUpload |
bool |
β | true |
Enable file attachments |
showSuggestions |
bool |
β | true |
Show suggestion chips |
suggestions |
List<String> |
β | [] |
Custom suggestion texts |
onMessageSent |
Function |
β | null |
Callback when user sends message |
onMessageReceived |
Function |
β | null |
Callback when AI responds |
onError |
Function |
β | null |
Error callback |
onAvatarLoaded |
Function |
β | null |
Called when avatar model loads |
Widget Modes #
LiyaWidgetMode.standard #
Default mode with avatar and chat panel side by side.
LiyaWidgetMode.modalKiosk #
Full-screen modal overlay, ideal for temporary interactions.
LiyaWidgetMode.kiosk #
Full-screen embedded mode, perfect for kiosk applications.
enum LiyaWidgetMode {
standard,
modalKiosk,
kiosk,
}
Theme Customization #
LiyaAvatarWidget(
// ... required params
theme: LiyaTheme(
primaryColor: Color(0xFF6366F1),
backgroundColor: Color(0xFF1A1A2E),
surfaceColor: Color(0xFF16213E),
textColor: Colors.white,
mutedTextColor: Colors.white70,
borderRadius: 16.0,
fontFamily: 'Inter',
),
)
LiyaTheme Properties #
| Property | Type | Default | Description |
|---|---|---|---|
primaryColor |
Color |
#6366F1 |
Primary accent color |
backgroundColor |
Color |
#1A1A2E |
Main background color |
surfaceColor |
Color |
#16213E |
Card/surface background |
textColor |
Color |
white |
Primary text color |
mutedTextColor |
Color |
white70 |
Secondary text color |
borderRadius |
double |
16.0 |
Border radius for cards |
fontFamily |
String |
null |
Custom font family |
Callbacks #
LiyaAvatarWidget(
// ... required params
onMessageSent: (String message, List<File>? files) {
print('User sent: $message');
},
onMessageReceived: (Map<String, dynamic> response) {
print('AI response: ${response['message']}');
},
onError: (String error) {
print('Error: $error');
},
onAvatarLoaded: () {
print('Avatar model loaded successfully');
},
)
Backend Requirements #
The widget requires a compatible backend API with the following endpoints:
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/external/chat/ |
Send chat message |
GET |
/api/v1/external/avatar/speech/ |
Get TTS audio |
POST |
/api/v1/external/chat/upload/ |
Upload file attachment |
GET |
/api/v1/external/sessions/ |
Get chat sessions |
Authentication #
All requests require the X-API-Key header:
X-API-Key: your_api_key
Chat Request Example #
POST /api/v1/external/chat/
{
"assistant_id": "uuid",
"message": "Hello!",
"session_id": "optional-session-uuid"
}
Chat Response Example #
{
"status": "success",
"data": {
"message": "Hello! How can I help you?",
"session_id": "uuid",
"visemes": [...],
"audio_url": "https://..."
}
}
Avatar Model Requirements #
Custom avatar models must be in GLB format with the following blend shapes for lip-sync:
viseme_silβ Silenceviseme_PPβ P, B, Mviseme_FFβ F, Vviseme_THβ Thviseme_DDβ D, T, Nviseme_kkβ K, Gviseme_CHβ Ch, J, Shviseme_SSβ S, Zviseme_nnβ N, Lviseme_RRβ Rviseme_aaβ Aviseme_Eβ Eviseme_Iβ Iviseme_Oβ Oviseme_Uβ U
Ready Player Me avatars are fully supported.
Troubleshooting #
WebView not loading on Android #
Ensure android:usesCleartextTraffic="true" is set in AndroidManifest.xml if using HTTP URLs.
Microphone permission denied #
Make sure to request microphone permission before using voice input:
import 'package:permission_handler/permission_handler.dart';
await Permission.microphone.request();
Audio not playing on iOS #
Add audio background mode to Info.plist if needed:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
Model not loading #
- Verify the GLB file URL is accessible
- Check CORS settings on your server
- Ensure the model has required blend shapes
Example App #
See the example directory for a complete sample application.
GAR (Global Application Router) #
Liya AI uses a distributed backend architecture. Each user is assigned to a specific backend instance.
Finding Your Backend URL #
Your backend URL is displayed in your Liya AI dashboard under Settings > API Configuration:
https://app-{X}-ai.liyalabs.com
Where {X} is your assigned instance number (1, 2, 3, etc.).
| Instance | Backend URL |
|---|---|
| 1 | https://app-1-ai.liyalabs.com |
| 2 | https://app-2-ai.liyalabs.com |
| 3 | https://app-3-ai.liyalabs.com |
Dynamic Configuration #
For production apps, fetch your backend URL from the mobile config endpoint:
final response = await http.get(
Uri.parse('https://app-1-ai.liyalabs.com/api/v1/external/mobile/config/')
);
final config = jsonDecode(response.body)['data'];
// config['base_url'] contains your dynamic backend URL
Live Demo #
See the Liya AI platform and avatar widget in action:
- Web Platform: ai.liyalabs.com β Create an assistant and experience the 3D avatar chat (same backend powers this Flutter widget)
- Website: liyalabs.com β Learn more about Liya AI capabilities
License #
MIT License - see LICENSE for details.
Support #
- π Website: liyalabs.com
- π Documentation: docs.liyalabs.com
- π Issues: GitHub Issues
- π§ Email: support@liyalabs.com