@estuary-ai/sdk 0.1.27 → 0.1.29
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/index.js +34 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +34 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -27041,9 +27041,9 @@ var init_livekit_voice = __esm({
|
|
|
27041
27041
|
_isActive = false;
|
|
27042
27042
|
speakingStateCallback = null;
|
|
27043
27043
|
audioLevelCallback = null;
|
|
27044
|
-
// Audio
|
|
27045
|
-
|
|
27046
|
-
|
|
27044
|
+
// Audio level polling (via LiveKit's server-pushed participant.audioLevel)
|
|
27045
|
+
botParticipant = null;
|
|
27046
|
+
smoothedAudioLevel = 0;
|
|
27047
27047
|
audioLevelPollTimer = null;
|
|
27048
27048
|
_isBotSpeaking = false;
|
|
27049
27049
|
constructor(socketManager, logger) {
|
|
@@ -27101,15 +27101,17 @@ var init_livekit_voice = __esm({
|
|
|
27101
27101
|
}
|
|
27102
27102
|
audioElement.play().catch(() => {
|
|
27103
27103
|
});
|
|
27104
|
-
this.
|
|
27104
|
+
this.botParticipant = participant;
|
|
27105
27105
|
if (this._isBotSpeaking) {
|
|
27106
|
-
|
|
27106
|
+
this.startAudioLevelPolling();
|
|
27107
27107
|
}
|
|
27108
27108
|
}
|
|
27109
27109
|
});
|
|
27110
27110
|
this.room.on(RoomEvent2.TrackUnsubscribed, (track) => {
|
|
27111
27111
|
if (track.kind === Track2.Kind.Audio) {
|
|
27112
|
-
this.
|
|
27112
|
+
this.stopAudioLevelPolling();
|
|
27113
|
+
this.botParticipant = null;
|
|
27114
|
+
this.smoothedAudioLevel = 0;
|
|
27113
27115
|
track.detach().forEach((el) => el.remove());
|
|
27114
27116
|
}
|
|
27115
27117
|
});
|
|
@@ -27117,7 +27119,9 @@ var init_livekit_voice = __esm({
|
|
|
27117
27119
|
this.logger.debug("LiveKit room disconnected");
|
|
27118
27120
|
this._isActive = false;
|
|
27119
27121
|
this._isBotSpeaking = false;
|
|
27120
|
-
this.
|
|
27122
|
+
this.stopAudioLevelPolling();
|
|
27123
|
+
this.botParticipant = null;
|
|
27124
|
+
this.smoothedAudioLevel = 0;
|
|
27121
27125
|
this.speakingStateCallback?.(false);
|
|
27122
27126
|
});
|
|
27123
27127
|
try {
|
|
@@ -27173,7 +27177,9 @@ var init_livekit_voice = __esm({
|
|
|
27173
27177
|
} catch {
|
|
27174
27178
|
}
|
|
27175
27179
|
this._isBotSpeaking = false;
|
|
27176
|
-
this.
|
|
27180
|
+
this.stopAudioLevelPolling();
|
|
27181
|
+
this.botParticipant = null;
|
|
27182
|
+
this.smoothedAudioLevel = 0;
|
|
27177
27183
|
this.speakingStateCallback?.(false);
|
|
27178
27184
|
if (this.room) {
|
|
27179
27185
|
for (const [, publication] of this.room.localParticipant.trackPublications) {
|
|
@@ -27198,7 +27204,9 @@ var init_livekit_voice = __esm({
|
|
|
27198
27204
|
this.speakingStateCallback = null;
|
|
27199
27205
|
this.audioLevelCallback = null;
|
|
27200
27206
|
this._isBotSpeaking = false;
|
|
27201
|
-
this.
|
|
27207
|
+
this.stopAudioLevelPolling();
|
|
27208
|
+
this.botParticipant = null;
|
|
27209
|
+
this.smoothedAudioLevel = 0;
|
|
27202
27210
|
if (this.room) {
|
|
27203
27211
|
this.room.disconnect();
|
|
27204
27212
|
this.room = null;
|
|
@@ -27206,44 +27214,19 @@ var init_livekit_voice = __esm({
|
|
|
27206
27214
|
this._isActive = false;
|
|
27207
27215
|
this._isMuted = false;
|
|
27208
27216
|
}
|
|
27209
|
-
// ─── Audio
|
|
27210
|
-
async setupAnalyser(track) {
|
|
27211
|
-
this.teardownAnalyser();
|
|
27212
|
-
try {
|
|
27213
|
-
const { createAudioAnalyser: createAudioAnalyser2 } = await Promise.resolve().then(() => (init_livekit_client_esm(), livekit_client_esm_exports));
|
|
27214
|
-
const { analyser, calculateVolume, cleanup } = createAudioAnalyser2(track, {
|
|
27215
|
-
fftSize: 256,
|
|
27216
|
-
smoothingTimeConstant: 0.3
|
|
27217
|
-
});
|
|
27218
|
-
if (analyser.context.state === "suspended") {
|
|
27219
|
-
await analyser.context.resume();
|
|
27220
|
-
}
|
|
27221
|
-
this.calculateVolume = calculateVolume;
|
|
27222
|
-
this.analyserCleanup = cleanup;
|
|
27223
|
-
this.logger.debug("Audio analyser created for bot track");
|
|
27224
|
-
} catch (err) {
|
|
27225
|
-
this.logger.debug("Failed to create audio analyser:", err);
|
|
27226
|
-
}
|
|
27227
|
-
}
|
|
27228
|
-
teardownAnalyser() {
|
|
27229
|
-
this.stopAudioLevelPolling();
|
|
27230
|
-
if (this.analyserCleanup) {
|
|
27231
|
-
this.analyserCleanup().catch(() => {
|
|
27232
|
-
});
|
|
27233
|
-
this.analyserCleanup = null;
|
|
27234
|
-
}
|
|
27235
|
-
this.calculateVolume = null;
|
|
27236
|
-
}
|
|
27217
|
+
// ─── Audio Level Polling (participant.audioLevel) ───────────────
|
|
27237
27218
|
startAudioLevelPolling() {
|
|
27238
27219
|
if (this.audioLevelPollTimer !== null) return;
|
|
27239
|
-
if (!this.
|
|
27220
|
+
if (!this.botParticipant) return;
|
|
27221
|
+
const alpha = 0.35;
|
|
27240
27222
|
this.audioLevelPollTimer = setInterval(() => {
|
|
27241
|
-
if (!this.
|
|
27223
|
+
if (!this.botParticipant) {
|
|
27242
27224
|
this.stopAudioLevelPolling();
|
|
27243
27225
|
return;
|
|
27244
27226
|
}
|
|
27245
|
-
const
|
|
27246
|
-
this.
|
|
27227
|
+
const raw = this.botParticipant.audioLevel ?? 0;
|
|
27228
|
+
this.smoothedAudioLevel += alpha * (raw - this.smoothedAudioLevel);
|
|
27229
|
+
this.audioLevelCallback?.(this.smoothedAudioLevel);
|
|
27247
27230
|
}, 33);
|
|
27248
27231
|
}
|
|
27249
27232
|
stopAudioLevelPolling() {
|
|
@@ -27251,6 +27234,7 @@ var init_livekit_voice = __esm({
|
|
|
27251
27234
|
clearInterval(this.audioLevelPollTimer);
|
|
27252
27235
|
this.audioLevelPollTimer = null;
|
|
27253
27236
|
}
|
|
27237
|
+
this.smoothedAudioLevel = 0;
|
|
27254
27238
|
}
|
|
27255
27239
|
// ─── Private ────────────────────────────────────────────────────
|
|
27256
27240
|
requestToken() {
|
|
@@ -31023,24 +31007,24 @@ async function isLiveKitAvailable() {
|
|
|
31023
31007
|
async function createVoiceManager(transport, socketManager, sampleRate, logger) {
|
|
31024
31008
|
if (transport === "websocket") {
|
|
31025
31009
|
const { WebSocketVoiceManager: WebSocketVoiceManager2 } = await Promise.resolve().then(() => (init_websocket_voice(), websocket_voice_exports));
|
|
31026
|
-
return new WebSocketVoiceManager2(socketManager, sampleRate, logger);
|
|
31010
|
+
return { manager: new WebSocketVoiceManager2(socketManager, sampleRate, logger), resolvedTransport: "websocket" };
|
|
31027
31011
|
}
|
|
31028
31012
|
if (transport === "livekit") {
|
|
31029
31013
|
if (await isLiveKitAvailable()) {
|
|
31030
31014
|
const { LiveKitVoiceManager: LiveKitVoiceManager2 } = await Promise.resolve().then(() => (init_livekit_voice(), livekit_voice_exports));
|
|
31031
|
-
return new LiveKitVoiceManager2(socketManager, logger);
|
|
31015
|
+
return { manager: new LiveKitVoiceManager2(socketManager, logger), resolvedTransport: "livekit" };
|
|
31032
31016
|
}
|
|
31033
31017
|
logger.warn("livekit-client not installed, falling back to WebSocket voice");
|
|
31034
31018
|
const { WebSocketVoiceManager: WebSocketVoiceManager2 } = await Promise.resolve().then(() => (init_websocket_voice(), websocket_voice_exports));
|
|
31035
|
-
return new WebSocketVoiceManager2(socketManager, sampleRate, logger);
|
|
31019
|
+
return { manager: new WebSocketVoiceManager2(socketManager, sampleRate, logger), resolvedTransport: "websocket" };
|
|
31036
31020
|
}
|
|
31037
31021
|
if (transport === "auto") {
|
|
31038
31022
|
if (await isLiveKitAvailable()) {
|
|
31039
31023
|
const { LiveKitVoiceManager: LiveKitVoiceManager2 } = await Promise.resolve().then(() => (init_livekit_voice(), livekit_voice_exports));
|
|
31040
|
-
return new LiveKitVoiceManager2(socketManager, logger);
|
|
31024
|
+
return { manager: new LiveKitVoiceManager2(socketManager, logger), resolvedTransport: "livekit" };
|
|
31041
31025
|
}
|
|
31042
31026
|
const { WebSocketVoiceManager: WebSocketVoiceManager2 } = await Promise.resolve().then(() => (init_websocket_voice(), websocket_voice_exports));
|
|
31043
|
-
return new WebSocketVoiceManager2(socketManager, sampleRate, logger);
|
|
31027
|
+
return { manager: new WebSocketVoiceManager2(socketManager, sampleRate, logger), resolvedTransport: "websocket" };
|
|
31044
31028
|
}
|
|
31045
31029
|
return null;
|
|
31046
31030
|
}
|
|
@@ -31528,11 +31512,12 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
31528
31512
|
}
|
|
31529
31513
|
const transport = this.config.voiceTransport ?? "auto";
|
|
31530
31514
|
const sampleRate = this.config.audioSampleRate ?? DEFAULT_SAMPLE_RATE;
|
|
31531
|
-
|
|
31532
|
-
if (!
|
|
31515
|
+
const result = await createVoiceManager(transport, this.socketManager, sampleRate, this.logger);
|
|
31516
|
+
if (!result) {
|
|
31533
31517
|
throw new EstuaryError("VOICE_NOT_SUPPORTED" /* VOICE_NOT_SUPPORTED */, "No voice transport available");
|
|
31534
31518
|
}
|
|
31535
|
-
|
|
31519
|
+
this.voiceManager = result.manager;
|
|
31520
|
+
if (!this.audioPlayer && result.resolvedTransport === "websocket" && typeof AudioContext !== "undefined") {
|
|
31536
31521
|
this.audioPlayer = new AudioPlayer(sampleRate, (event) => {
|
|
31537
31522
|
if (event.type === "started") {
|
|
31538
31523
|
this._hasAutoInterrupted = true;
|