avatar_kit 1.0.0-beta.1
avatar_kit: ^1.0.0-beta.1 copied to clipboard
A Flutter plugin for AvatarKit which provides avatar rendering with audio driving support.
example/lib/main.dart
import 'dart:convert';
import 'package:flutter/material.dart' hide ConnectionState;
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:avatar_kit/avatar_kit_plugin.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
MockData? mockData;
String version = '';
bool supportsCurrentDevice = false;
Avatar? avatar;
AvatarController? avatarController;
bool isConnected = false;
@override
void initState() {
super.initState();
initPlatformState();
// test: host mode
// loadMockData();
}
Future<void> initPlatformState() async {
try {
final configuration = Configuration(environment: Environment.test, drivingServiceMode: DrivingServiceMode.sdk, logLevel: LogLevel.all);
await AvatarSDK.initialize(appID: 'appID', configuration: configuration);
await AvatarSDK.setSessionToken('');
await AvatarSDK.setUserID('userID');
final version = await AvatarSDK.version();
final supportsCurrentDevice = await AvatarSDK.supportsCurrentDevice();
setState(() {
this.version = version;
this.supportsCurrentDevice = supportsCurrentDevice;
});
} catch (e) {
debugPrint(e.toString());
}
}
Future<void> loadMockData() async {
try {
final response = await http.get(
Uri.parse('https://avatar-sdk-go-test.spatialwalk.cn/media'),
);
if (response.statusCode == 200) {
final data = MockData.fromJson(jsonDecode(response.body));
setState(() {
mockData = data;
});
}
} catch (e) {
debugPrint('Fetching data failed: $e');
}
}
void schedulePlaying() async {
if (mockData == null) {
return;
}
final audioData = mockData!.audio;
final animations = mockData!.animations;
final conversationID = await avatarController!.yieldAudioData(audioData, end: true);
for (var i = 0; i < animations.length; i++) {
final animation = animations[i];
Future.delayed(Duration(seconds: i + 1), () {
avatarController!.yieldAnimations([animation], conversationID: conversationID);
},);
}
}
void setBackgroundImage() async {
final backgroundImage = await rootBundle.load('assets/background.jpeg').then((value) => value.buffer.asUint8List());
await avatarController!.setBackgroundImage(backgroundImage);
debugPrint('set background image: done');
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('AvatarKit Example'),
),
body: Center(child: Column(
children: [
Text('Version: $version'),
Text('Supports Current Device: $supportsCurrentDevice'),
Text('Is Connected: $isConnected'),
ElevatedButton(onPressed: () async {
try {
final avatar = await AvatarManager.shared.load(id: 'e41f7ee0-3807-4956-b169-1becf8497ebc', onProgress: (progress) {
debugPrint('load progress: $progress');
});
setState(() {
this.avatar = avatar;
});
} on AvatarError catch (e) {
debugPrint('load avatar error: ${e.name}');
} catch (e) {
debugPrint('load avatar failed: ${e.toString()}');
}
}, child: const Text('Load Avatar')),
Container(
margin: const EdgeInsets.only(top: 20),
width: 300,
height: 300,
child: avatar != null ? AvatarWidget(avatar: avatar!, onPlatformViewCreated: (controller) {
controller.onConnectionState = (state, errorMessage) {
debugPrint('onConnectionState: ${state.name}. ${errorMessage != null ? 'error: $errorMessage' : ''}');
setState(() {
isConnected = state == ConnectionState.connected;
});
};
controller.onConversationState = (state) {
debugPrint('onConversationState: ${state.name}');
};
controller.onError = (error) {
debugPrint('onError: ${error.name}');
};
// test volume
controller.setVolume(1.0).then((_) {
debugPrint('set volume: 1.0');
controller.volume().then((volume) {
debugPrint('get volume: $volume');
});
});
// test opaque
controller.setOpaque(false).then((_) {
debugPrint('set opaque: false');
controller.isOpaque().then((isOpaque) {
debugPrint('get isOpaque: $isOpaque');
});
});
// test background image
// setBackgroundImage();
setState(() {
avatarController = controller;
});
}) : const SizedBox.shrink(),
),
avatarController != null ? ElevatedButton(onPressed: () async {
await avatarController!.start();
}, child: const Text('Start')) : const SizedBox.shrink(),
avatarController != null ? ElevatedButton(onPressed: () async {
if (!isConnected) { return; }
final audioData = await rootBundle.load('assets/audio_01.pcm').then((value) => value.buffer.asUint8List());
final conversationID = await avatarController!.send(audioData, end: false);
debugPrint('send audio, conversationID: $conversationID');
}, child: const Text('Send Audio 01')) : const SizedBox.shrink(),
avatarController != null ? ElevatedButton(onPressed: () async {
if (!isConnected) { return; }
final audioData = await rootBundle.load('assets/audio_02.pcm').then((value) => value.buffer.asUint8List());
final conversationID = await avatarController!.send(audioData, end: true);
debugPrint('send audio, conversationID: $conversationID');
}, child: const Text('Send Audio 02')) : const SizedBox.shrink(),
avatarController != null ? ElevatedButton(onPressed: () async {
await avatarController!.interrupt();
}, child: const Text('Interrupt')) : const SizedBox.shrink(),
avatarController != null ? ElevatedButton(onPressed: () async {
await avatarController!.close();
}, child: const Text('Close')) : const SizedBox.shrink(),
// // test: host mode
// avatarController != null && mockData != null ? Column(
// children: [
// ElevatedButton(onPressed: () async {
// schedulePlaying();
// }, child: const Text('Schedule Playing'))
// ],
// ) : const SizedBox.shrink(),
],
)),
),
);
}
}
class MockData {
final Uint8List audio;
final List<Uint8List> animations;
MockData({required this.audio, required this.animations});
factory MockData.fromJson(Map<String, dynamic> json) {
return MockData(
audio: base64Decode(json['audio']),
animations: (json['animations'] as List<dynamic>)
.map<Uint8List>((animation) => base64Decode(animation as String))
.toList(),
);
}
}