@elevenlabs/client 1.8.0 → 1.9.0
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/InputController.d.ts +7 -0
- package/dist/InputController.d.ts.map +1 -1
- package/dist/InputController.js +2 -1
- package/dist/InputController.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib.iife.js +142 -28
- package/dist/lib.iife.js.map +1 -1
- package/dist/platform/tsconfig.test.tsbuildinfo +1 -1
- package/dist/platform/web/VoiceSessionSetup.d.ts.map +1 -1
- package/dist/platform/web/VoiceSessionSetup.js +15 -2
- package/dist/platform/web/VoiceSessionSetup.js.map +1 -1
- package/dist/platform/web/audioUnlock.d.ts +11 -0
- package/dist/platform/web/audioUnlock.d.ts.map +1 -0
- package/dist/platform/web/audioUnlock.js +74 -0
- package/dist/platform/web/audioUnlock.js.map +1 -0
- package/dist/platform/web/index.d.ts.map +1 -1
- package/dist/platform/web/index.js +6 -0
- package/dist/platform/web/index.js.map +1 -1
- package/dist/platform/web/input.d.ts +2 -2
- package/dist/platform/web/input.d.ts.map +1 -1
- package/dist/platform/web/input.js +12 -5
- package/dist/platform/web/input.js.map +1 -1
- package/dist/platform/web/output.d.ts +3 -1
- package/dist/platform/web/output.d.ts.map +1 -1
- package/dist/platform/web/output.js +29 -3
- package/dist/platform/web/output.js.map +1 -1
- package/dist/platform/web/rawAudioProcessor.generated.d.ts.map +1 -1
- package/dist/platform/web/rawAudioProcessor.generated.js +5 -1
- package/dist/platform/web/rawAudioProcessor.generated.js.map +1 -1
- package/dist/utils/WebSocketConnection.d.ts +1 -0
- package/dist/utils/WebSocketConnection.d.ts.map +1 -1
- package/dist/utils/WebSocketConnection.js +15 -0
- package/dist/utils/WebSocketConnection.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import type { FormatConfig } from "./utils/BaseConnection.js";
|
|
2
|
+
/** Default microphone audio chunk duration sent to the agent (WebSocket path). */
|
|
3
|
+
export declare const DEFAULT_INPUT_CHUNK_DURATION_MS = 25;
|
|
2
4
|
export type InputDeviceConfig = {
|
|
3
5
|
inputDeviceId?: string;
|
|
4
6
|
preferHeadphonesForIosDevices?: boolean;
|
|
5
7
|
};
|
|
6
8
|
export type InputConfig = InputDeviceConfig & {
|
|
7
9
|
onError?(message: string, context?: unknown): void;
|
|
10
|
+
/**
|
|
11
|
+
* Duration of each microphone audio chunk sent to the agent, in milliseconds.
|
|
12
|
+
* Only applies to the WebSocket input path (AudioWorklet). Default: 25.
|
|
13
|
+
*/
|
|
14
|
+
inputChunkDurationMs?: number;
|
|
8
15
|
};
|
|
9
16
|
export type InputMessageEvent = MessageEvent<[Uint8Array, number]>;
|
|
10
17
|
export type InputListener = (event: InputMessageEvent) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputController.d.ts","sourceRoot":"","sources":["../src/InputController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,iBAAiB,GAAG;IAC5C,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"InputController.d.ts","sourceRoot":"","sources":["../src/InputController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,kFAAkF;AAClF,eAAO,MAAM,+BAA+B,KAAK,CAAC;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,iBAAiB,GAAG;IAC5C,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACnD;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,YAAY,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;AACnE,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAE/D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC3C,cAAc,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;CAC/C,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,IAAI,OAAO,CAAC;IAEnB;;;;OAIG;IACH,WAAW,IAAI,YAAY,GAAG,SAAS,CAAC;IAExC,mDAAmD;IACnD,SAAS,IAAI,MAAM,CAAC;IACpB;;;;OAIG;IACH,oBAAoB,CAAC,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;CAC7D"}
|
package/dist/InputController.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputController.js","sourceRoot":"","sources":["../src/InputController.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"InputController.js","sourceRoot":"","sources":["../src/InputController.ts"],"names":[],"mappings":"AAEA,kFAAkF;AAClF,MAAM,CAAC,MAAM,+BAA+B,GAAG,EAAE,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { TextConversation } from "./TextConversation.js";
|
|
|
3
3
|
import { VoiceConversation } from "./VoiceConversation.js";
|
|
4
4
|
export type { Mode, Role, Options, PartialOptions, ClientToolsConfig, Callbacks, Status, AudioWorkletConfig, MultimodalMessageInput, UploadFileResult, ConversationCreatedCallback, ConversationLifecycleOptions, ContextualUpdateOptions, } from "./BaseConversation.js";
|
|
5
5
|
export type { InputController, InputDeviceConfig, InputConfig, } from "./InputController.js";
|
|
6
|
+
export { DEFAULT_INPUT_CHUNK_DURATION_MS } from "./InputController.js";
|
|
6
7
|
export type { OutputController, OutputDeviceConfig, OutputConfig, } from "./OutputController.js";
|
|
7
8
|
export type { IncomingSocketEvent, VadScoreEvent, AudioAlignmentEvent, } from "./utils/events.js";
|
|
8
9
|
export type { SessionConfig, BaseSessionConfig, DisconnectionContext, DisconnectionDetails, Language, ConnectionType, FormatConfig, } from "./utils/BaseConnection.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,YAAY,EACV,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,cAAc,EACd,iBAAiB,EACjB,SAAS,EACT,MAAM,EACN,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAChB,2BAA2B,EAC3B,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EACL,MAAM,EACN,WAAW,EACX,cAAc,EACd,cAAc,EACd,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,EAC1B,wCAAwC,EACxC,kBAAkB,EAClB,sBAAsB,EACtB,+BAA+B,EAC/B,iCAAiC,EACjC,6BAA6B,EAC7B,iCAAiC,EACjC,6BAA6B,EAC7B,uBAAuB,EACvB,+BAA+B,EAC/B,mCAAmC,EACnC,0CAA0C,EAC1C,mCAAmC,EACnC,2CAA2C,GAC5C,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAEhE,UAAU,qBAAqB;IAC7B,YAAY,CAAC,CAAC,SAAS,cAAc,EACnC,OAAO,EAAE,CAAC,GACT,CAAC,SAAS;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,GAC3B,OAAO,CAAC,gBAAgB,CAAC,GACzB,CAAC,SAAS;QAAE,QAAQ,EAAE,KAAK,CAAA;KAAE,GAC3B,OAAO,CAAC,iBAAiB,CAAC,GAC1B,OAAO,CAAC,gBAAgB,GAAG,iBAAiB,CAAC,CAAC;CACrD;AAED,eAAO,MAAM,YAAY,EAAE,qBAOD,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,YAAY,EACV,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,cAAc,EACd,iBAAiB,EACjB,SAAS,EACT,MAAM,EACN,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAChB,2BAA2B,EAC3B,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AACvE,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EACL,MAAM,EACN,WAAW,EACX,cAAc,EACd,cAAc,EACd,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,EAC1B,wCAAwC,EACxC,kBAAkB,EAClB,sBAAsB,EACtB,+BAA+B,EAC/B,iCAAiC,EACjC,6BAA6B,EAC7B,iCAAiC,EACjC,6BAA6B,EAC7B,uBAAuB,EACvB,+BAA+B,EAC/B,mCAAmC,EACnC,0CAA0C,EAC1C,mCAAmC,EACnC,2CAA2C,GAC5C,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAEhE,UAAU,qBAAqB;IAC7B,YAAY,CAAC,CAAC,SAAS,cAAc,EACnC,OAAO,EAAE,CAAC,GACT,CAAC,SAAS;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,GAC3B,OAAO,CAAC,gBAAgB,CAAC,GACzB,CAAC,SAAS;QAAE,QAAQ,EAAE,KAAK,CAAA;KAAE,GAC3B,OAAO,CAAC,iBAAiB,CAAC,GAC1B,OAAO,CAAC,gBAAgB,GAAG,iBAAiB,CAAC,CAAC;CACrD;AAED,eAAO,MAAM,YAAY,EAAE,qBAOD,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { isTextOnly } from "./BaseConversation.js";
|
|
|
2
2
|
import { assertRuntimeCompatibility } from "./runtime.js";
|
|
3
3
|
import { TextConversation } from "./TextConversation.js";
|
|
4
4
|
import { VoiceConversation } from "./VoiceConversation.js";
|
|
5
|
+
export { DEFAULT_INPUT_CHUNK_DURATION_MS } from "./InputController.js";
|
|
5
6
|
export { createConnection } from "./utils/ConnectionFactory.js";
|
|
6
7
|
export { WebSocketConnection } from "./utils/WebSocketConnection.js";
|
|
7
8
|
export { WebRTCConnection } from "./utils/WebRTCConnection.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAuB,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAuB,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAsB3D,OAAO,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AAoBvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,iBAAiB;AACjB,OAAO,EACL,MAAM,EACN,WAAW,EACX,cAAc,EACd,cAAc,EACd,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAmC3B,MAAM,CAAC,MAAM,YAAY,GAA0B;IACjD,KAAK,CAAC,YAAY,CAAC,OAAuB;QACxC,0BAA0B,EAAE,CAAC;QAC7B,OAAO,UAAU,CAAC,OAAO,CAAC;YACxB,CAAC,CAAC,gBAAgB,CAAC,YAAY,CAAC,OAAO,CAAC;YACxC,CAAC,CAAC,iBAAiB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;CACuB,CAAC"}
|
package/dist/lib.iife.js
CHANGED
|
@@ -92,7 +92,7 @@ var ElevenLabsClient = (function(exports) {
|
|
|
92
92
|
//#region src/sourceInfo.ts
|
|
93
93
|
let sourceInfo = Object.freeze({
|
|
94
94
|
name: "js_sdk",
|
|
95
|
-
version: "1.
|
|
95
|
+
version: "1.9.0"
|
|
96
96
|
});
|
|
97
97
|
//#endregion
|
|
98
98
|
//#region src/utils/events.ts
|
|
@@ -21955,14 +21955,39 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
21955
21955
|
};
|
|
21956
21956
|
}
|
|
21957
21957
|
//#endregion
|
|
21958
|
+
//#region src/platform/web/compatibility.ts
|
|
21959
|
+
function isIosDevice() {
|
|
21960
|
+
return [
|
|
21961
|
+
"iPad Simulator",
|
|
21962
|
+
"iPhone Simulator",
|
|
21963
|
+
"iPod Simulator",
|
|
21964
|
+
"iPad",
|
|
21965
|
+
"iPhone",
|
|
21966
|
+
"iPod"
|
|
21967
|
+
].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "ontouchend" in document;
|
|
21968
|
+
}
|
|
21969
|
+
function isAndroidDevice() {
|
|
21970
|
+
return /android/i.test(navigator.userAgent);
|
|
21971
|
+
}
|
|
21972
|
+
//#endregion
|
|
21958
21973
|
//#region src/platform/web/output.ts
|
|
21974
|
+
function maybePrimeIosPlayback({ sampleRate, format, worklet, audioElement }) {
|
|
21975
|
+
if (!isIosDevice()) return;
|
|
21976
|
+
const primeFrameCount = Math.floor(sampleRate * 100 / 1e3);
|
|
21977
|
+
const silentBuffer = format === "ulaw" ? new Uint8Array(primeFrameCount).fill(255) : new Int16Array(primeFrameCount);
|
|
21978
|
+
worklet.port.postMessage({
|
|
21979
|
+
type: "buffer",
|
|
21980
|
+
buffer: silentBuffer.buffer
|
|
21981
|
+
});
|
|
21982
|
+
audioElement.play().catch(() => {});
|
|
21983
|
+
}
|
|
21959
21984
|
var MediaDeviceOutput = class MediaDeviceOutput {
|
|
21960
|
-
static async create({ sampleRate, format, outputDeviceId, workletPaths, libsampleratePath }) {
|
|
21961
|
-
let context = null;
|
|
21985
|
+
static async create({ sampleRate, format, outputDeviceId, workletPaths, libsampleratePath, audioContext }) {
|
|
21986
|
+
let context = audioContext ?? null;
|
|
21962
21987
|
let audioElement = null;
|
|
21963
21988
|
try {
|
|
21964
21989
|
const supportsSampleRateConstraint = navigator.mediaDevices.getSupportedConstraints().sampleRate;
|
|
21965
|
-
context = new AudioContext(supportsSampleRateConstraint ? { sampleRate } : {});
|
|
21990
|
+
if (!context) context = new AudioContext(supportsSampleRateConstraint ? { sampleRate } : {});
|
|
21966
21991
|
const analyser = context.createAnalyser();
|
|
21967
21992
|
const gain = context.createGain();
|
|
21968
21993
|
audioElement = new Audio();
|
|
@@ -21988,6 +22013,12 @@ registerProcessor("audioConcatProcessor", AudioConcatProcessor);
|
|
|
21988
22013
|
});
|
|
21989
22014
|
worklet.connect(gain);
|
|
21990
22015
|
await context.resume();
|
|
22016
|
+
maybePrimeIosPlayback({
|
|
22017
|
+
sampleRate,
|
|
22018
|
+
format,
|
|
22019
|
+
worklet,
|
|
22020
|
+
audioElement
|
|
22021
|
+
});
|
|
21991
22022
|
if (outputDeviceId && audioElement.setSinkId) await audioElement.setSinkId(outputDeviceId);
|
|
21992
22023
|
return new MediaDeviceOutput(context, analyser, gain, worklet, audioElement);
|
|
21993
22024
|
} catch (error) {
|
|
@@ -22126,7 +22157,11 @@ class RawAudioProcessor extends AudioWorkletProcessor {
|
|
|
22126
22157
|
case "setFormat":
|
|
22127
22158
|
this.isMuted = false;
|
|
22128
22159
|
this.buffer = []; // Initialize an empty buffer
|
|
22129
|
-
|
|
22160
|
+
const chunkDurationMs = data.chunkDurationMs ?? 25;
|
|
22161
|
+
this.bufferSize = Math.max(
|
|
22162
|
+
1,
|
|
22163
|
+
Math.round((data.sampleRate * chunkDurationMs) / 1000)
|
|
22164
|
+
);
|
|
22130
22165
|
this.format = data.format;
|
|
22131
22166
|
|
|
22132
22167
|
if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) {
|
|
@@ -22200,20 +22235,9 @@ class RawAudioProcessor extends AudioWorkletProcessor {
|
|
|
22200
22235
|
registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
22201
22236
|
`);
|
|
22202
22237
|
//#endregion
|
|
22203
|
-
//#region src/
|
|
22204
|
-
|
|
22205
|
-
|
|
22206
|
-
"iPad Simulator",
|
|
22207
|
-
"iPhone Simulator",
|
|
22208
|
-
"iPod Simulator",
|
|
22209
|
-
"iPad",
|
|
22210
|
-
"iPhone",
|
|
22211
|
-
"iPod"
|
|
22212
|
-
].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "ontouchend" in document;
|
|
22213
|
-
}
|
|
22214
|
-
function isAndroidDevice() {
|
|
22215
|
-
return /android/i.test(navigator.userAgent);
|
|
22216
|
-
}
|
|
22238
|
+
//#region src/InputController.ts
|
|
22239
|
+
/** Default microphone audio chunk duration sent to the agent (WebSocket path). */
|
|
22240
|
+
const DEFAULT_INPUT_CHUNK_DURATION_MS = 25;
|
|
22217
22241
|
//#endregion
|
|
22218
22242
|
//#region src/platform/web/input.ts
|
|
22219
22243
|
const defaultConstraints = {
|
|
@@ -22223,7 +22247,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22223
22247
|
channelCount: { ideal: 1 }
|
|
22224
22248
|
};
|
|
22225
22249
|
var MediaDeviceInput = class MediaDeviceInput {
|
|
22226
|
-
static async create({ sampleRate, format, preferHeadphonesForIosDevices, inputDeviceId, workletPaths, libsampleratePath, onError }) {
|
|
22250
|
+
static async create({ sampleRate, format, preferHeadphonesForIosDevices, inputDeviceId, workletPaths, libsampleratePath, onError, inputChunkDurationMs = 25 }) {
|
|
22227
22251
|
let context = null;
|
|
22228
22252
|
let inputStream = null;
|
|
22229
22253
|
try {
|
|
@@ -22255,7 +22279,8 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22255
22279
|
worklet.port.postMessage({
|
|
22256
22280
|
type: "setFormat",
|
|
22257
22281
|
format,
|
|
22258
|
-
sampleRate
|
|
22282
|
+
sampleRate,
|
|
22283
|
+
chunkDurationMs: inputChunkDurationMs
|
|
22259
22284
|
});
|
|
22260
22285
|
source.connect(analyser);
|
|
22261
22286
|
analyser.connect(worklet);
|
|
@@ -22372,6 +22397,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22372
22397
|
inputFormat;
|
|
22373
22398
|
outputFormat;
|
|
22374
22399
|
outputListeners = /* @__PURE__ */ new Set();
|
|
22400
|
+
pendingAudioEvents = [];
|
|
22375
22401
|
constructor(socket, conversationId, inputFormat, outputFormat) {
|
|
22376
22402
|
super();
|
|
22377
22403
|
this.socket = socket;
|
|
@@ -22472,13 +22498,19 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22472
22498
|
}
|
|
22473
22499
|
}
|
|
22474
22500
|
close() {
|
|
22501
|
+
this.pendingAudioEvents = [];
|
|
22475
22502
|
this.socket.close(1e3, "User ended conversation");
|
|
22476
22503
|
}
|
|
22477
22504
|
sendMessage(message) {
|
|
22478
22505
|
this.socket.send(JSON.stringify(message));
|
|
22479
22506
|
}
|
|
22480
22507
|
addListener(listener) {
|
|
22508
|
+
const hadListeners = this.outputListeners.size > 0;
|
|
22481
22509
|
this.outputListeners.add(listener);
|
|
22510
|
+
if (hadListeners || this.pendingAudioEvents.length === 0) return;
|
|
22511
|
+
const pending = this.pendingAudioEvents;
|
|
22512
|
+
this.pendingAudioEvents = [];
|
|
22513
|
+
for (const event of pending) listener(event);
|
|
22482
22514
|
}
|
|
22483
22515
|
removeListener(listener) {
|
|
22484
22516
|
this.outputListeners.delete(listener);
|
|
@@ -22487,6 +22519,10 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22487
22519
|
super.handleMessage(parsedEvent);
|
|
22488
22520
|
if (parsedEvent.type === "audio" && parsedEvent.audio_event.audio_base_64) {
|
|
22489
22521
|
const audioEvent = { audio_base_64: parsedEvent.audio_event.audio_base_64 };
|
|
22522
|
+
if (this.outputListeners.size === 0) {
|
|
22523
|
+
this.pendingAudioEvents.push(audioEvent);
|
|
22524
|
+
return;
|
|
22525
|
+
}
|
|
22490
22526
|
this.outputListeners.forEach((listener) => listener(audioEvent));
|
|
22491
22527
|
}
|
|
22492
22528
|
}
|
|
@@ -22553,6 +22589,70 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22553
22589
|
if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
22554
22590
|
}
|
|
22555
22591
|
//#endregion
|
|
22592
|
+
//#region src/platform/web/audioUnlock.ts
|
|
22593
|
+
const STASH_TTL_MS = 3e4;
|
|
22594
|
+
const UNLOCK_EVENTS = [
|
|
22595
|
+
"touchstart",
|
|
22596
|
+
"touchend",
|
|
22597
|
+
"click"
|
|
22598
|
+
];
|
|
22599
|
+
let stashedAudioContext = null;
|
|
22600
|
+
let discardTimer = null;
|
|
22601
|
+
let unlockListenerInstalled = false;
|
|
22602
|
+
function unlockAudioContext(ctx) {
|
|
22603
|
+
const buffer = ctx.createBuffer(1, 1, 22050);
|
|
22604
|
+
const source = ctx.createBufferSource();
|
|
22605
|
+
source.buffer = buffer;
|
|
22606
|
+
source.connect(ctx.destination);
|
|
22607
|
+
source.start(0);
|
|
22608
|
+
ctx.resume().catch(() => {});
|
|
22609
|
+
}
|
|
22610
|
+
function scheduleStashDiscard() {
|
|
22611
|
+
if (discardTimer) clearTimeout(discardTimer);
|
|
22612
|
+
discardTimer = setTimeout(() => {
|
|
22613
|
+
discardTimer = null;
|
|
22614
|
+
discardStashedAudioContext();
|
|
22615
|
+
}, STASH_TTL_MS);
|
|
22616
|
+
}
|
|
22617
|
+
function clearStashDiscardTimer() {
|
|
22618
|
+
if (!discardTimer) return;
|
|
22619
|
+
clearTimeout(discardTimer);
|
|
22620
|
+
discardTimer = null;
|
|
22621
|
+
}
|
|
22622
|
+
/** Unlock iOS audio during a user gesture. No-op on non-iOS. */
|
|
22623
|
+
function unlockIosAudioForSession() {
|
|
22624
|
+
if (!isIosDevice() || stashedAudioContext) return;
|
|
22625
|
+
const ctx = new AudioContext();
|
|
22626
|
+
unlockAudioContext(ctx);
|
|
22627
|
+
stashedAudioContext = ctx;
|
|
22628
|
+
scheduleStashDiscard();
|
|
22629
|
+
}
|
|
22630
|
+
/**
|
|
22631
|
+
* Listen for the first user interaction on the page and unlock iOS audio in
|
|
22632
|
+
* the capture phase, before application click handlers run. Covers callers
|
|
22633
|
+
* (such as the convai widget) that `await` before `Conversation.startSession`.
|
|
22634
|
+
*/
|
|
22635
|
+
function installIosAudioUnlockListener() {
|
|
22636
|
+
if (!isIosDevice() || unlockListenerInstalled || typeof document === "undefined") return;
|
|
22637
|
+
unlockListenerInstalled = true;
|
|
22638
|
+
const onUserGesture = () => {
|
|
22639
|
+
unlockIosAudioForSession();
|
|
22640
|
+
};
|
|
22641
|
+
for (const event of UNLOCK_EVENTS) document.addEventListener(event, onUserGesture, true);
|
|
22642
|
+
}
|
|
22643
|
+
function takeUnlockedAudioContext() {
|
|
22644
|
+
const ctx = stashedAudioContext;
|
|
22645
|
+
stashedAudioContext = null;
|
|
22646
|
+
clearStashDiscardTimer();
|
|
22647
|
+
return ctx;
|
|
22648
|
+
}
|
|
22649
|
+
function discardStashedAudioContext() {
|
|
22650
|
+
if (!stashedAudioContext) return;
|
|
22651
|
+
stashedAudioContext.close().catch(() => {});
|
|
22652
|
+
stashedAudioContext = null;
|
|
22653
|
+
clearStashDiscardTimer();
|
|
22654
|
+
}
|
|
22655
|
+
//#endregion
|
|
22556
22656
|
//#region src/platform/web/VoiceSessionSetup.ts
|
|
22557
22657
|
function detectPlatform() {
|
|
22558
22658
|
if (isAndroidDevice()) return "android";
|
|
@@ -22569,17 +22669,19 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22569
22669
|
* Sets up WebSocket-specific input and output controllers using
|
|
22570
22670
|
* web MediaDevice APIs (AudioContext, AudioWorklet, etc.).
|
|
22571
22671
|
*/
|
|
22572
|
-
async function setupWebSocketIO(options, connection) {
|
|
22672
|
+
async function setupWebSocketIO(options, connection, audioContext) {
|
|
22573
22673
|
const [input, output] = await Promise.all([MediaDeviceInput.create({
|
|
22574
22674
|
...connection.inputFormat,
|
|
22575
22675
|
preferHeadphonesForIosDevices: options.preferHeadphonesForIosDevices,
|
|
22576
22676
|
inputDeviceId: options.inputDeviceId,
|
|
22677
|
+
inputChunkDurationMs: options.inputChunkDurationMs,
|
|
22577
22678
|
workletPaths: options.workletPaths,
|
|
22578
22679
|
libsampleratePath: options.libsampleratePath
|
|
22579
22680
|
}), MediaDeviceOutput.create({
|
|
22580
22681
|
...connection.outputFormat,
|
|
22581
22682
|
outputDeviceId: options.outputDeviceId,
|
|
22582
|
-
workletPaths: options.workletPaths
|
|
22683
|
+
workletPaths: options.workletPaths,
|
|
22684
|
+
audioContext: audioContext ?? void 0
|
|
22583
22685
|
})]);
|
|
22584
22686
|
const detachInput = attachInputToConnection(input, connection);
|
|
22585
22687
|
const detachOutput = attachConnectionToOutput(connection, output);
|
|
@@ -22602,6 +22704,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22602
22704
|
const useWakeLock = options.useWakeLock ?? true;
|
|
22603
22705
|
let wakeLock = null;
|
|
22604
22706
|
let preliminaryInputStream = null;
|
|
22707
|
+
let unlockedAudioContext = null;
|
|
22605
22708
|
try {
|
|
22606
22709
|
if (useWakeLock) wakeLock = await requestWakeLock();
|
|
22607
22710
|
preliminaryInputStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
@@ -22610,12 +22713,20 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22610
22713
|
const connection = await createConnection(options);
|
|
22611
22714
|
let result;
|
|
22612
22715
|
try {
|
|
22613
|
-
if (connection instanceof WebSocketConnection)
|
|
22614
|
-
|
|
22615
|
-
|
|
22616
|
-
|
|
22617
|
-
|
|
22716
|
+
if (connection instanceof WebSocketConnection) {
|
|
22717
|
+
unlockedAudioContext = takeUnlockedAudioContext();
|
|
22718
|
+
result = {
|
|
22719
|
+
connection,
|
|
22720
|
+
...await setupWebSocketIO(options, connection, unlockedAudioContext)
|
|
22721
|
+
};
|
|
22722
|
+
unlockedAudioContext = null;
|
|
22723
|
+
} else {
|
|
22724
|
+
discardStashedAudioContext();
|
|
22725
|
+
result = setupWebRTCSession(connection);
|
|
22726
|
+
}
|
|
22618
22727
|
} catch (ioError) {
|
|
22728
|
+
await unlockedAudioContext?.close().catch(() => {});
|
|
22729
|
+
unlockedAudioContext = null;
|
|
22619
22730
|
connection.close();
|
|
22620
22731
|
throw ioError;
|
|
22621
22732
|
}
|
|
@@ -22650,6 +22761,7 @@ registerProcessor("rawAudioProcessor", RawAudioProcessor);
|
|
|
22650
22761
|
await wakeLock?.release();
|
|
22651
22762
|
wakeLock = null;
|
|
22652
22763
|
} catch (_e) {}
|
|
22764
|
+
discardStashedAudioContext();
|
|
22653
22765
|
throw error;
|
|
22654
22766
|
}
|
|
22655
22767
|
}
|
|
@@ -23993,12 +24105,14 @@ registerProcessor("scribeAudioProcessor", ScribeAudioProcessor);
|
|
|
23993
24105
|
} };
|
|
23994
24106
|
//#endregion
|
|
23995
24107
|
//#region src/platform/web/index.ts
|
|
24108
|
+
installIosAudioUnlockListener();
|
|
23996
24109
|
setWebRTCAudioAdapterFactory(() => new WebAudioAdapter());
|
|
23997
24110
|
setScribeMicrophoneSetup(webScribeMicrophoneSetup);
|
|
23998
24111
|
//#endregion
|
|
23999
24112
|
exports.AudioFormat = AudioFormat;
|
|
24000
24113
|
exports.CommitStrategy = CommitStrategy;
|
|
24001
24114
|
exports.Conversation = Conversation;
|
|
24115
|
+
exports.DEFAULT_INPUT_CHUNK_DURATION_MS = DEFAULT_INPUT_CHUNK_DURATION_MS;
|
|
24002
24116
|
exports.RealtimeConnection = RealtimeConnection;
|
|
24003
24117
|
exports.RealtimeEvents = RealtimeEvents;
|
|
24004
24118
|
exports.Scribe = ScribeRealtime;
|