@unith-ai/core-client 2.0.5 → 2.0.6
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 +16 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/lib.js +1 -1
- package/dist/lib.js.map +1 -1
- package/dist/lib.module.js +1 -1
- package/dist/lib.module.js.map +1 -1
- package/dist/lib.web.js +212 -136
- package/dist/lib.web.js.map +1 -1
- package/dist/modules/connection.d.ts.map +1 -1
- package/dist/modules/idle-video.d.ts.map +1 -1
- package/dist/modules/microphone.d.ts +3 -3
- package/dist/modules/microphone.d.ts.map +1 -1
- package/dist/modules/video.d.ts +3 -1
- package/dist/modules/video.d.ts.map +1 -1
- package/dist/modules/vp8.d.ts +0 -2
- package/dist/modules/vp8.d.ts.map +1 -1
- package/dist/types/Conversation.d.ts +3 -0
- package/dist/types/Conversation.d.ts.map +1 -1
- package/dist/types/event.d.ts +6 -4
- package/dist/types/event.d.ts.map +1 -1
- package/dist/types/microphone.d.ts +4 -0
- package/dist/types/microphone.d.ts.map +1 -1
- package/dist/utils/microphone.d.ts +2 -7
- package/dist/utils/microphone.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/lib.web.js
CHANGED
|
@@ -503,6 +503,7 @@ var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
|
503
503
|
EventType2["PING"] = "ping";
|
|
504
504
|
EventType2["PONG"] = "pong";
|
|
505
505
|
EventType2["BINARY"] = "binary";
|
|
506
|
+
EventType2["STOP"] = "stop";
|
|
506
507
|
return EventType2;
|
|
507
508
|
})(EventType || {});
|
|
508
509
|
var StreamingEventType = /* @__PURE__ */ ((StreamingEventType2) => {
|
|
@@ -511,6 +512,7 @@ var StreamingEventType = /* @__PURE__ */ ((StreamingEventType2) => {
|
|
|
511
512
|
StreamingEventType2["METADATA"] = "metadata";
|
|
512
513
|
StreamingEventType2["ERROR"] = "error";
|
|
513
514
|
StreamingEventType2["CACHE"] = "cache";
|
|
515
|
+
StreamingEventType2["STOP"] = "stop";
|
|
514
516
|
return StreamingEventType2;
|
|
515
517
|
})(StreamingEventType || {});
|
|
516
518
|
function isJoinEvent(event) {
|
|
@@ -596,6 +598,17 @@ var Connection = class _Connection {
|
|
|
596
598
|
});
|
|
597
599
|
});
|
|
598
600
|
this.socket.addEventListener("close", (event) => {
|
|
601
|
+
if (this.onMessageCallback) {
|
|
602
|
+
const parsedEvent = {
|
|
603
|
+
event: "timeout" /* TIME_OUT */,
|
|
604
|
+
user_id: "",
|
|
605
|
+
username: ""
|
|
606
|
+
};
|
|
607
|
+
if (isValidSocketEvent(parsedEvent)) {
|
|
608
|
+
this.onMessageCallback(parsedEvent);
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
599
612
|
this.disconnect({
|
|
600
613
|
reason: "error",
|
|
601
614
|
message: event.reason || "The connection was closed by the server.",
|
|
@@ -700,6 +713,10 @@ var Connection = class _Connection {
|
|
|
700
713
|
this.socket.close();
|
|
701
714
|
}
|
|
702
715
|
sendMessage(message) {
|
|
716
|
+
if (this.socket.readyState !== WebSocket.OPEN) {
|
|
717
|
+
console.warn("Attempted to send a message on a closed socket.");
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
703
720
|
this.socket.send(JSON.stringify(message));
|
|
704
721
|
}
|
|
705
722
|
sendPingEvent(message) {
|
|
@@ -707,6 +724,7 @@ var Connection = class _Connection {
|
|
|
707
724
|
console.warn("Ping event sent without a callback set.");
|
|
708
725
|
return;
|
|
709
726
|
}
|
|
727
|
+
if (this.socket.readyState !== WebSocket.OPEN) return;
|
|
710
728
|
this.socket.send(JSON.stringify(message));
|
|
711
729
|
}
|
|
712
730
|
onPingPong(callback) {
|
|
@@ -753,11 +771,11 @@ var IdleVideo = class _IdleVideo {
|
|
|
753
771
|
);
|
|
754
772
|
}
|
|
755
773
|
} else {
|
|
756
|
-
const errorMessage = await response.
|
|
774
|
+
const errorMessage = await response.json();
|
|
757
775
|
const error = new Error(
|
|
758
|
-
|
|
776
|
+
errorMessage.detail || "An error occurred retrieving your digital human."
|
|
759
777
|
);
|
|
760
|
-
error.name = "
|
|
778
|
+
error.name = "headError";
|
|
761
779
|
throw error;
|
|
762
780
|
}
|
|
763
781
|
}
|
|
@@ -774,11 +792,11 @@ var IdleVideo = class _IdleVideo {
|
|
|
774
792
|
);
|
|
775
793
|
}
|
|
776
794
|
} else {
|
|
777
|
-
const errorMessage = await response.
|
|
795
|
+
const errorMessage = await response.json();
|
|
778
796
|
const error = new Error(
|
|
779
|
-
|
|
797
|
+
errorMessage.detail || "An error occurred retrieving your digital human."
|
|
780
798
|
);
|
|
781
|
-
error.name = "
|
|
799
|
+
error.name = "headError";
|
|
782
800
|
throw error;
|
|
783
801
|
}
|
|
784
802
|
}
|
|
@@ -795,11 +813,11 @@ var IdleVideo = class _IdleVideo {
|
|
|
795
813
|
);
|
|
796
814
|
}
|
|
797
815
|
} else {
|
|
798
|
-
const errorMessage = await response.
|
|
816
|
+
const errorMessage = await response.json();
|
|
799
817
|
const error = new Error(
|
|
800
|
-
|
|
818
|
+
errorMessage.detail || "An error occurred retrieving your digital human."
|
|
801
819
|
);
|
|
802
|
-
error.name = "
|
|
820
|
+
error.name = "headError";
|
|
803
821
|
throw error;
|
|
804
822
|
}
|
|
805
823
|
}
|
|
@@ -25406,15 +25424,54 @@ var N = class _N {
|
|
|
25406
25424
|
};
|
|
25407
25425
|
N.DEFAULT_BASE_URI = "wss://api.elevenlabs.io";
|
|
25408
25426
|
|
|
25427
|
+
// src/utils/storage.ts
|
|
25428
|
+
var storage = window.localStorage;
|
|
25429
|
+
var location = window.location.origin + window.location.pathname;
|
|
25430
|
+
var getFromStorage = (key, orgId, headId) => {
|
|
25431
|
+
if (typeof storage !== "undefined") {
|
|
25432
|
+
const prefix = `chat:${location}:${orgId}:${headId}:`;
|
|
25433
|
+
return storage.getItem(`${prefix}${key}`);
|
|
25434
|
+
}
|
|
25435
|
+
};
|
|
25436
|
+
var setToStorage = (key, val, orgId, headId) => {
|
|
25437
|
+
if (typeof storage !== "undefined") {
|
|
25438
|
+
const prefix = `chat:${location}:${orgId}:${headId}:`;
|
|
25439
|
+
storage.setItem(`${prefix}${key}`, val);
|
|
25440
|
+
return;
|
|
25441
|
+
}
|
|
25442
|
+
};
|
|
25443
|
+
|
|
25444
|
+
// src/utils/microphone.ts
|
|
25445
|
+
var EXPIRATION_OFFSET = 5 * 60 * 1e3;
|
|
25446
|
+
var defaultElevenLabsOptions = {
|
|
25447
|
+
vadSilenceThresholdSecs: 1.5,
|
|
25448
|
+
noiseSuppression: true,
|
|
25449
|
+
vadThreshold: 0.4,
|
|
25450
|
+
minSpeechDurationMs: 100,
|
|
25451
|
+
minSilenceDurationMs: 100,
|
|
25452
|
+
disableDynamicSpeechRecognition: false
|
|
25453
|
+
};
|
|
25454
|
+
function getLanguageCode(languageTag) {
|
|
25455
|
+
if (!languageTag || typeof languageTag !== "string") {
|
|
25456
|
+
throw new Error("Invalid language tag");
|
|
25457
|
+
}
|
|
25458
|
+
const parts = languageTag.trim().split("-");
|
|
25459
|
+
const languageCode = parts[0].toLowerCase();
|
|
25460
|
+
if (!/^[a-z]{2,3}$/.test(languageCode)) {
|
|
25461
|
+
throw new Error("Invalid ISO 639 language code format");
|
|
25462
|
+
}
|
|
25463
|
+
return languageCode;
|
|
25464
|
+
}
|
|
25465
|
+
|
|
25409
25466
|
// src/modules/microphone.ts
|
|
25410
25467
|
var Microphone = class _Microphone {
|
|
25411
|
-
constructor(provider, options, elevenLabsOptions, user, headInfo, microphoneAccess, token,
|
|
25468
|
+
constructor(provider, options, elevenLabsOptions, user, headInfo, microphoneAccess, token, voiceInterruptions) {
|
|
25412
25469
|
this.provider = provider;
|
|
25413
25470
|
this.options = options;
|
|
25414
25471
|
this.elevenLabsOptions = elevenLabsOptions;
|
|
25415
25472
|
this.user = user;
|
|
25416
25473
|
this.headInfo = headInfo;
|
|
25417
|
-
this.
|
|
25474
|
+
this.voiceInterruptions = voiceInterruptions;
|
|
25418
25475
|
this.microphoneStatus = "OFF";
|
|
25419
25476
|
this.microphoneAccess = false;
|
|
25420
25477
|
this.recognizer = null;
|
|
@@ -25447,7 +25504,7 @@ var Microphone = class _Microphone {
|
|
|
25447
25504
|
* @param sendMessage
|
|
25448
25505
|
* @returns
|
|
25449
25506
|
*/
|
|
25450
|
-
static async initializeMicrophone(options, provider, elevenLabsOptions, user, headInfo, microphoneAccess,
|
|
25507
|
+
static async initializeMicrophone(options, provider, elevenLabsOptions, user, headInfo, microphoneAccess, voiceInterruptions) {
|
|
25451
25508
|
let token = {
|
|
25452
25509
|
token: "",
|
|
25453
25510
|
generatedAt: null,
|
|
@@ -25469,7 +25526,7 @@ var Microphone = class _Microphone {
|
|
|
25469
25526
|
headInfo,
|
|
25470
25527
|
microphoneAccess,
|
|
25471
25528
|
token,
|
|
25472
|
-
|
|
25529
|
+
voiceInterruptions
|
|
25473
25530
|
);
|
|
25474
25531
|
}
|
|
25475
25532
|
updateMicrophoneStatus(status) {
|
|
@@ -25499,13 +25556,33 @@ var Microphone = class _Microphone {
|
|
|
25499
25556
|
const sdk = speechSdk;
|
|
25500
25557
|
let SpeechConfig, AudioConfig, SpeechRecognizer, ResultReason, PhraseListGrammar;
|
|
25501
25558
|
if (sdk.SpeechConfig) {
|
|
25502
|
-
({
|
|
25559
|
+
({
|
|
25560
|
+
SpeechConfig,
|
|
25561
|
+
AudioConfig,
|
|
25562
|
+
SpeechRecognizer,
|
|
25563
|
+
ResultReason,
|
|
25564
|
+
PhraseListGrammar
|
|
25565
|
+
} = sdk);
|
|
25503
25566
|
} else if ((_a = sdk.default) == null ? void 0 : _a.SpeechConfig) {
|
|
25504
|
-
({
|
|
25567
|
+
({
|
|
25568
|
+
SpeechConfig,
|
|
25569
|
+
AudioConfig,
|
|
25570
|
+
SpeechRecognizer,
|
|
25571
|
+
ResultReason,
|
|
25572
|
+
PhraseListGrammar
|
|
25573
|
+
} = sdk.default);
|
|
25505
25574
|
} else if ((_b = sdk.SpeechSDK) == null ? void 0 : _b.SpeechConfig) {
|
|
25506
|
-
({
|
|
25575
|
+
({
|
|
25576
|
+
SpeechConfig,
|
|
25577
|
+
AudioConfig,
|
|
25578
|
+
SpeechRecognizer,
|
|
25579
|
+
ResultReason,
|
|
25580
|
+
PhraseListGrammar
|
|
25581
|
+
} = sdk.SpeechSDK);
|
|
25507
25582
|
} else {
|
|
25508
|
-
throw new Error(
|
|
25583
|
+
throw new Error(
|
|
25584
|
+
"Azure Speech SDK does not expose expected symbols. Ensure microsoft-cognitiveservices-speech-sdk is installed."
|
|
25585
|
+
);
|
|
25509
25586
|
}
|
|
25510
25587
|
const speechConfig = SpeechConfig.fromAuthorizationToken(
|
|
25511
25588
|
this.tokenObj.token,
|
|
@@ -25528,6 +25605,12 @@ var Microphone = class _Microphone {
|
|
|
25528
25605
|
});
|
|
25529
25606
|
}
|
|
25530
25607
|
};
|
|
25608
|
+
this.recognizer.recognizing = (_3, event) => {
|
|
25609
|
+
if (!this.voiceInterruptions || event.result.text.length < 2) return;
|
|
25610
|
+
this.options.onMicrophonePartialSpeechRecognitionResult({
|
|
25611
|
+
transcript: event.result.text
|
|
25612
|
+
});
|
|
25613
|
+
};
|
|
25531
25614
|
this.recognizer.startContinuousRecognitionAsync(
|
|
25532
25615
|
() => {
|
|
25533
25616
|
this.micBeep.play();
|
|
@@ -25565,11 +25648,10 @@ var Microphone = class _Microphone {
|
|
|
25565
25648
|
generatedAt: Date.now()
|
|
25566
25649
|
};
|
|
25567
25650
|
}
|
|
25568
|
-
|
|
25651
|
+
const params = {
|
|
25569
25652
|
token: this.tokenObj.token,
|
|
25570
25653
|
modelId: "scribe_v2_realtime",
|
|
25571
25654
|
includeTimestamps: false,
|
|
25572
|
-
// languageCode: getLanguageCode(this.headInfo.lang_speech_recognition),
|
|
25573
25655
|
microphone: {
|
|
25574
25656
|
echoCancellation: true,
|
|
25575
25657
|
noiseSuppression: this.elevenLabsOptions.noiseSuppression
|
|
@@ -25579,7 +25661,13 @@ var Microphone = class _Microphone {
|
|
|
25579
25661
|
vadThreshold: this.elevenLabsOptions.vadThreshold,
|
|
25580
25662
|
minSpeechDurationMs: this.elevenLabsOptions.minSpeechDurationMs,
|
|
25581
25663
|
minSilenceDurationMs: this.elevenLabsOptions.minSilenceDurationMs
|
|
25582
|
-
}
|
|
25664
|
+
};
|
|
25665
|
+
if (this.elevenLabsOptions.disableDynamicSpeechRecognition) {
|
|
25666
|
+
params.languageCode = getLanguageCode(
|
|
25667
|
+
this.headInfo.lang_speech_recognition || "en-US"
|
|
25668
|
+
);
|
|
25669
|
+
}
|
|
25670
|
+
this.connection = N.connect(params);
|
|
25583
25671
|
this.connection.on(P.SESSION_STARTED, () => {
|
|
25584
25672
|
this.micBeep.play();
|
|
25585
25673
|
this.updateMicrophoneStatus("ON");
|
|
@@ -25588,6 +25676,13 @@ var Microphone = class _Microphone {
|
|
|
25588
25676
|
if (data.text.length < 2 || data.text[0] === "(") return;
|
|
25589
25677
|
this.handleRecognitionResult(data.text);
|
|
25590
25678
|
});
|
|
25679
|
+
this.connection.on(P.PARTIAL_TRANSCRIPT, (data) => {
|
|
25680
|
+
if (!this.voiceInterruptions || data.text.length < 2 || data.text[0] === "(")
|
|
25681
|
+
return;
|
|
25682
|
+
this.options.onMicrophonePartialSpeechRecognitionResult({
|
|
25683
|
+
transcript: data.text
|
|
25684
|
+
});
|
|
25685
|
+
});
|
|
25591
25686
|
this.connection.on(P.ERROR, (error) => {
|
|
25592
25687
|
console.error("Error:", error);
|
|
25593
25688
|
this.options.onMicrophoneError({
|
|
@@ -25769,23 +25864,6 @@ var SyncController = class {
|
|
|
25769
25864
|
}
|
|
25770
25865
|
};
|
|
25771
25866
|
|
|
25772
|
-
// src/utils/storage.ts
|
|
25773
|
-
var storage = window.localStorage;
|
|
25774
|
-
var location = window.location.origin + window.location.pathname;
|
|
25775
|
-
var getFromStorage = (key, orgId, headId) => {
|
|
25776
|
-
if (typeof storage !== "undefined") {
|
|
25777
|
-
const prefix = `chat:${location}:${orgId}:${headId}:`;
|
|
25778
|
-
return storage.getItem(`${prefix}${key}`);
|
|
25779
|
-
}
|
|
25780
|
-
};
|
|
25781
|
-
var setToStorage = (key, val, orgId, headId) => {
|
|
25782
|
-
if (typeof storage !== "undefined") {
|
|
25783
|
-
const prefix = `chat:${location}:${orgId}:${headId}:`;
|
|
25784
|
-
storage.setItem(`${prefix}${key}`, val);
|
|
25785
|
-
return;
|
|
25786
|
-
}
|
|
25787
|
-
};
|
|
25788
|
-
|
|
25789
25867
|
// src/modules/user.ts
|
|
25790
25868
|
var User = class _User {
|
|
25791
25869
|
constructor(accessToken, tokenType, id, username, password, orgId, headId, apiBase) {
|
|
@@ -26173,7 +26251,7 @@ var Vp8VideoOutput = class _Vp8VideoOutput {
|
|
|
26173
26251
|
cancelAnimationFrame(this.animationFrameId);
|
|
26174
26252
|
this.animationFrameId = null;
|
|
26175
26253
|
}
|
|
26176
|
-
this.frameBuffer
|
|
26254
|
+
this.frameBuffer.splice(0);
|
|
26177
26255
|
this.isProcessingFrame = false;
|
|
26178
26256
|
this.currentSequenceId = 0;
|
|
26179
26257
|
this.startTime = 0;
|
|
@@ -26181,35 +26259,8 @@ var Vp8VideoOutput = class _Vp8VideoOutput {
|
|
|
26181
26259
|
count: 0,
|
|
26182
26260
|
lastTime: 0
|
|
26183
26261
|
};
|
|
26184
|
-
if (this.decoder && this.decoder.state === "configured") {
|
|
26185
|
-
try {
|
|
26186
|
-
this.decoder.flush();
|
|
26187
|
-
} catch (error) {
|
|
26188
|
-
console.warn("Error flushing decoder:", error);
|
|
26189
|
-
}
|
|
26190
|
-
}
|
|
26191
|
-
this.clearCanvas();
|
|
26192
26262
|
this.state = "ready" /* READY */;
|
|
26193
|
-
|
|
26194
|
-
interrupt(fadeOut = false) {
|
|
26195
|
-
if (this.state === "destroyed" /* DESTROYED */) return;
|
|
26196
|
-
this.state = "interrupted" /* INTERRUPTED */;
|
|
26197
|
-
this.frameBuffer = [];
|
|
26198
|
-
this.isProcessingFrame = false;
|
|
26199
|
-
if (this.decoder && this.decoder.state === "configured") {
|
|
26200
|
-
try {
|
|
26201
|
-
this.decoder.flush();
|
|
26202
|
-
} catch (error) {
|
|
26203
|
-
console.warn("Error flushing decoder:", error);
|
|
26204
|
-
}
|
|
26205
|
-
}
|
|
26206
|
-
if (fadeOut) {
|
|
26207
|
-
this.fadeOutCanvas().then(() => {
|
|
26208
|
-
this.clearCanvas();
|
|
26209
|
-
});
|
|
26210
|
-
} else {
|
|
26211
|
-
this.clearCanvas();
|
|
26212
|
-
}
|
|
26263
|
+
return;
|
|
26213
26264
|
}
|
|
26214
26265
|
destroy() {
|
|
26215
26266
|
if (this.state === "destroyed" /* DESTROYED */) return;
|
|
@@ -26315,22 +26366,6 @@ var Vp8VideoOutput = class _Vp8VideoOutput {
|
|
|
26315
26366
|
clearCanvas() {
|
|
26316
26367
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
26317
26368
|
}
|
|
26318
|
-
async fadeOutCanvas() {
|
|
26319
|
-
return new Promise((resolve) => {
|
|
26320
|
-
let opacity = 1;
|
|
26321
|
-
const fadeStep = () => {
|
|
26322
|
-
opacity -= 0.05;
|
|
26323
|
-
this.canvas.style.opacity = opacity.toString();
|
|
26324
|
-
if (opacity <= 0) {
|
|
26325
|
-
this.canvas.style.opacity = "1";
|
|
26326
|
-
resolve();
|
|
26327
|
-
} else {
|
|
26328
|
-
requestAnimationFrame(fadeStep);
|
|
26329
|
-
}
|
|
26330
|
-
};
|
|
26331
|
-
fadeStep();
|
|
26332
|
-
});
|
|
26333
|
-
}
|
|
26334
26369
|
setupContextLossHandling() {
|
|
26335
26370
|
this.handleContextLoss = (event) => {
|
|
26336
26371
|
event.preventDefault();
|
|
@@ -26365,6 +26400,7 @@ var VideoOutput = class _VideoOutput {
|
|
|
26365
26400
|
this.bufferCheckAnimationId = null;
|
|
26366
26401
|
this.lastBufferCheckTime = 0;
|
|
26367
26402
|
this.sessionStarted = false;
|
|
26403
|
+
this.isRestoringIdleVideo = false;
|
|
26368
26404
|
//cached video
|
|
26369
26405
|
this.isShowingCachedVideo = false;
|
|
26370
26406
|
this.onSpeakingStartCallback = null;
|
|
@@ -26468,7 +26504,7 @@ var VideoOutput = class _VideoOutput {
|
|
|
26468
26504
|
this.lastBufferCheckTime = 0;
|
|
26469
26505
|
const checkBuffer = (timestamp) => {
|
|
26470
26506
|
if (timestamp - this.lastBufferCheckTime >= 100) {
|
|
26471
|
-
if (this.sessionStarted && this.videoOutput.getBufferLength() > 0) {
|
|
26507
|
+
if (this.sessionStarted && this.videoOutput.getBufferLength() > 0 && !this.isRestoringIdleVideo) {
|
|
26472
26508
|
this.hideIdleVideoBeforeStream();
|
|
26473
26509
|
} else if (!this.videoOutput.getStreamingStatus() && this.videoOutput.getBufferLength() === 0) {
|
|
26474
26510
|
this.showIdleVideoAfterStream();
|
|
@@ -26512,7 +26548,20 @@ var VideoOutput = class _VideoOutput {
|
|
|
26512
26548
|
{ once: true }
|
|
26513
26549
|
);
|
|
26514
26550
|
} catch (error) {
|
|
26515
|
-
|
|
26551
|
+
this.cachedVideo.style.opacity = "0";
|
|
26552
|
+
this.isShowingCachedVideo = false;
|
|
26553
|
+
await this.showIdleVideo();
|
|
26554
|
+
}
|
|
26555
|
+
}
|
|
26556
|
+
async stopCachedVideo() {
|
|
26557
|
+
if (!this.isShowingCachedVideo || !this.cachedVideo || this.isTransitioning)
|
|
26558
|
+
return;
|
|
26559
|
+
this.isShowingCachedVideo = false;
|
|
26560
|
+
try {
|
|
26561
|
+
await this.crossfadeFromCachedToIdle();
|
|
26562
|
+
await this.cleanupCachedVideo();
|
|
26563
|
+
await this.showIdleVideo();
|
|
26564
|
+
} catch (error) {
|
|
26516
26565
|
this.cachedVideo.style.opacity = "0";
|
|
26517
26566
|
this.isShowingCachedVideo = false;
|
|
26518
26567
|
await this.showIdleVideo();
|
|
@@ -26587,6 +26636,9 @@ var VideoOutput = class _VideoOutput {
|
|
|
26587
26636
|
getStreamingStatus() {
|
|
26588
26637
|
return this.videoOutput.getStreamingStatus();
|
|
26589
26638
|
}
|
|
26639
|
+
isPlayingCachedVideo() {
|
|
26640
|
+
return this.isShowingCachedVideo;
|
|
26641
|
+
}
|
|
26590
26642
|
async showIdleVideo() {
|
|
26591
26643
|
var _a, _b;
|
|
26592
26644
|
if (!this.idleVideo || this.isShowingIdleVideo) return;
|
|
@@ -26623,15 +26675,16 @@ var VideoOutput = class _VideoOutput {
|
|
|
26623
26675
|
return this.videoOutput.addFrame(uint8Array, timeStamp, isKeyframe);
|
|
26624
26676
|
}
|
|
26625
26677
|
clearFrame() {
|
|
26626
|
-
this.
|
|
26627
|
-
|
|
26678
|
+
this.isRestoringIdleVideo = true;
|
|
26679
|
+
this.showIdleVideoAfterStream();
|
|
26680
|
+
this.videoOutput.clearFrame();
|
|
26628
26681
|
}
|
|
26629
26682
|
async toggleStream(status) {
|
|
26683
|
+
if (status) {
|
|
26684
|
+
this.isRestoringIdleVideo = false;
|
|
26685
|
+
}
|
|
26630
26686
|
return this.videoOutput.toggleStream(status);
|
|
26631
26687
|
}
|
|
26632
|
-
interrupt(fadeOut) {
|
|
26633
|
-
this.videoOutput.interrupt(fadeOut);
|
|
26634
|
-
}
|
|
26635
26688
|
destroy() {
|
|
26636
26689
|
if (this.bufferCheckAnimationId) {
|
|
26637
26690
|
cancelAnimationFrame(this.bufferCheckAnimationId);
|
|
@@ -26655,16 +26708,6 @@ var VideoOutput = class _VideoOutput {
|
|
|
26655
26708
|
}
|
|
26656
26709
|
};
|
|
26657
26710
|
|
|
26658
|
-
// src/utils/microphone.ts
|
|
26659
|
-
var EXPIRATION_OFFSET = 5 * 60 * 1e3;
|
|
26660
|
-
var defaultElevenLabsOptions = {
|
|
26661
|
-
vadSilenceThresholdSecs: 1.5,
|
|
26662
|
-
noiseSuppression: true,
|
|
26663
|
-
vadThreshold: 0.4,
|
|
26664
|
-
minSpeechDurationMs: 100,
|
|
26665
|
-
minSilenceDurationMs: 100
|
|
26666
|
-
};
|
|
26667
|
-
|
|
26668
26711
|
// src/utils/sync.ts
|
|
26669
26712
|
var DEFAULT_SYNC_CONFIG = {
|
|
26670
26713
|
tolerance: 40,
|
|
@@ -26705,6 +26748,7 @@ var Conversation = class _Conversation {
|
|
|
26705
26748
|
this.status = "connecting";
|
|
26706
26749
|
this.volume = 1;
|
|
26707
26750
|
this.sessionStarted = false;
|
|
26751
|
+
this.isStoppingLastResponse = false;
|
|
26708
26752
|
this.messageCounter = 0;
|
|
26709
26753
|
this.monitor = null;
|
|
26710
26754
|
this.microphone = null;
|
|
@@ -26723,7 +26767,7 @@ var Conversation = class _Conversation {
|
|
|
26723
26767
|
});
|
|
26724
26768
|
if ("suggestions" in event) {
|
|
26725
26769
|
const suggestions = event.suggestions || [];
|
|
26726
|
-
if (suggestions.length >
|
|
26770
|
+
if (suggestions.length > 0) {
|
|
26727
26771
|
this.suggestionsQueue = suggestions;
|
|
26728
26772
|
}
|
|
26729
26773
|
}
|
|
@@ -26733,7 +26777,8 @@ var Conversation = class _Conversation {
|
|
|
26733
26777
|
if (!errorType || ![
|
|
26734
26778
|
"resource_exhausted",
|
|
26735
26779
|
"deadline_exceeded",
|
|
26736
|
-
"inactivity_timeout"
|
|
26780
|
+
"inactivity_timeout",
|
|
26781
|
+
"canceled"
|
|
26737
26782
|
].includes(errorType)) {
|
|
26738
26783
|
this.options.onError({
|
|
26739
26784
|
message: "A connection error occurred. Please try again.",
|
|
@@ -26742,21 +26787,12 @@ var Conversation = class _Conversation {
|
|
|
26742
26787
|
});
|
|
26743
26788
|
return;
|
|
26744
26789
|
}
|
|
26790
|
+
if (errorType === "canceled") {
|
|
26791
|
+
return;
|
|
26792
|
+
}
|
|
26745
26793
|
if (errorType === "resource_exhausted") {
|
|
26746
|
-
|
|
26747
|
-
|
|
26748
|
-
message: "We are experiencing heavy traffic and we can't deliver the response, try again",
|
|
26749
|
-
endConversation: false,
|
|
26750
|
-
type: "toast"
|
|
26751
|
-
});
|
|
26752
|
-
} else {
|
|
26753
|
-
this.options.onError({
|
|
26754
|
-
message: "The system is experiencing heavy traffic. Please try again later.",
|
|
26755
|
-
endConversation: true,
|
|
26756
|
-
type: "toast"
|
|
26757
|
-
});
|
|
26758
|
-
return;
|
|
26759
|
-
}
|
|
26794
|
+
this.options.onHighDemand();
|
|
26795
|
+
return;
|
|
26760
26796
|
} else if (errorType === "deadline_exceeded") {
|
|
26761
26797
|
this.options.onError({
|
|
26762
26798
|
message: "We are experiencing heavy traffic and we can't deliver the response, try again",
|
|
@@ -26817,6 +26853,15 @@ var Conversation = class _Conversation {
|
|
|
26817
26853
|
if (this.avController.isStoppingAV) return;
|
|
26818
26854
|
this.handleVideoFrame(event);
|
|
26819
26855
|
}
|
|
26856
|
+
if (event.type === "stop") {
|
|
26857
|
+
this.videoOutput.clearFrame();
|
|
26858
|
+
this.audioOutput.worklet.port.postMessage({
|
|
26859
|
+
type: "stopPlayback"
|
|
26860
|
+
});
|
|
26861
|
+
this.options.onStoppingEnd();
|
|
26862
|
+
this.isStoppingLastResponse = false;
|
|
26863
|
+
return;
|
|
26864
|
+
}
|
|
26820
26865
|
this.avController.playAudioVideo();
|
|
26821
26866
|
};
|
|
26822
26867
|
this.handleVideoFrame = async (event) => {
|
|
@@ -26942,7 +26987,7 @@ var Conversation = class _Conversation {
|
|
|
26942
26987
|
this.options.onConnect({
|
|
26943
26988
|
userId: connection.userId,
|
|
26944
26989
|
headInfo: {
|
|
26945
|
-
name: this.headInfo.
|
|
26990
|
+
name: this.headInfo.alias,
|
|
26946
26991
|
phrases: this.headInfo.phrases,
|
|
26947
26992
|
language: this.headInfo.language,
|
|
26948
26993
|
avatar: this.headInfo.avatarSrc
|
|
@@ -26971,6 +27016,8 @@ var Conversation = class _Conversation {
|
|
|
26971
27016
|
onMicrophoneStatusChange: () => {
|
|
26972
27017
|
},
|
|
26973
27018
|
onMicrophoneSpeechRecognitionResult: () => {
|
|
27019
|
+
},
|
|
27020
|
+
onMicrophonePartialSpeechRecognitionResult: () => {
|
|
26974
27021
|
}
|
|
26975
27022
|
},
|
|
26976
27023
|
elevenLabsOptions: defaultElevenLabsOptions,
|
|
@@ -26992,6 +27039,8 @@ var Conversation = class _Conversation {
|
|
|
26992
27039
|
},
|
|
26993
27040
|
onStoppingEnd: () => {
|
|
26994
27041
|
},
|
|
27042
|
+
onStoppingStart: () => {
|
|
27043
|
+
},
|
|
26995
27044
|
onTimeout: () => {
|
|
26996
27045
|
},
|
|
26997
27046
|
onTimeoutWarning: () => {
|
|
@@ -27000,6 +27049,8 @@ var Conversation = class _Conversation {
|
|
|
27000
27049
|
},
|
|
27001
27050
|
onError: () => {
|
|
27002
27051
|
},
|
|
27052
|
+
onHighDemand: () => {
|
|
27053
|
+
},
|
|
27003
27054
|
...partialOptions
|
|
27004
27055
|
};
|
|
27005
27056
|
}
|
|
@@ -27163,23 +27214,47 @@ var Conversation = class _Conversation {
|
|
|
27163
27214
|
}
|
|
27164
27215
|
}
|
|
27165
27216
|
/**
|
|
27166
|
-
* To stop
|
|
27167
|
-
*
|
|
27168
|
-
*
|
|
27169
|
-
* 3. clear audio queue
|
|
27170
|
-
* 4. send an event if all expected response from BE has been received. If not, FE will keep status in 'stopping' mode
|
|
27217
|
+
* To stop streaming response, we'll send a stop message to the BE. The BE will then stop sending audio and video frames, which will naturally end the response. This is more efficient and leads to a better user experience as it allows for a smoother transition when stopping the response.
|
|
27218
|
+
*
|
|
27219
|
+
* To stop cached response, we just stop the video and fade to idle.
|
|
27171
27220
|
*/
|
|
27172
|
-
|
|
27173
|
-
|
|
27174
|
-
|
|
27175
|
-
|
|
27176
|
-
|
|
27177
|
-
|
|
27178
|
-
|
|
27179
|
-
|
|
27180
|
-
|
|
27181
|
-
|
|
27182
|
-
|
|
27221
|
+
async stopResponse() {
|
|
27222
|
+
if (this.isStoppingLastResponse) {
|
|
27223
|
+
return;
|
|
27224
|
+
}
|
|
27225
|
+
this.isStoppingLastResponse = true;
|
|
27226
|
+
this.options.onStoppingStart();
|
|
27227
|
+
if (!this.connection) {
|
|
27228
|
+
this.isStoppingLastResponse = false;
|
|
27229
|
+
this.options.onStoppingEnd();
|
|
27230
|
+
throw new Error("Connection not established");
|
|
27231
|
+
}
|
|
27232
|
+
if (this.videoOutput.isPlayingCachedVideo()) {
|
|
27233
|
+
await this.videoOutput.stopCachedVideo();
|
|
27234
|
+
this.isStoppingLastResponse = false;
|
|
27235
|
+
this.options.onStoppingEnd();
|
|
27236
|
+
return;
|
|
27237
|
+
}
|
|
27238
|
+
if (!this.avController.isPlaying) {
|
|
27239
|
+
this.isStoppingLastResponse = false;
|
|
27240
|
+
this.options.onStoppingEnd();
|
|
27241
|
+
return;
|
|
27242
|
+
}
|
|
27243
|
+
const sessionId = `${this.user.id}::${this.user.orgId}::${this.user.headId}::${this.user.sessionId.toString().padStart(5, "0")}`;
|
|
27244
|
+
const message = {
|
|
27245
|
+
id: this.messageCounter,
|
|
27246
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27247
|
+
speaker: "user",
|
|
27248
|
+
text: "",
|
|
27249
|
+
isSent: false,
|
|
27250
|
+
user_id: this.user.id,
|
|
27251
|
+
username: this.user.username,
|
|
27252
|
+
event: "stop" /* STOP */,
|
|
27253
|
+
visible: true,
|
|
27254
|
+
session_id: sessionId
|
|
27255
|
+
};
|
|
27256
|
+
this.connection.sendMessage(message);
|
|
27257
|
+
}
|
|
27183
27258
|
async toggleMute() {
|
|
27184
27259
|
this.volume = this.volume === 0 ? 1 : 0;
|
|
27185
27260
|
this.audioOutput.toggleMute();
|
|
@@ -27188,7 +27263,7 @@ var Conversation = class _Conversation {
|
|
|
27188
27263
|
return this.volume;
|
|
27189
27264
|
}
|
|
27190
27265
|
async startSession() {
|
|
27191
|
-
var _a;
|
|
27266
|
+
var _a, _b;
|
|
27192
27267
|
this.sessionStarted = true;
|
|
27193
27268
|
if (this.audioOutput.context.state === "suspended") {
|
|
27194
27269
|
await this.audioOutput.context.resume();
|
|
@@ -27208,13 +27283,13 @@ var Conversation = class _Conversation {
|
|
|
27208
27283
|
this.user,
|
|
27209
27284
|
this.headInfo,
|
|
27210
27285
|
this.microphoneAccess,
|
|
27211
|
-
this.
|
|
27286
|
+
(_b = this.options.voiceInterruptions) != null ? _b : false
|
|
27212
27287
|
);
|
|
27213
27288
|
}
|
|
27214
27289
|
return this.connection;
|
|
27215
27290
|
}
|
|
27216
27291
|
async toggleMicrophone() {
|
|
27217
|
-
var _a;
|
|
27292
|
+
var _a, _b;
|
|
27218
27293
|
if (this.options.microphoneProvider === "custom") {
|
|
27219
27294
|
throw new Error("Cannot toggle microphone for custom provider.");
|
|
27220
27295
|
}
|
|
@@ -27226,7 +27301,7 @@ var Conversation = class _Conversation {
|
|
|
27226
27301
|
this.user,
|
|
27227
27302
|
this.headInfo,
|
|
27228
27303
|
this.microphoneAccess,
|
|
27229
|
-
this.
|
|
27304
|
+
(_b = this.options.voiceInterruptions) != null ? _b : false
|
|
27230
27305
|
);
|
|
27231
27306
|
}
|
|
27232
27307
|
if (!this.microphoneAccess && this.microphone.status() === "OFF") {
|
|
@@ -27284,6 +27359,7 @@ export {
|
|
|
27284
27359
|
EventType,
|
|
27285
27360
|
StreamingEventType,
|
|
27286
27361
|
VideoTransitionType,
|
|
27362
|
+
defaultElevenLabsOptions,
|
|
27287
27363
|
isBinaryEvent,
|
|
27288
27364
|
isConversationEndEvent,
|
|
27289
27365
|
isJoinEvent,
|