@elevenlabs/client 1.1.2 → 1.2.1
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/dist/BaseConversation.d.ts +16 -2
- package/dist/BaseConversation.d.ts.map +1 -1
- package/dist/BaseConversation.js +2 -3
- package/dist/BaseConversation.js.map +1 -1
- package/dist/InputController.d.ts +13 -0
- package/dist/InputController.d.ts.map +1 -1
- package/dist/OutputController.d.ts +13 -0
- package/dist/OutputController.d.ts.map +1 -1
- package/dist/TextConversation.d.ts.map +1 -1
- package/dist/TextConversation.js +12 -4
- package/dist/TextConversation.js.map +1 -1
- package/dist/VoiceConversation.d.ts +3 -3
- package/dist/VoiceConversation.d.ts.map +1 -1
- package/dist/VoiceConversation.js +21 -42
- package/dist/VoiceConversation.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/lib.iife.js +179 -43
- package/dist/lib.iife.js.map +1 -1
- package/dist/utils/WebRTCConnection.d.ts +14 -2
- package/dist/utils/WebRTCConnection.d.ts.map +1 -1
- package/dist/utils/WebRTCConnection.js +83 -10
- package/dist/utils/WebRTCConnection.js.map +1 -1
- package/dist/utils/calculateVolume.d.ts +7 -0
- package/dist/utils/calculateVolume.d.ts.map +1 -0
- package/dist/utils/calculateVolume.js +17 -0
- package/dist/utils/calculateVolume.js.map +1 -0
- package/dist/utils/input.d.ts +3 -0
- package/dist/utils/input.d.ts.map +1 -1
- package/dist/utils/input.js +15 -0
- package/dist/utils/input.js.map +1 -1
- package/dist/utils/output.d.ts +3 -0
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +9 -0
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/volumeProvider.d.ts +21 -0
- package/dist/utils/volumeProvider.d.ts.map +1 -0
- package/dist/utils/volumeProvider.js +51 -0
- package/dist/utils/volumeProvider.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/lib.iife.js
CHANGED
|
@@ -46,10 +46,11 @@ var ElevenLabsClient = (function(exports) {
|
|
|
46
46
|
constructor(options, connection) {
|
|
47
47
|
this.options = options;
|
|
48
48
|
this.connection = connection;
|
|
49
|
-
if (this.options.onConnect) this.options.onConnect({ conversationId: connection.conversationId });
|
|
50
49
|
this.connection.onMessage(this.onMessage);
|
|
51
50
|
this.connection.onDisconnect(this.endSessionWithDetails);
|
|
52
51
|
this.connection.onModeChange((mode) => this.updateMode(mode));
|
|
52
|
+
}
|
|
53
|
+
markConnected() {
|
|
53
54
|
this.updateStatus("connected");
|
|
54
55
|
}
|
|
55
56
|
endSession() {
|
|
@@ -383,7 +384,7 @@ var ElevenLabsClient = (function(exports) {
|
|
|
383
384
|
//#region src/sourceInfo.ts
|
|
384
385
|
let sourceInfo = Object.freeze({
|
|
385
386
|
name: "js_sdk",
|
|
386
|
-
version: "1.1
|
|
387
|
+
version: "1.2.1"
|
|
387
388
|
});
|
|
388
389
|
//#endregion
|
|
389
390
|
//#region src/utils/events.ts
|
|
@@ -21929,6 +21930,66 @@ class RawAudioProcessor extends AudioWorkletProcessor {
|
|
|
21929
21930
|
}
|
|
21930
21931
|
registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
21931
21932
|
`);
|
|
21933
|
+
//#endregion
|
|
21934
|
+
//#region src/utils/calculateVolume.ts
|
|
21935
|
+
/**
|
|
21936
|
+
* Calculate a scalar volume level (0–1) from byte frequency data.
|
|
21937
|
+
*
|
|
21938
|
+
* The value is the mean of all frequency bins normalised to [0, 1].
|
|
21939
|
+
*/
|
|
21940
|
+
function calculateVolume(frequencyData) {
|
|
21941
|
+
if (frequencyData.length === 0) return 0;
|
|
21942
|
+
let volume = 0;
|
|
21943
|
+
for (let i = 0; i < frequencyData.length; i++) volume += frequencyData[i] / 255;
|
|
21944
|
+
volume /= frequencyData.length;
|
|
21945
|
+
return volume < 0 ? 0 : volume > 1 ? 1 : volume;
|
|
21946
|
+
}
|
|
21947
|
+
//#endregion
|
|
21948
|
+
//#region src/utils/volumeProvider.ts
|
|
21949
|
+
const NO_VOLUME = {
|
|
21950
|
+
getVolume: () => 0,
|
|
21951
|
+
getByteFrequencyData: () => {}
|
|
21952
|
+
};
|
|
21953
|
+
const MAX_VOICE_FREQUENCY = 8e3;
|
|
21954
|
+
/**
|
|
21955
|
+
* Resamples the voice-relevant portion of raw frequency data into an output
|
|
21956
|
+
* buffer using linear interpolation. This ensures both web and React Native
|
|
21957
|
+
* return comparable frequency data focused on the human voice range.
|
|
21958
|
+
*/
|
|
21959
|
+
function resampleVoiceRange(raw, buffer, sampleRate) {
|
|
21960
|
+
const binCount = raw.length;
|
|
21961
|
+
const hzPerBin = sampleRate / 2 / binCount;
|
|
21962
|
+
const minBin = Math.floor(100 / hzPerBin);
|
|
21963
|
+
const maxBin = Math.min(Math.ceil(MAX_VOICE_FREQUENCY / hzPerBin), binCount);
|
|
21964
|
+
const voiceBinCount = maxBin - minBin;
|
|
21965
|
+
const outLen = buffer.length;
|
|
21966
|
+
for (let i = 0; i < outLen; i++) {
|
|
21967
|
+
const pos = i / outLen * voiceBinCount;
|
|
21968
|
+
const lo = minBin + Math.floor(pos);
|
|
21969
|
+
const hi = Math.min(lo + 1, maxBin - 1);
|
|
21970
|
+
const t = pos - Math.floor(pos);
|
|
21971
|
+
buffer[i] = Math.round(raw[lo] * (1 - t) + raw[hi] * t);
|
|
21972
|
+
}
|
|
21973
|
+
}
|
|
21974
|
+
function createAnalyserVolumeProvider(analyser, sampleRate) {
|
|
21975
|
+
const binCount = analyser.frequencyBinCount;
|
|
21976
|
+
let rawData;
|
|
21977
|
+
let voiceData;
|
|
21978
|
+
return {
|
|
21979
|
+
getVolume() {
|
|
21980
|
+
rawData ??= new Uint8Array(binCount);
|
|
21981
|
+
voiceData ??= new Uint8Array(binCount);
|
|
21982
|
+
analyser.getByteFrequencyData(rawData);
|
|
21983
|
+
resampleVoiceRange(rawData, voiceData, sampleRate);
|
|
21984
|
+
return calculateVolume(voiceData);
|
|
21985
|
+
},
|
|
21986
|
+
getByteFrequencyData(buffer) {
|
|
21987
|
+
rawData ??= new Uint8Array(binCount);
|
|
21988
|
+
analyser.getByteFrequencyData(rawData);
|
|
21989
|
+
resampleVoiceRange(rawData, buffer, sampleRate);
|
|
21990
|
+
}
|
|
21991
|
+
};
|
|
21992
|
+
}
|
|
21932
21993
|
//#endregion
|
|
21933
21994
|
//#region src/utils/WebRTCConnection.ts
|
|
21934
21995
|
const DEFAULT_LIVEKIT_WS_URL = "wss://livekit.rtc.elevenlabs.io";
|
|
@@ -21946,8 +22007,11 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
21946
22007
|
audioCaptureContext = null;
|
|
21947
22008
|
audioElements = [];
|
|
21948
22009
|
outputDeviceId = null;
|
|
22010
|
+
inputAnalyser = null;
|
|
22011
|
+
inputAudioContext = null;
|
|
22012
|
+
inputVolumeProvider = NO_VOLUME;
|
|
21949
22013
|
outputAnalyser = null;
|
|
21950
|
-
|
|
22014
|
+
outputVolumeProvider = NO_VOLUME;
|
|
21951
22015
|
_isMuted = false;
|
|
21952
22016
|
input = {
|
|
21953
22017
|
close: async () => {
|
|
@@ -21970,6 +22034,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
21970
22034
|
console.warn("Cannot set microphone muted: room not connected or no local participant");
|
|
21971
22035
|
return;
|
|
21972
22036
|
}
|
|
22037
|
+
this._isMuted = isMuted;
|
|
21973
22038
|
const micTrackPublication = this.room.localParticipant.getTrackPublication(Track.Source.Microphone);
|
|
21974
22039
|
if (micTrackPublication?.track) try {
|
|
21975
22040
|
if (isMuted) await micTrackPublication.track.mute();
|
|
@@ -21978,10 +22043,24 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
21978
22043
|
await this.room.localParticipant.setMicrophoneEnabled(!isMuted);
|
|
21979
22044
|
}
|
|
21980
22045
|
else await this.room.localParticipant.setMicrophoneEnabled(!isMuted);
|
|
21981
|
-
|
|
22046
|
+
if (!isMuted) {
|
|
22047
|
+
const track = this.room.localParticipant.getTrackPublication(Track.Source.Microphone)?.track;
|
|
22048
|
+
if (track) this.setupInputAnalyser(track.mediaStreamTrack);
|
|
22049
|
+
}
|
|
21982
22050
|
},
|
|
21983
22051
|
isMuted: () => this._isMuted,
|
|
21984
|
-
getAnalyser: () => void 0
|
|
22052
|
+
getAnalyser: () => this.inputAnalyser ?? void 0,
|
|
22053
|
+
getVolume: () => {
|
|
22054
|
+
if (this._isMuted) return 0;
|
|
22055
|
+
return this.inputVolumeProvider.getVolume();
|
|
22056
|
+
},
|
|
22057
|
+
getByteFrequencyData: (buffer) => {
|
|
22058
|
+
if (this._isMuted) {
|
|
22059
|
+
buffer.fill(0);
|
|
22060
|
+
return;
|
|
22061
|
+
}
|
|
22062
|
+
this.inputVolumeProvider.getByteFrequencyData(buffer);
|
|
22063
|
+
}
|
|
21985
22064
|
};
|
|
21986
22065
|
output = {
|
|
21987
22066
|
close: async () => {},
|
|
@@ -21995,7 +22074,11 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
21995
22074
|
this.setAudioVolume(volume);
|
|
21996
22075
|
},
|
|
21997
22076
|
interrupt: (_resetDuration) => {},
|
|
21998
|
-
getAnalyser: () => this.outputAnalyser ?? void 0
|
|
22077
|
+
getAnalyser: () => this.outputAnalyser ?? void 0,
|
|
22078
|
+
getVolume: () => this.outputVolumeProvider.getVolume(),
|
|
22079
|
+
getByteFrequencyData: (buffer) => {
|
|
22080
|
+
this.outputVolumeProvider.getByteFrequencyData(buffer);
|
|
22081
|
+
}
|
|
21999
22082
|
};
|
|
22000
22083
|
constructor(room, conversationId, inputFormat, outputFormat, config = {}) {
|
|
22001
22084
|
super(config);
|
|
@@ -22043,6 +22126,8 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22043
22126
|
}
|
|
22044
22127
|
});
|
|
22045
22128
|
await micEnabled;
|
|
22129
|
+
const micTrack = room.localParticipant.getTrackPublication(Track.Source.Microphone)?.track;
|
|
22130
|
+
if (micTrack) connection.setupInputAnalyser(micTrack.mediaStreamTrack);
|
|
22046
22131
|
if (room.name) connection.conversationId = room.name.match(/(conv_[a-zA-Z0-9]+)/)?.[0] || room.name;
|
|
22047
22132
|
const overridesEvent = constructOverrides(config);
|
|
22048
22133
|
connection.debug({
|
|
@@ -22126,6 +22211,13 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22126
22211
|
} catch (error) {
|
|
22127
22212
|
console.warn("Error stopping local tracks:", error);
|
|
22128
22213
|
}
|
|
22214
|
+
if (this.inputAudioContext) {
|
|
22215
|
+
this.inputAudioContext.close().catch((error) => {
|
|
22216
|
+
console.warn("Error closing input audio context:", error);
|
|
22217
|
+
});
|
|
22218
|
+
this.inputAudioContext = null;
|
|
22219
|
+
this.inputAnalyser = null;
|
|
22220
|
+
}
|
|
22129
22221
|
if (this.audioCaptureContext) {
|
|
22130
22222
|
this.audioCaptureContext.close().catch((error) => {
|
|
22131
22223
|
console.warn("Error closing audio capture context:", error);
|
|
@@ -22162,6 +22254,35 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22162
22254
|
getRoom() {
|
|
22163
22255
|
return this.room;
|
|
22164
22256
|
}
|
|
22257
|
+
/**
|
|
22258
|
+
* (Re-)creates an AudioContext + AnalyserNode from the given track and
|
|
22259
|
+
* installs the corresponding VolumeProvider. Called once during create()
|
|
22260
|
+
* and again after an input device switch so the analyser follows the
|
|
22261
|
+
* active mic track.
|
|
22262
|
+
*/
|
|
22263
|
+
setupInputAnalyser(mediaStreamTrack) {
|
|
22264
|
+
if (this.inputAudioContext) {
|
|
22265
|
+
this.inputAudioContext.close().catch(() => {});
|
|
22266
|
+
this.inputAudioContext = null;
|
|
22267
|
+
this.inputAnalyser = null;
|
|
22268
|
+
}
|
|
22269
|
+
try {
|
|
22270
|
+
const ctx = new AudioContext();
|
|
22271
|
+
const analyser = ctx.createAnalyser();
|
|
22272
|
+
ctx.createMediaStreamSource(new MediaStream([mediaStreamTrack])).connect(analyser);
|
|
22273
|
+
this.inputAnalyser = analyser;
|
|
22274
|
+
this.inputAudioContext = ctx;
|
|
22275
|
+
this.inputVolumeProvider = createAnalyserVolumeProvider(analyser, ctx.sampleRate);
|
|
22276
|
+
} catch (error) {
|
|
22277
|
+
console.warn("[ConversationalAI] Failed to set up input volume analyser:", error);
|
|
22278
|
+
}
|
|
22279
|
+
}
|
|
22280
|
+
setInputVolumeProvider(provider) {
|
|
22281
|
+
this.inputVolumeProvider = provider;
|
|
22282
|
+
}
|
|
22283
|
+
setOutputVolumeProvider(provider) {
|
|
22284
|
+
this.outputVolumeProvider = provider;
|
|
22285
|
+
}
|
|
22165
22286
|
async setupAudioCapture(track) {
|
|
22166
22287
|
try {
|
|
22167
22288
|
const audioContext = new AudioContext();
|
|
@@ -22172,6 +22293,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22172
22293
|
const mediaStream = new MediaStream([track.mediaStreamTrack]);
|
|
22173
22294
|
const source = audioContext.createMediaStreamSource(mediaStream);
|
|
22174
22295
|
source.connect(this.outputAnalyser);
|
|
22296
|
+
this.setOutputVolumeProvider(createAnalyserVolumeProvider(this.outputAnalyser, audioContext.sampleRate));
|
|
22175
22297
|
await loadRawAudioProcessor(audioContext.audioWorklet);
|
|
22176
22298
|
const worklet = new AudioWorkletNode(audioContext, "rawAudioProcessor");
|
|
22177
22299
|
this.outputAnalyser.connect(worklet);
|
|
@@ -22236,6 +22358,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22236
22358
|
name: "microphone",
|
|
22237
22359
|
source: Track.Source.Microphone
|
|
22238
22360
|
});
|
|
22361
|
+
this.setupInputAnalyser(audioTrack.mediaStreamTrack);
|
|
22239
22362
|
} catch (error) {
|
|
22240
22363
|
console.error("Failed to change input device:", error);
|
|
22241
22364
|
try {
|
|
@@ -22246,12 +22369,6 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22246
22369
|
throw error;
|
|
22247
22370
|
}
|
|
22248
22371
|
}
|
|
22249
|
-
getOutputByteFrequencyData() {
|
|
22250
|
-
if (!this.outputAnalyser) return null;
|
|
22251
|
-
this.outputFrequencyData ??= new Uint8Array(this.outputAnalyser.frequencyBinCount);
|
|
22252
|
-
this.outputAnalyser.getByteFrequencyData(this.outputFrequencyData);
|
|
22253
|
-
return this.outputFrequencyData;
|
|
22254
|
-
}
|
|
22255
22372
|
};
|
|
22256
22373
|
//#endregion
|
|
22257
22374
|
//#region src/utils/ConnectionFactory.ts
|
|
@@ -22299,7 +22416,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22299
22416
|
}
|
|
22300
22417
|
//#endregion
|
|
22301
22418
|
//#region src/TextConversation.ts
|
|
22302
|
-
const EMPTY_FREQUENCY_DATA
|
|
22419
|
+
const EMPTY_FREQUENCY_DATA = new Uint8Array(0);
|
|
22303
22420
|
var TextConversation = class TextConversation extends BaseConversation {
|
|
22304
22421
|
type = "text";
|
|
22305
22422
|
setVolume() {
|
|
@@ -22309,10 +22426,10 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22309
22426
|
throw new Error("setMicMuted is not supported in text conversations");
|
|
22310
22427
|
}
|
|
22311
22428
|
getInputByteFrequencyData() {
|
|
22312
|
-
return EMPTY_FREQUENCY_DATA
|
|
22429
|
+
return EMPTY_FREQUENCY_DATA;
|
|
22313
22430
|
}
|
|
22314
22431
|
getOutputByteFrequencyData() {
|
|
22315
|
-
return EMPTY_FREQUENCY_DATA
|
|
22432
|
+
return EMPTY_FREQUENCY_DATA;
|
|
22316
22433
|
}
|
|
22317
22434
|
getInputVolume() {
|
|
22318
22435
|
return 0;
|
|
@@ -22327,13 +22444,21 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22327
22444
|
if (fullOptions.onModeChange) fullOptions.onModeChange({ mode: "listening" });
|
|
22328
22445
|
if (fullOptions.onCanSendFeedbackChange) fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });
|
|
22329
22446
|
let connection = null;
|
|
22447
|
+
let conversation = null;
|
|
22330
22448
|
try {
|
|
22331
22449
|
await applyDelay(fullOptions.connectionDelay);
|
|
22332
22450
|
connection = await createConnection(fullOptions);
|
|
22333
|
-
|
|
22451
|
+
conversation = new TextConversation(fullOptions, connection);
|
|
22452
|
+
fullOptions.onConversationCreated?.(conversation);
|
|
22453
|
+
conversation.markConnected();
|
|
22454
|
+
fullOptions.onConnect?.({ conversationId: connection.conversationId });
|
|
22455
|
+
return conversation;
|
|
22334
22456
|
} catch (error) {
|
|
22335
|
-
if (
|
|
22336
|
-
|
|
22457
|
+
if (conversation) await conversation.endSession().catch(() => {});
|
|
22458
|
+
else {
|
|
22459
|
+
fullOptions.onStatusChange?.({ status: "disconnected" });
|
|
22460
|
+
connection?.close();
|
|
22461
|
+
}
|
|
22337
22462
|
throw error;
|
|
22338
22463
|
}
|
|
22339
22464
|
}
|
|
@@ -22498,6 +22623,7 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
22498
22623
|
volume = 1;
|
|
22499
22624
|
interrupted = false;
|
|
22500
22625
|
interruptTimeout = null;
|
|
22626
|
+
volumeProvider;
|
|
22501
22627
|
constructor(context, analyser, gain, worklet, audioElement) {
|
|
22502
22628
|
this.context = context;
|
|
22503
22629
|
this.analyser = analyser;
|
|
@@ -22505,10 +22631,17 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
22505
22631
|
this.worklet = worklet;
|
|
22506
22632
|
this.audioElement = audioElement;
|
|
22507
22633
|
this.worklet.port.start();
|
|
22634
|
+
this.volumeProvider = createAnalyserVolumeProvider(analyser, context.sampleRate);
|
|
22508
22635
|
}
|
|
22509
22636
|
getAnalyser() {
|
|
22510
22637
|
return this.analyser;
|
|
22511
22638
|
}
|
|
22639
|
+
getVolume() {
|
|
22640
|
+
return this.volumeProvider.getVolume();
|
|
22641
|
+
}
|
|
22642
|
+
getByteFrequencyData(buffer) {
|
|
22643
|
+
this.volumeProvider.getByteFrequencyData(buffer);
|
|
22644
|
+
}
|
|
22512
22645
|
addListener(listener) {
|
|
22513
22646
|
this.worklet.port.addEventListener("message", listener);
|
|
22514
22647
|
}
|
|
@@ -22617,6 +22750,7 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
22617
22750
|
return isIosDevice() ? { ideal: deviceId } : { exact: deviceId };
|
|
22618
22751
|
}
|
|
22619
22752
|
muted = false;
|
|
22753
|
+
volumeProvider;
|
|
22620
22754
|
constructor(context, analyser, worklet, inputStream, mediaStreamSource, permissions, onError = console.error) {
|
|
22621
22755
|
this.context = context;
|
|
22622
22756
|
this.analyser = analyser;
|
|
@@ -22627,10 +22761,22 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
22627
22761
|
this.onError = onError;
|
|
22628
22762
|
this.permissions.addEventListener("change", this.handlePermissionsChange);
|
|
22629
22763
|
this.worklet.port.start();
|
|
22764
|
+
this.volumeProvider = createAnalyserVolumeProvider(analyser, context.sampleRate);
|
|
22630
22765
|
}
|
|
22631
22766
|
getAnalyser() {
|
|
22632
22767
|
return this.analyser;
|
|
22633
22768
|
}
|
|
22769
|
+
getVolume() {
|
|
22770
|
+
if (this.muted) return 0;
|
|
22771
|
+
return this.volumeProvider.getVolume();
|
|
22772
|
+
}
|
|
22773
|
+
getByteFrequencyData(buffer) {
|
|
22774
|
+
if (this.muted) {
|
|
22775
|
+
buffer.fill(0);
|
|
22776
|
+
return;
|
|
22777
|
+
}
|
|
22778
|
+
this.volumeProvider.getByteFrequencyData(buffer);
|
|
22779
|
+
}
|
|
22634
22780
|
isMuted() {
|
|
22635
22781
|
return this.muted;
|
|
22636
22782
|
}
|
|
@@ -22771,7 +22917,6 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
22771
22917
|
let setupStrategy = webSessionSetup;
|
|
22772
22918
|
//#endregion
|
|
22773
22919
|
//#region src/VoiceConversation.ts
|
|
22774
|
-
const EMPTY_FREQUENCY_DATA = new Uint8Array(0);
|
|
22775
22920
|
var VoiceConversation = class VoiceConversation extends BaseConversation {
|
|
22776
22921
|
type = "voice";
|
|
22777
22922
|
static async requestWakeLock() {
|
|
@@ -22785,6 +22930,7 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
22785
22930
|
if (fullOptions.onStatusChange) fullOptions.onStatusChange({ status: "connecting" });
|
|
22786
22931
|
if (fullOptions.onCanSendFeedbackChange) fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });
|
|
22787
22932
|
let preliminaryInputStream = null;
|
|
22933
|
+
let conversation = null;
|
|
22788
22934
|
const useWakeLock = options.useWakeLock ?? true;
|
|
22789
22935
|
let wakeLock = null;
|
|
22790
22936
|
if (useWakeLock) wakeLock = await VoiceConversation.requestWakeLock();
|
|
@@ -22796,12 +22942,17 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
22796
22942
|
track.stop();
|
|
22797
22943
|
});
|
|
22798
22944
|
preliminaryInputStream = null;
|
|
22799
|
-
|
|
22945
|
+
conversation = new VoiceConversation(fullOptions, sessionSetup.connection, sessionSetup.input, sessionSetup.output, sessionSetup.playbackEventTarget, sessionSetup.detach, wakeLock);
|
|
22946
|
+
fullOptions.onConversationCreated?.(conversation);
|
|
22947
|
+
conversation.markConnected();
|
|
22948
|
+
fullOptions.onConnect?.({ conversationId: sessionSetup.connection.conversationId });
|
|
22949
|
+
return conversation;
|
|
22800
22950
|
} catch (error) {
|
|
22801
|
-
if (fullOptions.onStatusChange) fullOptions.onStatusChange({ status: "disconnected" });
|
|
22802
22951
|
preliminaryInputStream?.getTracks().forEach((track) => {
|
|
22803
22952
|
track.stop();
|
|
22804
22953
|
});
|
|
22954
|
+
if (conversation) await conversation.endSession().catch(() => {});
|
|
22955
|
+
else fullOptions.onStatusChange?.({ status: "disconnected" });
|
|
22805
22956
|
try {
|
|
22806
22957
|
await wakeLock?.release();
|
|
22807
22958
|
wakeLock = null;
|
|
@@ -22860,42 +23011,27 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
22860
23011
|
this.updateMode("speaking");
|
|
22861
23012
|
}
|
|
22862
23013
|
}
|
|
22863
|
-
|
|
22864
|
-
if (frequencyData.length === 0) return 0;
|
|
22865
|
-
let volume = 0;
|
|
22866
|
-
for (let i = 0; i < frequencyData.length; i++) volume += frequencyData[i] / 255;
|
|
22867
|
-
volume /= frequencyData.length;
|
|
22868
|
-
return volume < 0 ? 0 : volume > 1 ? 1 : volume;
|
|
22869
|
-
};
|
|
23014
|
+
static FREQUENCY_BIN_COUNT = 1024;
|
|
22870
23015
|
setMicMuted(isMuted) {
|
|
22871
23016
|
this.input.setMuted(isMuted).catch((error) => {
|
|
22872
23017
|
this.options.onError?.("Failed to set input muted state", error);
|
|
22873
23018
|
});
|
|
22874
23019
|
}
|
|
22875
23020
|
getInputByteFrequencyData() {
|
|
22876
|
-
|
|
22877
|
-
|
|
22878
|
-
this.inputFrequencyData ??= new Uint8Array(analyser.frequencyBinCount);
|
|
22879
|
-
analyser.getByteFrequencyData(this.inputFrequencyData);
|
|
23021
|
+
this.inputFrequencyData ??= new Uint8Array(VoiceConversation.FREQUENCY_BIN_COUNT);
|
|
23022
|
+
this.input.getByteFrequencyData(this.inputFrequencyData);
|
|
22880
23023
|
return this.inputFrequencyData;
|
|
22881
23024
|
}
|
|
22882
23025
|
getOutputByteFrequencyData() {
|
|
22883
|
-
|
|
22884
|
-
|
|
22885
|
-
if (webrtcData) return webrtcData;
|
|
22886
|
-
return new Uint8Array(1024);
|
|
22887
|
-
}
|
|
22888
|
-
const analyser = this.output.getAnalyser();
|
|
22889
|
-
if (!analyser) return EMPTY_FREQUENCY_DATA;
|
|
22890
|
-
this.outputFrequencyData ??= new Uint8Array(analyser.frequencyBinCount);
|
|
22891
|
-
analyser.getByteFrequencyData(this.outputFrequencyData);
|
|
23026
|
+
this.outputFrequencyData ??= new Uint8Array(VoiceConversation.FREQUENCY_BIN_COUNT);
|
|
23027
|
+
this.output.getByteFrequencyData(this.outputFrequencyData);
|
|
22892
23028
|
return this.outputFrequencyData;
|
|
22893
23029
|
}
|
|
22894
23030
|
getInputVolume() {
|
|
22895
|
-
return this.
|
|
23031
|
+
return this.input.getVolume();
|
|
22896
23032
|
}
|
|
22897
23033
|
getOutputVolume() {
|
|
22898
|
-
return this.
|
|
23034
|
+
return this.output.getVolume();
|
|
22899
23035
|
}
|
|
22900
23036
|
async changeInputDevice({ sampleRate, format, preferHeadphonesForIosDevices, inputDeviceId }) {
|
|
22901
23037
|
try {
|