The real-time digital-human SDK provides a simple API for quickly integrating digital-human interactions across platforms, including Web, iOS, Android, and Mini Program.
- Multi-platform support: Web, iOS, Android, and Mini Program.
- Floating-button entry: Open the digital-human chat interface with one click.
- Custom loading screen: Customize loading UI for a better experience.
- Hot-word filtering: Filter sensitive terms in interactions.
- Easy to use: A concise API for quick integration.
- Web (browser)
- iOS (Swift)
- Android (Kotlin/Java)
- Mini Program (WeChat Mini Program)
Before you begin, complete these steps on the NuwaAI platform:
- Register and sign in to a NuwaAI account.
- Record your user ID.
- Create a digital human and record its ID.
- Create and save an API key.
Get an API key, digital-human ID, and user ID
Choose the installation method for your platform:
npm install nuwaai-human-sdk
Now create your first digital-human interaction application:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SDK initialization</title>
<link rel="stylesheet" href="/node_modules/nuwaai-human-sdk/css/demo.css">
<script type="module" src="/node_modules/nuwaai-human-sdk/js/npcTalkFloatingButton.js"></script>
</head>
<body>
<div class="container">
<h1>🔧 SDK initialization settings</h1>
<form id="sdkForm">
<div class="form-group">
<label for="apiKey">API Key</label>
<input type="text" id="apiKey" name="apiKey" placeholder="Enter your API key" value="sk-jqZ-gBPcRCG1nLpaenmS1gew7rcCkIs-NUWSPzpd3DeWYxobM_CHm-uPTCa8gDPv">
</div>
<div class="form-group">
<label for="avatarId">Digital-human ID</label>
<input type="text" id="avatarId" name="avatarId" placeholder="Enter the digital-human ID" value="2027224426241638401">
</div>
<div class="form-group">
<label for="userId">User ID</label>
<input type="text" id="userId" name="userId" placeholder="Enter the user ID" value="54">
</div>
<button type="button" class="btn-init" onclick="initializeSDK()">Initialize SDK</button>
</form>
<div id="result" class="result"></div>
</div>
<script>
function initializeSDK() {
let floatingButtonInstance = null;
const apiKey = document.getElementById('apiKey').value.trim();
const avatarId = document.getElementById('avatarId').value.trim();
const userId = document.getElementById('userId').value.trim();
const resultDiv = document.getElementById('result');
if (!apiKey || !avatarId || !userId) {
resultDiv.className = 'result error';
resultDiv.textContent = 'Complete all required fields';
return;
}
fetch('https://api.nuwaai.com/web/apiKey/auth', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
secretKey: apiKey,
}),
})
.then(res => res.json())
.then(data => {
if (data.code === 0) {
console.log('token:', data.data);
localStorage.setItem('token', data.data);
initWithCustomLoading(avatarId, userId);
} else {
console.error('Request failed:', data.msg);
}
})
.catch(error => {
console.error('Request error:', error);
});
function initWithCustomLoading(avatorId, userId) {
try {
if (floatingButtonInstance) {
floatingButtonInstance.destroy();
}
floatingButtonInstance = new window.NpcTalkFloatingButton({
avatorid: avatorId,
userid: userId,
npcPage1: '/node_modules/nuwaai-human-sdk/index-sdk.html',
loadingConfig: null,
disabledButton: false,
title: 'Digital-human chat',
href: '',
sliceTime:10000,
backAddress:'',
hotWords:['咱们','休息一下','你好呀']
});
} catch (error) {
console.error('Initialization failed:', error);
}
}
}
document.getElementById('sdkForm').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
initializeSDK();
}
});
</script>
</body>
</html>
import UIKit
import NuwaSDK
class ViewController: UIViewController {
private var apiKeyTextField: UITextField!
private var avatarIdTextField: UITextField!
private var userIdTextField: UITextField!
private var initializeButton: UIButton!
private var floatingButton: NuwaFloatingButton?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
title = "Nuwa SDK initialization"
setupUI()
}
func setupUI() {
let screenWidth = view.frame.size.width
let padding: CGFloat = 40
let fieldWidth = screenWidth - padding * 2
let fieldHeight: CGFloat = 50
let verticalSpacing: CGFloat = 24
let topOffset: CGFloat = 120
let apiKeyLabel = createLabel(withText: "API Key", y: topOffset)
view.addSubview(apiKeyLabel)
apiKeyTextField = createTextField(withY: apiKeyLabel.frame.origin.y + apiKeyLabel.frame.size.height + 8)
apiKeyTextField.placeholder = "Enter the API key"
apiKeyTextField.text = "sk-u96kvX4vRJ9CtX7Zj4KSK-CnHXpihy4B6ehyyw8v8SwfDIUbEwA_HmFTG3E_jGMy"
view.addSubview(apiKeyTextField)
let avatarIdLabel = createLabel(withText: "Digital-human ID", y: apiKeyTextField.frame.origin.y + apiKeyTextField.frame.size.height + verticalSpacing)
view.addSubview(avatarIdLabel)
avatarIdTextField = createTextField(withY: avatarIdLabel.frame.origin.y + avatarIdLabel.frame.size.height + 8)
avatarIdTextField.placeholder = "Enter the digital-human ID"
avatarIdTextField.text = "2031288580266336258"
view.addSubview(avatarIdTextField)
let userIdLabel = createLabel(withText: "User ID", y: avatarIdTextField.frame.origin.y + avatarIdTextField.frame.size.height + verticalSpacing)
view.addSubview(userIdLabel)
userIdTextField = createTextField(withY: userIdLabel.frame.origin.y + userIdLabel.frame.size.height + 8)
userIdTextField.placeholder = "Enter the user ID"
userIdTextField.text = "54"
view.addSubview(userIdTextField)
initializeButton = UIButton(type: .system)
initializeButton.frame = CGRect(x: padding, y: userIdTextField.frame.origin.y + userIdTextField.frame.size.height + verticalSpacing * 2, width: fieldWidth, height: fieldHeight)
initializeButton.setTitle("Initialize SDK", for: .normal)
initializeButton.backgroundColor = UIColor(red: 0.122, green: 0.467, blue: 0.918, alpha: 1.0)
initializeButton.setTitleColor(.white, for: .normal)
initializeButton.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
initializeButton.layer.cornerRadius = 8
initializeButton.layer.shadowColor = UIColor.black.cgColor
initializeButton.layer.shadowOffset = CGSize(width: 0, height: 2)
initializeButton.layer.shadowOpacity = 0.1
initializeButton.layer.shadowRadius = 4
initializeButton.addTarget(self, action: #selector(initSDK), for: .touchUpInside)
view.addSubview(initializeButton)
}
func createLabel(withText text: String, y: CGFloat) -> UILabel {
let padding: CGFloat = 40
let screenWidth = view.frame.size.width
let label = UILabel(frame: CGRect(x: padding, y: y, width: screenWidth - padding * 2, height: 24))
label.text = text
label.font = UIFont.systemFont(ofSize: 14, weight: .medium)
label.textColor = UIColor(red: 0.333, green: 0.333, blue: 0.333, alpha: 1.0)
return label
}
func createTextField(withY y: CGFloat) -> UITextField {
let padding: CGFloat = 40
let screenWidth = view.frame.size.width
let textField = UITextField(frame: CGRect(x: padding, y: y, width: screenWidth - padding * 2, height: 50))
textField.borderStyle = .roundedRect
textField.font = UIFont.systemFont(ofSize: 16)
textField.backgroundColor = UIColor(red: 0.957, green: 0.957, blue: 0.957, alpha: 1.0)
textField.layer.cornerRadius = 8
textField.layer.borderWidth = 1
textField.layer.borderColor = UIColor(red: 0.878, green: 0.878, blue: 0.878, alpha: 1.0).cgColor
return textField
}
@objc func initSDK() {
guard let apiKey = apiKeyTextField.text, !apiKey.isEmpty else {
showAlert(withTitle: "Notice", message: "Enter the API key")
return
}
guard let avatarId = avatarIdTextField.text, !avatarId.isEmpty else {
showAlert(withTitle: "Notice", message: "Enter the digital-human ID")
return
}
let userId = userIdTextField.text ?? ""
let config = NuwaFloatingButtonConfig()
config.apiKey = apiKey
config.avatorId = avatarId
config.userId = userId
floatingButton = NuwaFloatingButton(config: config)
floatingButton?.show(in: view)
showAlert(withTitle: "Success", message: "The SDK was initialized and the floating button is now visible")
}
func showAlert(withTitle title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
}
}
#import <UIKit/UIKit.h>
#import "NuwaSDK.h"
@interface ViewController : UIViewController
@property (nonatomic, strong) UITextField *apiKeyTextField;
@property (nonatomic, strong) UITextField *avatarIdTextField;
@property (nonatomic, strong) UITextField *userIdTextField;
@property (nonatomic, strong) UIButton *initializeButton;
@property (nonatomic, strong) NuwaFloatingButton *floatingButton;
@end
#import "ViewController.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"Nuwa SDK initialization";
[self setupUI];
}
- (void)setupUI {
CGFloat screenWidth = self.view.frame.size.width;
CGFloat padding = 40;
CGFloat fieldWidth = screenWidth - padding * 2;
CGFloat fieldHeight = 50;
CGFloat verticalSpacing = 24;
CGFloat topOffset = 120;
UILabel *apiKeyLabel = [self createLabelWithText:@"API Key" y:topOffset];
[self.view addSubview:apiKeyLabel];
self.apiKeyTextField = [self createTextFieldWithY:apiKeyLabel.frame.origin.y + apiKeyLabel.frame.size.height + 8];
self.apiKeyTextField.placeholder = @"Enter the API key";
self.apiKeyTextField.text = @"sk-u96kvX4vRJ9CtX7Zj4KSK-CnHXpihy4B6ehyyw8v8SwfDIUbEwA_HmFTG3E_jGMy";
[self.view addSubview:self.apiKeyTextField];
UILabel *avatarIdLabel = [self createLabelWithText:@"Digital-human ID" y:self.apiKeyTextField.frame.origin.y + self.apiKeyTextField.frame.size.height + verticalSpacing];
[self.view addSubview:avatarIdLabel];
self.avatarIdTextField = [self createTextFieldWithY:avatarIdLabel.frame.origin.y + avatarIdLabel.frame.size.height + 8];
self.avatarIdTextField.placeholder = @"Enter the digital-human ID";
self.avatarIdTextField.text = @"2031288580266336258";
[self.view addSubview:self.avatarIdTextField];
UILabel *userIdLabel = [self createLabelWithText:@"User ID" y:self.avatarIdTextField.frame.origin.y + self.avatarIdTextField.frame.size.height + verticalSpacing];
[self.view addSubview:userIdLabel];
self.userIdTextField = [self createTextFieldWithY:userIdLabel.frame.origin.y + userIdLabel.frame.size.height + 8];
self.userIdTextField.placeholder = @"Enter the user ID";
self.userIdTextField.text = @"54";
[self.view addSubview:self.userIdTextField];
self.initializeButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.initializeButton.frame = CGRectMake(padding, self.userIdTextField.frame.origin.y + self.userIdTextField.frame.size.height + verticalSpacing * 2, fieldWidth, fieldHeight);
[self.initializeButton setTitle:@"Initialize SDK" forState:UIControlStateNormal];
self.initializeButton.backgroundColor = [UIColor colorWithRed:0.122 green:0.467 blue:0.918 alpha:1.0];
[self.initializeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
self.initializeButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
self.initializeButton.layer.cornerRadius = 8;
self.initializeButton.layer.shadowColor = [UIColor blackColor].CGColor;
self.initializeButton.layer.shadowOffset = CGSizeMake(0, 2);
self.initializeButton.layer.shadowOpacity = 0.1;
self.initializeButton.layer.shadowRadius = 4;
[self.initializeButton addTarget:self action:@selector(initSDK) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.initializeButton];
}
- (UILabel *)createLabelWithText:(NSString *)text y:(CGFloat)y {
CGFloat padding = 40;
CGFloat screenWidth = self.view.frame.size.width;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(padding, y, screenWidth - padding * 2, 24)];
label.text = text;
label.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
label.textColor = [UIColor colorWithRed:0.333 green:0.333 blue:0.333 alpha:1.0];
return label;
}
- (UITextField *)createTextFieldWithY:(CGFloat)y {
CGFloat padding = 40;
CGFloat screenWidth = self.view.frame.size.width;
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(padding, y, screenWidth - padding * 2, 50)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.font = [UIFont systemFontOfSize:16];
textField.backgroundColor = [UIColor colorWithRed:0.957 green:0.957 blue:0.957 alpha:1.0];
textField.layer.cornerRadius = 8;
textField.layer.borderWidth = 1;
textField.layer.borderColor = [UIColor colorWithRed:0.878 green:0.878 blue:0.878 alpha:1.0].CGColor;
return textField;
}
- (void)initSDK {
NSString *apiKey = self.apiKeyTextField.text;
NSString *avatarId = self.avatarIdTextField.text;
NSString *userId = self.userIdTextField.text;
if (!apiKey || apiKey.length == 0) {
[self showAlertWithTitle:@"Notice" message:@"Enter the API key"];
return;
}
if (!avatarId || avatarId.length == 0) {
[self showAlertWithTitle:@"Notice" message:@"Enter the digital-human ID"];
return;
}
NuwaFloatingButtonConfig *config = [[NuwaFloatingButtonConfig alloc] init];
config.apiKey = apiKey;
config.avatorId = avatarId;
config.userId = userId;
self.floatingButton = [[NuwaFloatingButton alloc] initWithConfig:config];
[self.floatingButton showInView:self.view];
[self showAlertWithTitle:@"Success" message:@"The SDK was initialized and the floating button is now visible"];
}
- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:okAction];
[self presentViewController:alert animated:YES completion:nil];
}
@end
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.nuwaai.human.NuwaHumanLoadingConfig;
import com.nuwaai.human.NuwaHumanSDK;
import com.nuwaai.human.NuwaHumanSDKOptions;
import com.nuwaai.sdk.NuwaAIClient;
import com.nuwaai.sdk.NuwaAIConfig;
import com.nuwaai.sdk.NuwaCallback;
import java.util.ArrayList;
import java.util.List;
public class HumanDemoActivity extends AppCompatActivity {
private EditText etApiKey;
private EditText etAvatarId;
private EditText etUserId;
private EditText etHotWords;
private CheckBox cbHideFloat;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_human_demo);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Digital-human interaction");
}
initViews();
setupClickListeners();
}
@Override
public boolean onSupportNavigateUp() {
finish();
return true;
}
private void initViews() {
etApiKey = findViewById(R.id.et_api_key);
etAvatarId = findViewById(R.id.et_avatar_id);
etUserId = findViewById(R.id.et_user_id);
etHotWords = findViewById(R.id.et_hot_words);
cbHideFloat = findViewById(R.id.cb_hide_float);
etAvatarId.setText("2027224426241638401");
etUserId.setText("54");
etHotWords.setText("咱们,休息一下,你好呀");
}
private void setupClickListeners() {
findViewById(R.id.btn_init_sdk).setOnClickListener(v -> initializeSDK());
findViewById(R.id.btn_navigate_talk).setOnClickListener(v -> {
NuwaHumanSDK sdk = NuwaHumanSDK.getInstance();
if (sdk == null) {
Toast.makeText(this, "Initialize the SDK first", Toast.LENGTH_SHORT).show();
return;
}
sdk.navigateToNpcTalk();
});
findViewById(R.id.btn_show_float).setOnClickListener(v -> {
NuwaHumanSDK sdk = NuwaHumanSDK.getInstance();
if (sdk == null) {
Toast.makeText(this, "Initialize the SDK first", Toast.LENGTH_SHORT).show();
return;
}
sdk.showFloatingButton();
});
findViewById(R.id.btn_hide_float).setOnClickListener(v -> {
NuwaHumanSDK sdk = NuwaHumanSDK.getInstance();
if (sdk == null) {
Toast.makeText(this, "Initialize the SDK first", Toast.LENGTH_SHORT).show();
return;
}
sdk.hideFloatingButton();
});
findViewById(R.id.btn_destroy_sdk).setOnClickListener(v -> {
NuwaHumanSDK sdk = NuwaHumanSDK.getInstance();
if (sdk != null) {
sdk.destroy();
Toast.makeText(this, "SDK destroyed", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "No SDK instance exists", Toast.LENGTH_SHORT).show();
}
});
}
private void initializeSDK() {
String apiKey = etApiKey.getText().toString().trim();
String avatarId = etAvatarId.getText().toString().trim();
String userId = etUserId.getText().toString().trim();
boolean hideFloat = cbHideFloat.isChecked();
if (avatarId.isEmpty() || userId.isEmpty()) {
Toast.makeText(this, "Enter the digital-human ID and user ID", Toast.LENGTH_SHORT).show();
return;
}
if (apiKey.isEmpty()) {
Toast.makeText(this, "Enter the API key (used only for nuwaai-sdk authentication; it is not passed to the digital-human SDK)", Toast.LENGTH_SHORT).show();
return;
}
NuwaAIConfig config = NuwaAIConfig.builder().apiKey(apiKey).build();
NuwaAIClient.init(config);
NuwaAIClient.getInstance().authenticate(new NuwaCallback<String>() {
@Override
public void onSuccess(String token) {
runOnUiThread(() -> {
NuwaHumanLoadingConfig loadingConfig = NuwaHumanLoadingConfig.builder()
.html("<div class=\"loading\">Loading...</div>")
.style("display", "flex")
.style("flex-direction", "column")
.style("align-items", "center")
.style("justify-content", "center")
.style("background", "#111111")
.style("color", "#eeeeee")
.additionalCss(
".custom-loading-container .loading{text-align:center;width:100%;}")
.build();
NuwaHumanSDKOptions options = NuwaHumanSDKOptions.builder()
.avatarId(avatarId)
.userId(userId)
.token(token)
.loadingConfig(loadingConfig)
.disabledButton(hideFloat)
.hotWords(parseHotWords(etHotWords.getText().toString()))
.build();
NuwaHumanSDK.initialize(HumanDemoActivity.this, options);
Toast.makeText(HumanDemoActivity.this,
hideFloat ? "Initialized without showing the floating button" : "Initialized and showing the floating button",
Toast.LENGTH_SHORT).show();
});
}
@Override
public void onFailure(int code, String message) {
runOnUiThread(() -> Toast.makeText(HumanDemoActivity.this,
"Authentication failed: " + message, Toast.LENGTH_SHORT).show());
}
});
}
private static List<String> parseHotWords(String raw) {
if (raw == null || raw.trim().isEmpty()) {
return new ArrayList<>();
}
String[] parts = raw.split(",");
List<String> list = new ArrayList<>();
for (String p : parts) {
String t = p.trim();
if (!t.isEmpty()) {
list.add(t);
}
}
return list;
}
}
<web-view src="{{webUrl}}" ></web-view>
You have now integrated the Nuwa real-time digital-human SDK into your application.
Web integration demo: open the demo
Before using the SDK, obtain an access token: Get an access token
let floatingButtonInstance = new window.NpcTalkFloatingButton({
avatorid: '2027224426241638401',
userid: '54',
npcPage1: 'index-sdk.html',
loadingConfig: {
html: '<div class="loading">Loading...</div>',
style: {
background: '#fff',
color: '#333'
}
},
disabledButton: false,
title: 'Digital-human chat',
href: '',
sliceTime: 10000,
backAddress: '',
hotWord: ['咱们', '休息一下', '你好呀']
});
let config = NuwaFloatingButtonConfig()
config.apiKey = "your_api_key"
config.avatorId = "your_avatar_id"
config.userId = "your_user_id"
let floatingButton = NuwaFloatingButton(config: config)
floatingButton.show(in: view)
NuwaHumanLoadingConfig loadingConfig = NuwaHumanLoadingConfig.builder()
.html("<div class=\"loading\">Loading...</div>")
.additionalCss(
".custom-loading-container .loading{text-align:center;width:100%;}")
.build();
NuwaHumanSDKOptions options = NuwaHumanSDKOptions.builder()
.avatarId(avatarId)
.userId(userId)
.token(token)
.loadingConfig(loadingConfig)
.disabledButton(false)
.build();
NuwaHumanSDK.initialize(HumanDemoActivity.this, options);
| Parameter | Type | Required | Description | Platform |
|---|
| avatorid | String | Yes | Digital-human ID | All |
| userid | String | Yes | User ID | All |
| token | String | Yes | Access token | iOS/Android/Mini Program |
| npcPage1 | String | Yes | Digital-human chat page path | Web/Mini Program |
| loadingConfig | Object | No | Custom loading-screen configuration | All |
| disabledButton | Boolean | No | Whether to hide the floating button | All |
| title | String | No | Page title | Web/iOS/Android |
| href | String | No | Page logo URL | Web |
| sliceTime | Number | No | Time slice in milliseconds | Web |
| backAddress | String | No | Return URL | Web |
| hotWord | Array | No | Hot-word list for sensitive-term filtering | All |
Customize the loading screen to improve user experience:
const loadingConfig = {
html: `
<div class="custom-loading-wrapper">
<div class="custom-loading-spinner"></div>
<div class="custom-loading-text">Connecting to the digital human...</div>
<div class="custom-loading-subtext">Please wait</div>
</div>
`,
style: {
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
},
additionalCSS: `
.custom-loading-container .custom-loading-wrapper {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.custom-loading-container .custom-loading-spinner {
width: 60px;
height: 60px;
border: 4px solid rgba(255, 255, 255, 0.3);
border-top-color: white;
border-radius: 50%;
animation: custom-loading-spin 1s linear infinite;
margin-bottom: 20px;
}
@keyframes custom-loading-spin {
to { transform: rotate(360deg); }
}
`,
};
floatingButtonInstance = new window.NpcTalkFloatingButton({
loadingConfig: loadingConfig
});
func initSDK() {
let activityIndicator = UIActivityIndicatorView(style: .large)
activityIndicator.center = view.center
activityIndicator.color = .blue
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
activityIndicator.stopAnimating()
activityIndicator.removeFromSuperview()
let config = NuwaFloatingButtonConfig()
config.apiKey = "your_api_key"
config.avatorId = "your_avatar_id"
config.userId = "your_user_id"
let floatingButton = NuwaFloatingButton(config: config)
floatingButton.show(in: self.view)
self.showAlert(withTitle: "Success", message: "The SDK was initialized and the floating button is now visible")
}
}
NuwaHumanLoadingConfig loadingConfig = NuwaHumanLoadingConfig.builder()
.html("<div class=\"loading\">Loading...</div>")
.style("display", "flex")
.style("flex-direction", "column")
.style("align-items", "center")
.style("justify-content", "center")
.style("background", "#111111")
.style("color", "#eeeeee")
.additionalCss(
".custom-loading-container .loading{text-align:center;width:100%;}")
.build();
NuwaHumanSDKOptions options = NuwaHumanSDKOptions.builder()
.loadingConfig(loadingConfig)
.build();
NuwaHumanSDK.initialize(HumanDemoActivity.this, options);
floatingButtonInstance = new window.NpcTalkFloatingButton({
disabledButton: true
});
floatingButtonInstance.navigateToNpcTalk();
floatingButtonInstance.destroy();
floatingButton?.show(in: view)
floatingButton?.hide()
NuwaHumanSDKOptions options = NuwaHumanSDKOptions.builder()
.disabledButton(true)
.build();
NuwaHumanSDK.initialize(HumanDemoActivity.this, options);
NuwaHumanSDK.getInstance().navigateToNpcTalk()
NuwaHumanSDK.getInstance().showFloatingButton()
NuwaHumanSDK.getInstance().hideFloatingButton()
NuwaHumanSDK.getInstance().destroy()
| Method | Description | Platform |
|---|
| showFloatingButton() | Show the floating button | All |
| hideFloatingButton() | Hide the floating button | All |
| navigateToNpcTalk() | Open the digital-human chat interface | All |
- The device must have a microphone.
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
- Microphone permission is required.
- iOS 12.0+
- Xcode 12.0+
- Swift 5.0+
- Add microphone permission to
Info.plist:
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required for voice calls</string>
Install NuwaSDK:
- With CocoaPods, add
pod 'NuwaSDK' to the Podfile. - Or add
NuwaSDK.framework directly to the project.
Import the headers:
Create the configuration:
let config = NuwaFloatingButtonConfig()
config.apiKey = "your_api_key"
config.avatorId = "your_avatar_id"
config.userId = "your_user_id"
Create and show the floating button:
let floatingButton = NuwaFloatingButton(config: config)
floatingButton.show(in: view)
Hide the floating button (optional):
- Android 5.0+
- minSdkVersion 21+
- targetSdkVersion 33+
Add the required permissions to AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
- WeChat Mini Program base library 2.10.0 or later.
- Real-time audio/video capability enabled.
Add the required settings to app.json:
{
"requiredBackgroundModes": ["audio", "video"],
"permission": {
"scope.camera": {
"desc": "Required for video calls"
},
"scope.record": {
"desc": "Required for voice calls"
}
}
}
Issue: The digital-human chat interface does not appear after clicking the floating button.
Solution:
- Check that the
npcPage1 path is correct. - Ensure the page exists and is accessible.
- Check browser console or logs for errors.
Issue: Hot-word filtering is not taking effect.
Solution:
- Ensure
hotWord is an array. - Verify the hot words are configured correctly and use the required format.
- Issue: Floating button does not appear. Solution: Verify the API key and digital-human ID, and check the network.
- Issue: Video does not appear. Solution: Add camera permission and verify the camera is available.
- Issue: Audio does not work. Solution: Add microphone permission and ensure device volume is enabled.
- Issue: Permission denied. Solution: Request microphone permission at runtime.
- Issue: Unable to open the microphone. Solution: Ensure the user has granted microphone permission.