ultron-ai-sdk 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,35 +16,37 @@ npm install ultron-ai-sdk
16
16
 
17
17
  ```javascript
18
18
  // Import the SDK
19
- import {SceneCanvas, Character} from './dist/index.mjs';
19
+ import {SceneCanvas, Character} from 'ultron-ai-sdk';
20
20
 
21
- let devices = await navigator.mediaDevices.enumerateDevices();
22
- console.log(devices)
23
- let sceneCanvas
24
- let character
25
-
26
- const init = async() => {
27
- sceneCanvas = new SceneCanvas('target-html-element')
28
- const initializationSetting= {
29
- avatarId: "AVATAR_ID/REQUEST_ID",
30
- config:{
31
- accessToken : "ACCESS_TOKEN",
32
- refreshToken : "REFRESH_TOKEN",
33
- // sessionId : "426536db-25a4-4682-9bb4-4e93530f84a0",
34
- apiKey: "YOUR_ULTRON_API_KEY"
35
- },
36
- options:{
37
- alwaysListen: false // For Push to talk conversation
38
- }
21
+ let sceneCanvas
22
+ let character
23
+
24
+ const init = async() => {
25
+ sceneCanvas = new SceneCanvas('target-html-element')
26
+ const initializationSetting= {
27
+ avatarId: "AVATAR_ID", // AvatarId and Request Id are same
28
+ config:{
29
+ accessToken: 'YOUR_CURRENT_AUTH_TOKEN', // Can be accessed from your app.ultronai.me localstorage data
30
+ apiKey: "YOUR_ULTRON_API_KEY"
31
+ },
32
+ options:{
33
+ alwaysListen: false // For Push to talk conversation
39
34
  }
40
- await sceneCanvas.init(initializationSetting)
41
- character = sceneCanvas.character
42
-
43
35
  }
44
- init()
36
+ await sceneCanvas.init(initializationSetting)
37
+ character = sceneCanvas.character
38
+
39
+ }
40
+ init()
45
41
 
46
42
  ```
47
43
 
44
+ #### Quick Demo
45
+
46
+ Check out our website for demo at: [🔗Talk to Avatar in metabrix website](https://dev-website.ultronai.me)
47
+
48
+
49
+
48
50
  ---
49
51
 
50
52
  ## Target HTML Element
@@ -61,8 +63,7 @@ import {SceneCanvas, Character} from './dist/index.mjs';
61
63
 
62
64
  ```javascript
63
65
  const sceneCanvas = new SceneCanvas('target-html-element')
64
-
65
- ultronSDK.init(config)
66
+ sceneCanvas.init(config)
66
67
  ```
67
68
 
68
69
  ---
@@ -71,11 +72,27 @@ ultronSDK.init(config)
71
72
 
72
73
  | Option | Description |
73
74
  |-------------|--------------|
74
- | `accessToken` | Token recieved on successfull authentication |
75
- | `refreshToken` |Token recieved on successfull refreshing of existing access token |
75
+ | `accessToken` (optional) | accessToken current logged in Account |
76
76
  | `sessionId` (optional) | Session Id obtained using API key |
77
77
  | `apiKey` | You ultron key which can be found in your profile in Ultron App |
78
78
 
79
+ #### API key (apiKey)
80
+
81
+ To get API key of your ultron account follow the steps below
82
+
83
+ ### STEP 1: Click on account at top right corner
84
+
85
+ ![Avatar ID step 1](https://media.ultronai.me/Images/website/apikeysh1.png)
86
+
87
+ ### STEP 2: Select API key from dropdown
88
+
89
+ ![Avatar ID step 1](https://media.ultronai.me/Images/website/apikey2.png)
90
+
91
+ ### STEP 3: Copy your API key
92
+
93
+ ![Avatar ID step 1](https://media.ultronai.me/Images/website/apishe3.png)
94
+
95
+
79
96
  ---
80
97
 
81
98
  ## Core Methods
@@ -86,8 +103,24 @@ Loads a specific avatar into the container.
86
103
 
87
104
  - `avatarId`: **String** - The unique identifier for the avatar
88
105
 
89
- ---
90
106
 
107
+ ### AvatarId
108
+
109
+ To get avatarId follow the steps below
110
+
111
+ ### Step 1: Open the desired avatar in ultron app (app.ultronai.me)
112
+
113
+ Click share on top right corner
114
+
115
+ ![Avatar ID step 1](https://media.ultronai.me/Images/website/avateridshar1.png)
116
+
117
+ ### Step 1: Open the desired avatar in ultron app (app.ultronai.me)
118
+
119
+ Step 2: Select the avatar id value as from share url
120
+
121
+ ![Avatar ID step 2](https://media.ultronai.me/Images/website/avartaridshare2.png)
122
+
123
+ ---
91
124
 
92
125
  ## Audio Input Device Settings
93
126
 
@@ -142,25 +175,27 @@ ultronSDK.setAudioInputDevice(myDevice.deviceId)
142
175
  ### Basic Implementation
143
176
 
144
177
  ```javascript
145
- import CharacterCompanionSDK from './dist/index.mjs';
146
-
147
- init=()=>{
148
- let sdk = new CharacterCompanionSDK('ultron-model')
149
- ultronSDK.init({
150
- accessToken : 'YOUR_ACCESS_TOKEN',
151
- refreshToken : 'YOUR_REFRESH_TOKEN',
152
- sessionId : "SESSIOON_ID", // If you have backend or it will create session from apiKey
153
- apiKey: "YOUR_ULTRON_API_KEY"
154
- })
155
- const avatarId = 'AVATAR_ID/REQUEST_ID'
156
- await ultronSDK.loadAvatarById(avatarId)
157
- ultronSDK.initAudioListener()
158
-
159
- // Load an avatar
160
- await ultron.loadAvatar('avatar-id');
161
- }
162
-
163
- init()
178
+ import {SceneCanvas, Character} from 'ultron-ai-sdk';
179
+
180
+ let sceneCanvas
181
+ let character
182
+
183
+ const init = async() => {
184
+ sceneCanvas = new SceneCanvas('target-html-element')
185
+ const initializationSetting= {
186
+ avatarId: "AVATAR_ID/REQUEST_ID",
187
+ config:{
188
+ apiKey: "YOUR_ULTRON_API_KEY"
189
+ },
190
+ options:{
191
+ alwaysListen: false // For Push to talk conversation
192
+ }
193
+ }
194
+ await sceneCanvas.init(initializationSetting)
195
+ character = sceneCanvas.character
196
+
197
+ }
198
+ init()
164
199
  ```
165
200
 
166
201
  ---
@@ -168,7 +203,9 @@ init()
168
203
  ### Chat with character using AI
169
204
 
170
205
  ```javascript
171
- ultronSDK.chat("your text query to AI")
206
+ // once you have the "character" object from sceneCanvas after init() you can use it to chat
207
+
208
+ character.chat("your text query to AI")
172
209
 
173
210
  //This will generate a response from AI as per Avatar backstory and character will speak the response
174
211
 
@@ -178,7 +215,8 @@ ultronSDK.chat("your text query to AI")
178
215
  ### Make the character say
179
216
 
180
217
  ```javascript
181
- ultronSDK.say("your text that character will speak")
218
+
219
+ character.say("your text that character will speak")
182
220
 
183
221
  // This will simply make the character speak the text you provide
184
222
 
@@ -189,11 +227,11 @@ ultronSDK.say("your text that character will speak")
189
227
  ```javascript
190
228
  //Switch camera to potrait (closer to face)
191
229
 
192
- ultronSDK.switchCameraToPotrait()
230
+ sceneCanvas.switchCameraToPotrait()
193
231
 
194
232
  //Switch camera to normal position (full body view)
195
233
 
196
- ultronSDK.switchCameraToNormal()
234
+ sceneCanvas.switchCameraToNormal()
197
235
 
198
236
 
199
237
 
package/dist/index.cjs CHANGED
@@ -43655,6 +43655,7 @@ class AudioListener {
43655
43655
  stopListening() {
43656
43656
  if (this.mediaRecorder && this.mediaRecorder.state === "recording") {
43657
43657
  this.mediaRecorder.stop();
43658
+
43658
43659
  this.stream.getTracks().forEach(track => {
43659
43660
  track.stop();
43660
43661
 
@@ -43693,10 +43694,13 @@ class AudioListener {
43693
43694
 
43694
43695
  }
43695
43696
 
43696
- detectSilence(silenceThreshold = -50, silenceDuration = 2000) {
43697
+ detectSilence(silenceThreshold = -40, silenceDuration = 700, maxListenDuration = 10) {
43697
43698
  const bufferLength = this.analyser.frequencyBinCount;
43698
43699
  const dataArray = new Uint8Array(bufferLength);
43699
-
43700
+ this.maxkimitTimeout = setTimeout(()=>{
43701
+ console.log("Max time limite reached, stopping recording...");
43702
+ this.stopListening();
43703
+ },maxListenDuration*1000);
43700
43704
  const checkSilence = () => {
43701
43705
  if (!this.mediaRecorder || this.mediaRecorder.state !== "recording") return;
43702
43706
 
@@ -43928,6 +43932,7 @@ class SceneCanvas{
43928
43932
 
43929
43933
  addCharacter=(character)=>{
43930
43934
  this.character = character;
43935
+ this.character.sceneCanvasRef = this;
43931
43936
  this.scene.add(this.character.model);
43932
43937
  }
43933
43938
 
@@ -43959,23 +43964,31 @@ class SceneCanvas{
43959
43964
 
43960
43965
  console.log('adding mic button');
43961
43966
  // Create button element
43967
+ this.voiceElementBlock = document.createElement('div');
43968
+
43969
+ this.voiceElementBlock.style.position = 'absolute';
43970
+ this.voiceElementBlock.style.bottom = '20px';
43971
+ this.voiceElementBlock.style.marginLeft = '50%';
43972
+ this.voiceElementBlock.style.transition = 'background-color 0.2s';
43973
+ this.voiceElementBlock.style.transform = 'translate(-50%, 0%)';
43974
+
43962
43975
  const micButton = document.createElement('button');
43976
+ this.micButton = micButton;
43963
43977
  micButton.id = 'mic-button';
43964
43978
  // Mic emoji (you can replace with SVG if needed)
43965
43979
 
43966
43980
  // Apply styles (round, centered icon, etc.)
43967
- micButton.style.width = '64px';
43968
- micButton.style.height = '64px';
43981
+ micButton.style.width = '48px';
43982
+ micButton.style.height = '48px';
43969
43983
  micButton.style.borderRadius = '50%';
43970
43984
  micButton.style.backgroundColor = '#f1f1f1';
43971
- micButton.style.position = 'absolute';
43972
- micButton.style.bottom = '20px';
43973
- micButton.style.marginLeft = '50%';
43985
+
43986
+
43974
43987
 
43975
43988
  micButton.style.display = 'flex';
43976
43989
  micButton.style.alignItems = 'center';
43977
43990
  micButton.style.justifyContent = 'center';
43978
- micButton.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
43991
+ micButton.style.boxShadow = '0 4px 8px rgba(0,0,0,0.3)';
43979
43992
  micButton.style.cursor = 'pointer';
43980
43993
  micButton.style.border = 'none';
43981
43994
  micButton.style.fontSize = '24px';
@@ -43987,9 +44000,18 @@ class SceneCanvas{
43987
44000
  const micIcon = document.createElement('img');
43988
44001
  micIcon.src = micUrl;
43989
44002
  micIcon.alt = 'Mic Icon';
43990
- micIcon.style.width = '36px';
43991
- micIcon.style.height = '36px';
44003
+ micIcon.style.width = '26px';
44004
+ micIcon.style.height = '26px';
43992
44005
 
44006
+ this.voiceUIText = document.createElement('div');
44007
+ this.voiceUIText.style.display = 'none';
44008
+ this.voiceUIText.style.fontFamily = '"Inter", sans-serif';
44009
+ this.voiceUIText.style.fontSize = '20px';
44010
+ this.voiceUIText.style.color = "white";
44011
+ this.voiceUIText.style.backgroundColor = "#00000030";
44012
+ this.voiceUIText.style.padding = "4px";
44013
+
44014
+ this.voiceUIText.innerHTML = "Listening...";
43993
44015
  // Hover effect
43994
44016
  micButton.onmouseover = () => {
43995
44017
  micButton.style.backgroundColor = '#e5e5e5';
@@ -44006,7 +44028,10 @@ class SceneCanvas{
44006
44028
 
44007
44029
  // Append to target div
44008
44030
  micButton.appendChild(micIcon);
44009
- this.container.appendChild(micButton);
44031
+ this.voiceElementBlock.append(this.micButton);
44032
+ this.voiceElementBlock.append(this.voiceUIText);
44033
+
44034
+ this.container.appendChild(this.voiceElementBlock);
44010
44035
  }
44011
44036
  }
44012
44037
 
@@ -44052,10 +44077,23 @@ class Character {
44052
44077
  console.log('initializing audio listener');
44053
44078
  this.continuousConversation = alwaysListen;
44054
44079
  this.audioListener = new AudioListener();
44055
- this.audioListener.onSpeechStart = () => {console.log('Listening...'); };
44080
+ this.audioListener.onSpeechStart = () => {
44081
+ console.log('Listening...');
44082
+ if(this.sceneCanvasRef?.micButton){
44083
+ this.sceneCanvasRef.micButton.style.display = 'none';
44084
+ }
44085
+ if(this.sceneCanvasRef?.voiceUIText){
44086
+ this.sceneCanvasRef.voiceUIText.style.display = 'block';
44087
+ this.sceneCanvasRef.voiceUIText.innerHTML = "Listening...";
44088
+ }
44089
+
44090
+ };
44056
44091
  this.audioListener.onSpeechEnd = (audio) => {
44057
44092
  console.log("audio ended", audio);
44058
- this.AIServices.currentAudioChunks = [audio];
44093
+ this.AIServices.currentAudioChunks = [audio];
44094
+ if(this.sceneCanvasRef?.voiceUIText){
44095
+ this.sceneCanvasRef.voiceUIText.innerHTML = "Thinking...";
44096
+ }
44059
44097
  this.handleCurrentAudioMessage();
44060
44098
  };
44061
44099
  console.log(this.audioListener);
@@ -44093,6 +44131,7 @@ class Character {
44093
44131
  formData.append("lipSync", false);
44094
44132
 
44095
44133
  this.chatHistory.push({ text: 'audio', role: 'user' });
44134
+ // this.playAnimation('listening')
44096
44135
  await this.chat('audio',formData);
44097
44136
  // this.chatHistory.push({ text: response.text, role: 'assistant' });
44098
44137
  }
@@ -44240,14 +44279,27 @@ class Character {
44240
44279
  }, (duration - 0.5)*1000);
44241
44280
  }
44242
44281
  }
44282
+ if(this.sceneCanvasRef?.voiceUIText){
44283
+ this.sceneCanvasRef.voiceUIText.innerHTML = "Speaking...";
44284
+
44285
+ }
44243
44286
 
44244
44287
  }
44245
44288
 
44246
44289
  onSpeakComplete=()=>{
44247
- if(this.continuousConversation)
44290
+ if(this.continuousConversation){
44248
44291
  this.startListening();
44249
- else
44250
- this.playAnimation('idle');
44292
+ }else {
44293
+ if(this.sceneCanvasRef?.micButton){
44294
+ this.sceneCanvasRef.micButton.style.display = 'flex';
44295
+ }
44296
+ if(this.sceneCanvasRef?.voiceUIText){
44297
+ this.sceneCanvasRef.voiceUIText.style.display = 'none';
44298
+ this.sceneCanvasRef.voiceUIText.innerHTML = "";
44299
+ }
44300
+
44301
+ this.playAnimation('idle');
44302
+ }
44251
44303
  }
44252
44304
 
44253
44305
  processLipSync=(lipSyncData)=>{
package/dist/index.mjs CHANGED
@@ -43653,6 +43653,7 @@ class AudioListener {
43653
43653
  stopListening() {
43654
43654
  if (this.mediaRecorder && this.mediaRecorder.state === "recording") {
43655
43655
  this.mediaRecorder.stop();
43656
+
43656
43657
  this.stream.getTracks().forEach(track => {
43657
43658
  track.stop();
43658
43659
 
@@ -43691,10 +43692,13 @@ class AudioListener {
43691
43692
 
43692
43693
  }
43693
43694
 
43694
- detectSilence(silenceThreshold = -50, silenceDuration = 2000) {
43695
+ detectSilence(silenceThreshold = -40, silenceDuration = 700, maxListenDuration = 10) {
43695
43696
  const bufferLength = this.analyser.frequencyBinCount;
43696
43697
  const dataArray = new Uint8Array(bufferLength);
43697
-
43698
+ this.maxkimitTimeout = setTimeout(()=>{
43699
+ console.log("Max time limite reached, stopping recording...");
43700
+ this.stopListening();
43701
+ },maxListenDuration*1000);
43698
43702
  const checkSilence = () => {
43699
43703
  if (!this.mediaRecorder || this.mediaRecorder.state !== "recording") return;
43700
43704
 
@@ -43926,6 +43930,7 @@ class SceneCanvas{
43926
43930
 
43927
43931
  addCharacter=(character)=>{
43928
43932
  this.character = character;
43933
+ this.character.sceneCanvasRef = this;
43929
43934
  this.scene.add(this.character.model);
43930
43935
  }
43931
43936
 
@@ -43957,23 +43962,31 @@ class SceneCanvas{
43957
43962
 
43958
43963
  console.log('adding mic button');
43959
43964
  // Create button element
43965
+ this.voiceElementBlock = document.createElement('div');
43966
+
43967
+ this.voiceElementBlock.style.position = 'absolute';
43968
+ this.voiceElementBlock.style.bottom = '20px';
43969
+ this.voiceElementBlock.style.marginLeft = '50%';
43970
+ this.voiceElementBlock.style.transition = 'background-color 0.2s';
43971
+ this.voiceElementBlock.style.transform = 'translate(-50%, 0%)';
43972
+
43960
43973
  const micButton = document.createElement('button');
43974
+ this.micButton = micButton;
43961
43975
  micButton.id = 'mic-button';
43962
43976
  // Mic emoji (you can replace with SVG if needed)
43963
43977
 
43964
43978
  // Apply styles (round, centered icon, etc.)
43965
- micButton.style.width = '64px';
43966
- micButton.style.height = '64px';
43979
+ micButton.style.width = '48px';
43980
+ micButton.style.height = '48px';
43967
43981
  micButton.style.borderRadius = '50%';
43968
43982
  micButton.style.backgroundColor = '#f1f1f1';
43969
- micButton.style.position = 'absolute';
43970
- micButton.style.bottom = '20px';
43971
- micButton.style.marginLeft = '50%';
43983
+
43984
+
43972
43985
 
43973
43986
  micButton.style.display = 'flex';
43974
43987
  micButton.style.alignItems = 'center';
43975
43988
  micButton.style.justifyContent = 'center';
43976
- micButton.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
43989
+ micButton.style.boxShadow = '0 4px 8px rgba(0,0,0,0.3)';
43977
43990
  micButton.style.cursor = 'pointer';
43978
43991
  micButton.style.border = 'none';
43979
43992
  micButton.style.fontSize = '24px';
@@ -43985,9 +43998,18 @@ class SceneCanvas{
43985
43998
  const micIcon = document.createElement('img');
43986
43999
  micIcon.src = micUrl;
43987
44000
  micIcon.alt = 'Mic Icon';
43988
- micIcon.style.width = '36px';
43989
- micIcon.style.height = '36px';
44001
+ micIcon.style.width = '26px';
44002
+ micIcon.style.height = '26px';
43990
44003
 
44004
+ this.voiceUIText = document.createElement('div');
44005
+ this.voiceUIText.style.display = 'none';
44006
+ this.voiceUIText.style.fontFamily = '"Inter", sans-serif';
44007
+ this.voiceUIText.style.fontSize = '20px';
44008
+ this.voiceUIText.style.color = "white";
44009
+ this.voiceUIText.style.backgroundColor = "#00000030";
44010
+ this.voiceUIText.style.padding = "4px";
44011
+
44012
+ this.voiceUIText.innerHTML = "Listening...";
43991
44013
  // Hover effect
43992
44014
  micButton.onmouseover = () => {
43993
44015
  micButton.style.backgroundColor = '#e5e5e5';
@@ -44004,7 +44026,10 @@ class SceneCanvas{
44004
44026
 
44005
44027
  // Append to target div
44006
44028
  micButton.appendChild(micIcon);
44007
- this.container.appendChild(micButton);
44029
+ this.voiceElementBlock.append(this.micButton);
44030
+ this.voiceElementBlock.append(this.voiceUIText);
44031
+
44032
+ this.container.appendChild(this.voiceElementBlock);
44008
44033
  }
44009
44034
  }
44010
44035
 
@@ -44050,10 +44075,23 @@ class Character {
44050
44075
  console.log('initializing audio listener');
44051
44076
  this.continuousConversation = alwaysListen;
44052
44077
  this.audioListener = new AudioListener();
44053
- this.audioListener.onSpeechStart = () => {console.log('Listening...'); };
44078
+ this.audioListener.onSpeechStart = () => {
44079
+ console.log('Listening...');
44080
+ if(this.sceneCanvasRef?.micButton){
44081
+ this.sceneCanvasRef.micButton.style.display = 'none';
44082
+ }
44083
+ if(this.sceneCanvasRef?.voiceUIText){
44084
+ this.sceneCanvasRef.voiceUIText.style.display = 'block';
44085
+ this.sceneCanvasRef.voiceUIText.innerHTML = "Listening...";
44086
+ }
44087
+
44088
+ };
44054
44089
  this.audioListener.onSpeechEnd = (audio) => {
44055
44090
  console.log("audio ended", audio);
44056
- this.AIServices.currentAudioChunks = [audio];
44091
+ this.AIServices.currentAudioChunks = [audio];
44092
+ if(this.sceneCanvasRef?.voiceUIText){
44093
+ this.sceneCanvasRef.voiceUIText.innerHTML = "Thinking...";
44094
+ }
44057
44095
  this.handleCurrentAudioMessage();
44058
44096
  };
44059
44097
  console.log(this.audioListener);
@@ -44091,6 +44129,7 @@ class Character {
44091
44129
  formData.append("lipSync", false);
44092
44130
 
44093
44131
  this.chatHistory.push({ text: 'audio', role: 'user' });
44132
+ // this.playAnimation('listening')
44094
44133
  await this.chat('audio',formData);
44095
44134
  // this.chatHistory.push({ text: response.text, role: 'assistant' });
44096
44135
  }
@@ -44238,14 +44277,27 @@ class Character {
44238
44277
  }, (duration - 0.5)*1000);
44239
44278
  }
44240
44279
  }
44280
+ if(this.sceneCanvasRef?.voiceUIText){
44281
+ this.sceneCanvasRef.voiceUIText.innerHTML = "Speaking...";
44282
+
44283
+ }
44241
44284
 
44242
44285
  }
44243
44286
 
44244
44287
  onSpeakComplete=()=>{
44245
- if(this.continuousConversation)
44288
+ if(this.continuousConversation){
44246
44289
  this.startListening();
44247
- else
44248
- this.playAnimation('idle');
44290
+ }else {
44291
+ if(this.sceneCanvasRef?.micButton){
44292
+ this.sceneCanvasRef.micButton.style.display = 'flex';
44293
+ }
44294
+ if(this.sceneCanvasRef?.voiceUIText){
44295
+ this.sceneCanvasRef.voiceUIText.style.display = 'none';
44296
+ this.sceneCanvasRef.voiceUIText.innerHTML = "";
44297
+ }
44298
+
44299
+ this.playAnimation('idle');
44300
+ }
44249
44301
  }
44250
44302
 
44251
44303
  processLipSync=(lipSyncData)=>{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultron-ai-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "This package is for integrating Ultron AI Characters as website Companions on a website",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",