@framers/agentos 0.13.78 → 0.13.79
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/io/voice-pipeline/AcousticEndpointDetector.d.ts +2 -0
- package/dist/io/voice-pipeline/AcousticEndpointDetector.d.ts.map +1 -1
- package/dist/io/voice-pipeline/AcousticEndpointDetector.js +1 -0
- package/dist/io/voice-pipeline/AcousticEndpointDetector.js.map +1 -1
- package/dist/io/voice-pipeline/HeuristicEndpointDetector.d.ts +2 -0
- package/dist/io/voice-pipeline/HeuristicEndpointDetector.d.ts.map +1 -1
- package/dist/io/voice-pipeline/HeuristicEndpointDetector.js +4 -0
- package/dist/io/voice-pipeline/HeuristicEndpointDetector.js.map +1 -1
- package/dist/io/voice-pipeline/ListenSession.d.ts +111 -0
- package/dist/io/voice-pipeline/ListenSession.d.ts.map +1 -0
- package/dist/io/voice-pipeline/ListenSession.js +242 -0
- package/dist/io/voice-pipeline/ListenSession.js.map +1 -0
- package/dist/io/voice-pipeline/ReconnectingSTT.d.ts +90 -0
- package/dist/io/voice-pipeline/ReconnectingSTT.d.ts.map +1 -0
- package/dist/io/voice-pipeline/ReconnectingSTT.js +318 -0
- package/dist/io/voice-pipeline/ReconnectingSTT.js.map +1 -0
- package/dist/io/voice-pipeline/env-constructor.d.ts +17 -9
- package/dist/io/voice-pipeline/env-constructor.d.ts.map +1 -1
- package/dist/io/voice-pipeline/env-constructor.js +6 -2
- package/dist/io/voice-pipeline/env-constructor.js.map +1 -1
- package/dist/io/voice-pipeline/index.d.ts +6 -0
- package/dist/io/voice-pipeline/index.d.ts.map +1 -1
- package/dist/io/voice-pipeline/index.js +7 -0
- package/dist/io/voice-pipeline/index.js.map +1 -1
- package/dist/io/voice-pipeline/providers/StreamingSTTChain.d.ts +9 -5
- package/dist/io/voice-pipeline/providers/StreamingSTTChain.d.ts.map +1 -1
- package/dist/io/voice-pipeline/providers/StreamingSTTChain.js +44 -8
- package/dist/io/voice-pipeline/providers/StreamingSTTChain.js.map +1 -1
- package/dist/io/voice-pipeline/types.d.ts +6 -0
- package/dist/io/voice-pipeline/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -105,6 +105,8 @@ export declare class AcousticEndpointDetector extends EventEmitter implements IE
|
|
|
105
105
|
* See `IEndpointDetector.mode`.
|
|
106
106
|
*/
|
|
107
107
|
readonly mode: "acoustic";
|
|
108
|
+
/** Maximum silence wait plus one polling interval, used when draining a listen session. */
|
|
109
|
+
readonly turnCompletionTimeoutMs: number;
|
|
108
110
|
/**
|
|
109
111
|
* Underlying silence-duration tracker from `media/audio/`.
|
|
110
112
|
* Handles the actual timer management and threshold comparison.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AcousticEndpointDetector.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/AcousticEndpointDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,eAAe,EAAqB,MAAM,YAAY,CAAC;AAMlG;;;;;;;;;;GAUG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;;;;;OAMG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;IAErC;;;;;;;;;OASG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,wBAAyB,SAAQ,YAAa,YAAW,iBAAiB;IACrF;;;OAGG;IACH,SAAgB,IAAI,EAAG,UAAU,CAAU;IAE3C;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAElD;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB,CAAuB;IAEhD;;;;;;OAMG;IACH,OAAO,CAAC,eAAe,CAAuB;IAM9C;;;;OAIG;gBACS,MAAM,GAAE,8BAAmC;
|
|
1
|
+
{"version":3,"file":"AcousticEndpointDetector.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/AcousticEndpointDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,eAAe,EAAqB,MAAM,YAAY,CAAC;AAMlG;;;;;;;;;;GAUG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;;;;;OAMG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;IAErC;;;;;;;;;OASG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,wBAAyB,SAAQ,YAAa,YAAW,iBAAiB;IACrF;;;OAGG;IACH,SAAgB,IAAI,EAAG,UAAU,CAAU;IAE3C,2FAA2F;IAC3F,SAAgB,uBAAuB,EAAE,MAAM,CAAC;IAEhD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAElD;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB,CAAuB;IAEhD;;;;;;OAMG;IACH,OAAO,CAAC,eAAe,CAAuB;IAM9C;;;;OAIG;gBACS,MAAM,GAAE,8BAAmC;IAwCvD;;;;;;;;;;OAUG;IACI,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAwC1C;;;;;;;OAOG;IACI,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAUpD;;;;;;OAMG;IACI,KAAK,IAAI,IAAI;CAKrB"}
|
|
@@ -108,6 +108,7 @@ export class AcousticEndpointDetector extends EventEmitter {
|
|
|
108
108
|
utteranceEndThresholdMs: config.utteranceEndThresholdMs ?? 3000,
|
|
109
109
|
};
|
|
110
110
|
this.silenceDetector = new SilenceDetector(sdConfig);
|
|
111
|
+
this.turnCompletionTimeoutMs = Math.max(500, sdConfig.utteranceEndThresholdMs || 3000) + 250;
|
|
111
112
|
// When SilenceDetector decides the utterance has ended (silence exceeded
|
|
112
113
|
// utteranceEndThresholdMs), translate that into a TurnCompleteEvent.
|
|
113
114
|
this.silenceDetector.on('utterance_end_detected', (_silenceDurationMs) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AcousticEndpointDetector.js","sourceRoot":"","sources":["../../../src/io/voice-pipeline/AcousticEndpointDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAA8B,MAAM,+BAA+B,CAAC;AAyC5F,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,wBAAyB,SAAQ,YAAY;
|
|
1
|
+
{"version":3,"file":"AcousticEndpointDetector.js","sourceRoot":"","sources":["../../../src/io/voice-pipeline/AcousticEndpointDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -142,6 +142,8 @@ export declare class HeuristicEndpointDetector extends EventEmitter implements I
|
|
|
142
142
|
* @param options - Optional configuration overrides.
|
|
143
143
|
*/
|
|
144
144
|
constructor(options?: HeuristicEndpointDetectorOptions);
|
|
145
|
+
/** Maximum wait for a pending turn after speech ends, used when draining a listen session. */
|
|
146
|
+
get turnCompletionTimeoutMs(): number;
|
|
145
147
|
/**
|
|
146
148
|
* Ingest a transcript event from the upstream STT session.
|
|
147
149
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeuristicEndpointDetector.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/HeuristicEndpointDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,QAAQ,EAAqB,MAAM,YAAY,CAAC;AAkElG;;;;;;;GAOG;AACH,MAAM,WAAW,gCAAgC;IAC/C;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,yBAA0B,SAAQ,YAAa,YAAW,iBAAiB;IACtF;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAe;IAEvD,gDAAgD;IAChD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAM;IAE7B;;;;OAIG;IACH,OAAO,CAAC,YAAY,CAAS;IAE7B;;;OAGG;IACH,OAAO,CAAC,YAAY,CAA8C;IAElE;;;;OAIG;IACH,OAAO,CAAC,WAAW,CAAuB;IAE1C;;;;OAIG;IACH,OAAO,CAAC,cAAc,CAAK;IAE3B;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB,CAAuB;IAEnD;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB,CAAK;IAMnC;;;;OAIG;gBACS,OAAO,GAAE,gCAAqC;
|
|
1
|
+
{"version":3,"file":"HeuristicEndpointDetector.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/HeuristicEndpointDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,QAAQ,EAAqB,MAAM,YAAY,CAAC;AAkElG;;;;;;;GAOG;AACH,MAAM,WAAW,gCAAgC;IAC/C;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,yBAA0B,SAAQ,YAAa,YAAW,iBAAiB;IACtF;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAe;IAEvD,gDAAgD;IAChD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAM;IAE7B;;;;OAIG;IACH,OAAO,CAAC,YAAY,CAAS;IAE7B;;;OAGG;IACH,OAAO,CAAC,YAAY,CAA8C;IAElE;;;;OAIG;IACH,OAAO,CAAC,WAAW,CAAuB;IAE1C;;;;OAIG;IACH,OAAO,CAAC,cAAc,CAAK;IAE3B;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB,CAAuB;IAEnD;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB,CAAK;IAMnC;;;;OAIG;gBACS,OAAO,GAAE,gCAAqC;IAK1D,8FAA8F;IAC9F,IAAI,uBAAuB,IAAI,MAAM,CAEpC;IAMD;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI;IAwCjD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IA6CnC;;;;;;;OAOG;IACH,KAAK,IAAI,IAAI;IAab;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAatB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,iBAAiB;IAkBzB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;CAM3B"}
|
|
@@ -187,6 +187,10 @@ export class HeuristicEndpointDetector extends EventEmitter {
|
|
|
187
187
|
this.speechEndWithoutTextAt = 0;
|
|
188
188
|
this.silenceTimeoutMs = options.silenceTimeoutMs ?? DEFAULT_SILENCE_TIMEOUT_MS;
|
|
189
189
|
}
|
|
190
|
+
/** Maximum wait for a pending turn after speech ends, used when draining a listen session. */
|
|
191
|
+
get turnCompletionTimeoutMs() {
|
|
192
|
+
return this.silenceTimeoutMs;
|
|
193
|
+
}
|
|
190
194
|
// ---------------------------------------------------------------------------
|
|
191
195
|
// IEndpointDetector -- pushTranscript
|
|
192
196
|
// ---------------------------------------------------------------------------
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeuristicEndpointDetector.js","sourceRoot":"","sources":["../../../src/io/voice-pipeline/HeuristicEndpointDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,0BAA0B,GAAG,IAAK,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAEtC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IACvD,QAAQ;IACR,MAAM;IACN,MAAM;IACN,IAAI;IACJ,QAAQ;IACR,OAAO;IACP,KAAK;IACL,QAAQ;IACR,OAAO;IACP,MAAM;IACN,KAAK;IACL,KAAK;IACL,QAAQ;CACT,CAAC,CAAC;AAwBH,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,OAAO,yBAA0B,SAAQ,YAAY;IAgEzD,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAE9E;;;;OAIG;IACH,YAAY,UAA4C,EAAE;QACxD,KAAK,EAAE,CAAC;QAzEV;;;;;WAKG;QACM,SAAI,GAA8B,WAAW,CAAC;QAKvD;;;;WAIG;QACK,oBAAe,GAAG,EAAE,CAAC;QAE7B;;;;WAIG;QACK,iBAAY,GAAG,KAAK,CAAC;QAE7B;;;WAGG;QACK,iBAAY,GAAyC,IAAI,CAAC;QAElE;;;;WAIG;QACK,gBAAW,GAAkB,IAAI,CAAC;QAE1C;;;;WAIG;QACK,mBAAc,GAAG,CAAC,CAAC;QAE3B;;;;;;;WAOG;QACK,yBAAoB,GAAkB,IAAI,CAAC;QAEnD;;;;;WAKG;QACK,2BAAsB,GAAG,CAAC,CAAC;QAajC,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,0BAA0B,CAAC;IACjF,CAAC;IAED,8EAA8E;IAC9E,sCAAsC;IACtC,8EAA8E;IAE9E;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,UAA2B;QACxC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACxB,kEAAkE;YAClE,gDAAgD;YAChD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC;QAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAE7C,uEAAuE;QACvE,mCAAmC;QACnC,IAAI,CAAC,UAAU;YAAE,OAAO;QAExB,uEAAuE;QACvE,oEAAoE;QACpE,IAAI,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,kEAAkE;QAClE,kEAAkE;QAClE,yEAAyE;QACzE,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,UAAU,CAAC;QAE5C,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,IAAI,CAAC,oBAAoB,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YAC7D,MAAM,kBAAkB,GAAG,IAAI,CAAC,oBAAoB,CAAC;YACrD,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;YACjC,IAAI,CAAC,cAAc,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,oCAAoC;IACpC,8EAA8E;IAE9E;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,YAAY,CAAC,KAAe;QAC1B,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,cAAc,CAAC,CAAC,CAAC;gBACpB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;gBACzB,wEAAwE;gBACxE,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;gBACjC,iEAAiE;gBACjE,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC1B,gEAAgE;gBAChE,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;oBAC9B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC;gBACrC,CAAC;gBACD,MAAM;YACR,CAAC;YAED,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;gBAE1B,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC1B,yDAAyD;oBACzD,6DAA6D;oBAC7D,yDAAyD;oBACzD,8DAA8D;oBAC9D,yDAAyD;oBACzD,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC,SAAS,CAAC;oBAC5C,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBACzC,MAAM;gBACR,CAAC;gBAED,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBACrC,MAAM;YACR,CAAC;YAED,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,8DAA8D;gBAC9D,8DAA8D;gBAC9D,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,6BAA6B;IAC7B,8EAA8E;IAE9E;;;;;;;OAOG;IACH,KAAK;QACH,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;IACnC,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E;;;;;;;;OAQG;IACK,cAAc,CAAC,kBAA0B,EAAE,cAAc,GAAG,CAAC;QACnE,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;YACpD,8DAA8D;YAC9D,gEAAgE;YAChE,IAAI,CAAC,iBAAiB,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,sDAAsD;YACtD,+DAA+D;YAC/D,0DAA0D;YAC1D,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED;;;;;;;;;;;OAWG;IACK,iBAAiB,CAAC,MAAmC,EAAE,kBAA0B;QACvF,2EAA2E;QAC3E,sDAAsD;QACtD,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,kBAAkB,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzF,MAAM,KAAK,GAAsB;YAC/B,UAAU,EAAE,IAAI,CAAC,eAAe;YAChC,UAAU,EAAE,IAAI,CAAC,cAAc;YAC/B,UAAU;YACV,MAAM;SACP,CAAC;QAEF,0EAA0E;QAC1E,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACpC,CAAC;IAED;;;;;;;;;;;;;OAaG;IACK,kBAAkB,CAAC,kBAA0B,EAAE,cAAc,GAAG,CAAC;QACvE,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,sEAAsE;QACtE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAC9C,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxD,4EAA4E;YAC5E,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;YAC9D,OAAO;QACT,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE;YAClC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;QAChE,CAAC,EAAE,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IACxC,CAAC;IAED;;;OAGG;IACK,kBAAkB;QACxB,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YAC/B,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAChC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;IACH,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"HeuristicEndpointDetector.js","sourceRoot":"","sources":["../../../src/io/voice-pipeline/HeuristicEndpointDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module voice-pipeline/ListenSession
|
|
3
|
+
*
|
|
4
|
+
* A session that listens and writes: a transport's audio into a streaming
|
|
5
|
+
* transcriber, each final (or each detector turn) into a sink as a numbered
|
|
6
|
+
* turn. No synthesis, no barge-in, no agent turn. Built for a notetaker, a
|
|
7
|
+
* meeting bot or a transcription job, where {@link VoicePipelineOrchestrator}
|
|
8
|
+
* is built for a conversation.
|
|
9
|
+
*/
|
|
10
|
+
import { EventEmitter } from 'node:events';
|
|
11
|
+
import { type ReconnectingSTTOptions } from './ReconnectingSTT.js';
|
|
12
|
+
import type { IEndpointDetector, IStreamingSTT, IStreamTransport, ITranscriptInputSink, StreamingSTTConfig, TranscriptEvent } from './types.js';
|
|
13
|
+
export type { ITranscriptSink, ITranscriptInputSink, TranscriptInput, TranscriptTurn } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Why a listen session ended. `stopped` drains the last utterance first; `purged` drains nothing and drops what is
|
|
16
|
+
* queued; faults are `stt_failed` (the transcriber failed for good, past {@link ReconnectingSTT}'s cap or at once
|
|
17
|
+
* without it), `transport_closed`, `transport_failed` (the transport emitted an error, included in `ended`)
|
|
18
|
+
* and `sink_failed` (the sink threw on a write).
|
|
19
|
+
*/
|
|
20
|
+
export type ListenEndReason = 'stopped' | 'purged' | 'stt_failed' | 'transport_closed' | 'transport_failed' | 'sink_failed';
|
|
21
|
+
/** What {@link startListenSession} takes besides the transport and the sink: only the transcriber and the run are required. */
|
|
22
|
+
export interface ListenSessionOverrides {
|
|
23
|
+
/** The streaming transcriber; wrapped in {@link ReconnectingSTT} unless `reconnect` is `false`. */
|
|
24
|
+
streamingSTT: IStreamingSTT;
|
|
25
|
+
/** The run the turns belong to; turn ids are `<runId>:<n>`. */
|
|
26
|
+
runId: string;
|
|
27
|
+
/**
|
|
28
|
+
* When given, its `turn_complete` events are the turns; without one, each final is a turn.
|
|
29
|
+
* An empty detector transcript uses the STT finals since the previous turn, joined with spaces,
|
|
30
|
+
* and their first start and last end times (including with {@link AcousticEndpointDetector}).
|
|
31
|
+
*/
|
|
32
|
+
endpointDetector?: IEndpointDetector;
|
|
33
|
+
/** Passed to the transcriber's `startSession()`. */
|
|
34
|
+
sttConfig?: StreamingSTTConfig;
|
|
35
|
+
/** Wrap the transcriber in {@link ReconnectingSTT} (default true). A chain of several providers passes `false`. */
|
|
36
|
+
reconnect?: boolean | ReconnectingSTTOptions;
|
|
37
|
+
/** Finals waiting for the sink before the transport is paused. Default 8. */
|
|
38
|
+
sinkQueueLimit?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Names who spoke a turn, from the transcriber's final. A detector turn carries its text and no words,
|
|
41
|
+
* unless empty detector text uses the accumulated STT finals and their words.
|
|
42
|
+
*/
|
|
43
|
+
speaker?: (event: TranscriptEvent) => string | undefined;
|
|
44
|
+
/** How long a stop waits for the flushed final to arrive, before draining a pending detector turn. Default 250. */
|
|
45
|
+
drainMs?: number;
|
|
46
|
+
}
|
|
47
|
+
/** A listen session's counts so far. */
|
|
48
|
+
export interface ListenSessionStats {
|
|
49
|
+
/** Turns the sink stored; one it dropped (behind a fence, or for a run that is over) is not counted. */
|
|
50
|
+
turns: number;
|
|
51
|
+
/**
|
|
52
|
+
* Audio frames that came while the transport was asked to pause. They still reach the transcriber, so a count
|
|
53
|
+
* above zero shows a transport that does not hold its buffer.
|
|
54
|
+
*/
|
|
55
|
+
dropped: number;
|
|
56
|
+
/** Reconnects of the transcriber. */
|
|
57
|
+
reconnects: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `listening`: audio flows and finals are written. `draining`: a stop was asked; the transcriber is flushed and the
|
|
61
|
+
* finals it still emits are written. `ending`: nothing new is accepted; the queue is written out. `ended`: done.
|
|
62
|
+
*/
|
|
63
|
+
export type ListenSessionState = 'listening' | 'draining' | 'ending' | 'ended';
|
|
64
|
+
/** A running listen session; {@link startListenSession} lists its events. */
|
|
65
|
+
export interface ListenSession extends EventEmitter {
|
|
66
|
+
/** The run its turns belong to. */
|
|
67
|
+
readonly runId: string;
|
|
68
|
+
/** Where the session is in its life, read when asked. */
|
|
69
|
+
readonly state: ListenSessionState;
|
|
70
|
+
/** The transport it reads. */
|
|
71
|
+
readonly transport: IStreamTransport;
|
|
72
|
+
/** The counts so far. */
|
|
73
|
+
stats(): ListenSessionStats;
|
|
74
|
+
/**
|
|
75
|
+
* `stopped` flushes the transcriber, waits `drainMs`, then waits for a pending detector turn up to
|
|
76
|
+
* its `turnCompletionTimeoutMs` (3250 ms if omitted), plus one timer tick, before resetting. `purged` drops everything
|
|
77
|
+
* queued without draining. Every end releases an outstanding transport pause; resolves at `ended`.
|
|
78
|
+
*/
|
|
79
|
+
close(reason?: ListenEndReason): Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Starts listening. Emits `turn` (a {@link TranscriptTurn}), `interim` (a {@link TranscriptEvent}), `stt:reconnected`,
|
|
83
|
+
* `stt:gap`, `paused`, `resumed` and `ended` (`{ reason, error? }`).
|
|
84
|
+
*
|
|
85
|
+
* The transport's frames go to the transcriber. Each final, or with an endpoint detector each `turn_complete`, goes
|
|
86
|
+
* to the sink, one write at a time in arrival order; the sink numbers it. When `sinkQueueLimit` finals wait for the
|
|
87
|
+
* sink, the session emits `pause` on the transport and `paused` on itself, and `resume` and `resumed` once the queue
|
|
88
|
+
* is down to half or the session ends; a final is never dropped for a slow sink. The transcriber's `speech_start`
|
|
89
|
+
* and `speech_end` reach the detector as voice activity, as the orchestrator gives them. The session ends once, for the first
|
|
90
|
+
* {@link ListenEndReason}; it closes the transcriber and leaves the transport open, since the transport is the
|
|
91
|
+
* caller's. A transport error ends it with `transport_failed` and the error in `ended`. Its transport listeners
|
|
92
|
+
* are removed on every end. An empty detector turn uses the accumulated STT finals and their timing.
|
|
93
|
+
*
|
|
94
|
+
* @param transport - Where the audio comes from: the session listens for its `audio`, `close` and `error`.
|
|
95
|
+
* @param sink - Where the turns go; it assigns each turn's number and id.
|
|
96
|
+
* @param overrides - The transcriber, the run and the session's options.
|
|
97
|
+
* @returns The session, listening.
|
|
98
|
+
* @throws {Error} When the transcriber's first session fails to open.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const session = await startListenSession(transport, sink, {
|
|
103
|
+
* streamingSTT: new DeepgramStreamingSTT({ apiKey: process.env.DEEPGRAM_API_KEY! }),
|
|
104
|
+
* runId: 'run-1',
|
|
105
|
+
* });
|
|
106
|
+
* session.on('ended', ({ reason }: { reason: ListenEndReason }) => console.log(`listening ended: ${reason}`));
|
|
107
|
+
* await session.close('stopped');
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export declare function startListenSession(transport: IStreamTransport, sink: ITranscriptInputSink, overrides: ListenSessionOverrides): Promise<ListenSession>;
|
|
111
|
+
//# sourceMappingURL=ListenSession.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListenSession.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/ListenSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAmB,KAAK,sBAAsB,EAA8C,MAAM,sBAAsB,CAAC;AAChI,OAAO,KAAK,EAAc,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,kBAAkB,EAAuB,eAAe,EAAgE,MAAM,YAAY,CAAC;AAE/O,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEzG;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY,GAAG,kBAAkB,GAAG,kBAAkB,GAAG,aAAa,CAAC;AAE5H,+HAA+H;AAC/H,MAAM,WAAW,sBAAsB;IACrC,mGAAmG;IACnG,YAAY,EAAE,aAAa,CAAC;IAC5B,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,oDAAoD;IACpD,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,mHAAmH;IACnH,SAAS,CAAC,EAAE,OAAO,GAAG,sBAAsB,CAAC;IAC7C,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,MAAM,GAAG,SAAS,CAAC;IACzD,mHAAmH;IACnH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wCAAwC;AACxC,MAAM,WAAW,kBAAkB;IACjC,wGAAwG;IACxG,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/E,6EAA6E;AAC7E,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,mCAAmC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,yBAAyB;IACzB,KAAK,IAAI,kBAAkB,CAAC;IAC5B;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,oBAAoB,EAAE,SAAS,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,CAAC,CAwL3J"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module voice-pipeline/ListenSession
|
|
3
|
+
*
|
|
4
|
+
* A session that listens and writes: a transport's audio into a streaming
|
|
5
|
+
* transcriber, each final (or each detector turn) into a sink as a numbered
|
|
6
|
+
* turn. No synthesis, no barge-in, no agent turn. Built for a notetaker, a
|
|
7
|
+
* meeting bot or a transcription job, where {@link VoicePipelineOrchestrator}
|
|
8
|
+
* is built for a conversation.
|
|
9
|
+
*/
|
|
10
|
+
import { EventEmitter } from 'node:events';
|
|
11
|
+
import { ReconnectingSTT } from './ReconnectingSTT.js';
|
|
12
|
+
/**
|
|
13
|
+
* Starts listening. Emits `turn` (a {@link TranscriptTurn}), `interim` (a {@link TranscriptEvent}), `stt:reconnected`,
|
|
14
|
+
* `stt:gap`, `paused`, `resumed` and `ended` (`{ reason, error? }`).
|
|
15
|
+
*
|
|
16
|
+
* The transport's frames go to the transcriber. Each final, or with an endpoint detector each `turn_complete`, goes
|
|
17
|
+
* to the sink, one write at a time in arrival order; the sink numbers it. When `sinkQueueLimit` finals wait for the
|
|
18
|
+
* sink, the session emits `pause` on the transport and `paused` on itself, and `resume` and `resumed` once the queue
|
|
19
|
+
* is down to half or the session ends; a final is never dropped for a slow sink. The transcriber's `speech_start`
|
|
20
|
+
* and `speech_end` reach the detector as voice activity, as the orchestrator gives them. The session ends once, for the first
|
|
21
|
+
* {@link ListenEndReason}; it closes the transcriber and leaves the transport open, since the transport is the
|
|
22
|
+
* caller's. A transport error ends it with `transport_failed` and the error in `ended`. Its transport listeners
|
|
23
|
+
* are removed on every end. An empty detector turn uses the accumulated STT finals and their timing.
|
|
24
|
+
*
|
|
25
|
+
* @param transport - Where the audio comes from: the session listens for its `audio`, `close` and `error`.
|
|
26
|
+
* @param sink - Where the turns go; it assigns each turn's number and id.
|
|
27
|
+
* @param overrides - The transcriber, the run and the session's options.
|
|
28
|
+
* @returns The session, listening.
|
|
29
|
+
* @throws {Error} When the transcriber's first session fails to open.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const session = await startListenSession(transport, sink, {
|
|
34
|
+
* streamingSTT: new DeepgramStreamingSTT({ apiKey: process.env.DEEPGRAM_API_KEY! }),
|
|
35
|
+
* runId: 'run-1',
|
|
36
|
+
* });
|
|
37
|
+
* session.on('ended', ({ reason }: { reason: ListenEndReason }) => console.log(`listening ended: ${reason}`));
|
|
38
|
+
* await session.close('stopped');
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export async function startListenSession(transport, sink, overrides) {
|
|
42
|
+
const stt = overrides.reconnect === false ? overrides.streamingSTT : new ReconnectingSTT(overrides.streamingSTT, typeof overrides.reconnect === 'object' ? overrides.reconnect : {});
|
|
43
|
+
const sttSession = await stt.startSession(overrides.sttConfig);
|
|
44
|
+
const detector = overrides.endpointDetector;
|
|
45
|
+
const queueLimit = overrides.sinkQueueLimit ?? 8;
|
|
46
|
+
const drainMs = overrides.drainMs ?? 250;
|
|
47
|
+
const emitter = new EventEmitter();
|
|
48
|
+
let state = 'listening';
|
|
49
|
+
let turns = 0;
|
|
50
|
+
let dropped = 0;
|
|
51
|
+
let reconnects = 0;
|
|
52
|
+
let paused = false;
|
|
53
|
+
let sinkFailed = false;
|
|
54
|
+
const pending = [];
|
|
55
|
+
const finals = [];
|
|
56
|
+
let speechEnded = false;
|
|
57
|
+
let writing = Promise.resolve();
|
|
58
|
+
let endPromise;
|
|
59
|
+
const accepting = () => state === 'listening' || state === 'draining';
|
|
60
|
+
const resume = () => {
|
|
61
|
+
if (!paused)
|
|
62
|
+
return;
|
|
63
|
+
paused = false;
|
|
64
|
+
transport.emit('resume');
|
|
65
|
+
emitter.emit('resumed');
|
|
66
|
+
};
|
|
67
|
+
const drainDetector = async () => {
|
|
68
|
+
if (!detector || finals.length === 0)
|
|
69
|
+
return;
|
|
70
|
+
await new Promise((resolve) => {
|
|
71
|
+
const done = () => {
|
|
72
|
+
clearTimeout(timer);
|
|
73
|
+
detector.off('turn_complete', done);
|
|
74
|
+
resolve();
|
|
75
|
+
};
|
|
76
|
+
// One timer tick lets a detector scheduled by the synthetic speech_end
|
|
77
|
+
// below emit at its bound before the fallback removes its listener.
|
|
78
|
+
const timer = setTimeout(done, (detector.turnCompletionTimeoutMs ?? 3250) + 1);
|
|
79
|
+
detector.on('turn_complete', done);
|
|
80
|
+
// A provider need not report speech_end when flushed. End the input so
|
|
81
|
+
// the detector can start its silence timer, without restarting a pending one.
|
|
82
|
+
if (!speechEnded)
|
|
83
|
+
detector.pushVadEvent({ type: 'speech_end', timestamp: Date.now(), source: 'stt' });
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
/** One end for every path. The writer calls it with `fromWriter` and never waits for its own chain. */
|
|
87
|
+
const end = (reason, error, fromWriter = false) => {
|
|
88
|
+
if (endPromise)
|
|
89
|
+
return endPromise;
|
|
90
|
+
// Reserve the end before cleanup emits resume: its listeners may call close again.
|
|
91
|
+
let resolveEnd = () => { };
|
|
92
|
+
let rejectEnd = () => { };
|
|
93
|
+
endPromise = new Promise((resolve, reject) => { resolveEnd = resolve; rejectEnd = reject; });
|
|
94
|
+
void (async () => {
|
|
95
|
+
if (reason === 'stopped') {
|
|
96
|
+
// the transcriber is flushed and its last finals are still written
|
|
97
|
+
state = 'draining';
|
|
98
|
+
try {
|
|
99
|
+
await sttSession.flush();
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// the transcriber is gone; nothing to drain
|
|
103
|
+
}
|
|
104
|
+
await new Promise((r) => setTimeout(r, drainMs));
|
|
105
|
+
await drainDetector();
|
|
106
|
+
}
|
|
107
|
+
state = 'ending';
|
|
108
|
+
transport.off('audio', onAudio);
|
|
109
|
+
transport.off('close', onTransportClose);
|
|
110
|
+
detector?.off('turn_complete', onTurnComplete);
|
|
111
|
+
finals.length = 0;
|
|
112
|
+
if (reason === 'purged')
|
|
113
|
+
pending.length = 0;
|
|
114
|
+
resume();
|
|
115
|
+
sttSession.close();
|
|
116
|
+
detector?.reset();
|
|
117
|
+
if (!fromWriter)
|
|
118
|
+
await writing;
|
|
119
|
+
transport.off('error', onTransportError);
|
|
120
|
+
state = 'ended';
|
|
121
|
+
emitter.emit('ended', error ? { reason, error } : { reason });
|
|
122
|
+
})().then(resolveEnd, rejectEnd);
|
|
123
|
+
return endPromise;
|
|
124
|
+
};
|
|
125
|
+
const write = (text, event) => {
|
|
126
|
+
if (!accepting() || sinkFailed)
|
|
127
|
+
return;
|
|
128
|
+
const turn = { runId: overrides.runId, at: Date.now(), text, startMs: event.startMs, endMs: event.endMs, speaker: overrides.speaker?.(event) };
|
|
129
|
+
pending.push(turn);
|
|
130
|
+
if (pending.length >= queueLimit && !paused) {
|
|
131
|
+
paused = true;
|
|
132
|
+
transport.emit('pause');
|
|
133
|
+
emitter.emit('paused');
|
|
134
|
+
}
|
|
135
|
+
writing = writing.then(async () => {
|
|
136
|
+
const next = pending.shift();
|
|
137
|
+
if (!next || sinkFailed)
|
|
138
|
+
return;
|
|
139
|
+
try {
|
|
140
|
+
const stored = await sink.appendNext(next);
|
|
141
|
+
if (stored) {
|
|
142
|
+
turns += 1;
|
|
143
|
+
emitter.emit('turn', stored);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
sinkFailed = true;
|
|
148
|
+
pending.length = 0;
|
|
149
|
+
void end('sink_failed', err instanceof Error ? err : new Error(String(err)), true);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (paused && pending.length < Math.ceil(queueLimit / 2)) {
|
|
153
|
+
resume();
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
const onAudio = (frame) => {
|
|
158
|
+
if (state !== 'listening')
|
|
159
|
+
return;
|
|
160
|
+
if (paused)
|
|
161
|
+
dropped += 1; // the transport was asked to pause; a frame that still comes is counted, and the transcriber keeps its own buffer
|
|
162
|
+
sttSession.pushAudio(frame);
|
|
163
|
+
};
|
|
164
|
+
const onTransportClose = () => {
|
|
165
|
+
void end('transport_closed');
|
|
166
|
+
};
|
|
167
|
+
const onTransportError = (error) => {
|
|
168
|
+
void end('transport_failed', error);
|
|
169
|
+
};
|
|
170
|
+
const onTurnComplete = (turn) => {
|
|
171
|
+
if (!accepting())
|
|
172
|
+
return;
|
|
173
|
+
const accumulated = finals.splice(0);
|
|
174
|
+
if (!turn.transcript.trim()) {
|
|
175
|
+
const text = accumulated.map((event) => event.text).filter(Boolean).join(' ');
|
|
176
|
+
if (text)
|
|
177
|
+
write(text, {
|
|
178
|
+
text, confidence: accumulated[accumulated.length - 1].confidence,
|
|
179
|
+
words: accumulated.flatMap((event) => event.words), isFinal: true,
|
|
180
|
+
startMs: accumulated[0].startMs, endMs: accumulated[accumulated.length - 1].endMs,
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
// a detector turn has its text and confidence, and no audio boundaries of its own
|
|
185
|
+
write(turn.transcript, { text: turn.transcript, confidence: turn.confidence, words: [], isFinal: true, durationMs: turn.durationMs });
|
|
186
|
+
};
|
|
187
|
+
sttSession.on('transcript', (event) => {
|
|
188
|
+
if (!accepting())
|
|
189
|
+
return;
|
|
190
|
+
if (detector) {
|
|
191
|
+
if (event.isFinal)
|
|
192
|
+
finals.push(event);
|
|
193
|
+
detector.pushTranscript(event);
|
|
194
|
+
if (!event.isFinal)
|
|
195
|
+
emitter.emit('interim', event);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (event.isFinal)
|
|
199
|
+
write(event.text, event);
|
|
200
|
+
else
|
|
201
|
+
emitter.emit('interim', event);
|
|
202
|
+
});
|
|
203
|
+
const onVad = (event) => {
|
|
204
|
+
if (!accepting())
|
|
205
|
+
return;
|
|
206
|
+
if (event.type === 'speech_start')
|
|
207
|
+
speechEnded = false;
|
|
208
|
+
else if (event.type === 'speech_end')
|
|
209
|
+
speechEnded = true;
|
|
210
|
+
detector?.pushVadEvent(event);
|
|
211
|
+
};
|
|
212
|
+
sttSession.on('vad', onVad);
|
|
213
|
+
// the transcriber's own speech events reach the detector as voice activity, as the orchestrator gives them
|
|
214
|
+
sttSession.on('speech_start', () => onVad({ type: 'speech_start', timestamp: Date.now(), source: 'stt' }));
|
|
215
|
+
sttSession.on('speech_end', () => onVad({ type: 'speech_end', timestamp: Date.now(), source: 'stt' }));
|
|
216
|
+
sttSession.on('stt:reconnected', (e) => {
|
|
217
|
+
reconnects += 1;
|
|
218
|
+
emitter.emit('stt:reconnected', e);
|
|
219
|
+
});
|
|
220
|
+
sttSession.on('stt:gap', (e) => emitter.emit('stt:gap', e));
|
|
221
|
+
sttSession.on('error', (err) => {
|
|
222
|
+
if (state === 'listening')
|
|
223
|
+
void end('stt_failed', err);
|
|
224
|
+
});
|
|
225
|
+
sttSession.on('close', () => {
|
|
226
|
+
if (state === 'listening')
|
|
227
|
+
void end('stt_failed', new Error('the transcriber closed'));
|
|
228
|
+
});
|
|
229
|
+
detector?.on('turn_complete', onTurnComplete);
|
|
230
|
+
transport.on('audio', onAudio);
|
|
231
|
+
transport.on('close', onTransportClose);
|
|
232
|
+
transport.on('error', onTransportError);
|
|
233
|
+
const session = Object.assign(emitter, {
|
|
234
|
+
runId: overrides.runId,
|
|
235
|
+
transport,
|
|
236
|
+
stats: () => ({ turns, dropped, reconnects }),
|
|
237
|
+
close: (reason = 'stopped') => end(reason),
|
|
238
|
+
});
|
|
239
|
+
Object.defineProperty(session, 'state', { get: () => state, enumerable: true });
|
|
240
|
+
return session;
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=ListenSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListenSession.js","sourceRoot":"","sources":["../../../src/io/voice-pipeline/ListenSession.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { IStreamingSTT, StreamingSTTConfig, StreamingSTTSession } from './types.js';
|
|
2
|
+
/** Options of {@link ReconnectingSTT}. */
|
|
3
|
+
export interface ReconnectingSTTOptions {
|
|
4
|
+
/** How much audio is kept for replay. Default 3000. */
|
|
5
|
+
ringBufferCapacityMs?: number;
|
|
6
|
+
/** Replays below this are skipped. Default 400. */
|
|
7
|
+
minReplayMs?: number;
|
|
8
|
+
/** Attempts allowed in any sixty seconds before the session gives up. Default 3. */
|
|
9
|
+
maxAttemptsPerMinute?: number;
|
|
10
|
+
/** Frames queued while a reconnect runs; beyond it the oldest are dropped and counted. Default 2000 ms. */
|
|
11
|
+
queueCapacityMs?: number;
|
|
12
|
+
/** Milliseconds now, for the attempt window and the gap's length. Default `Date.now`. */
|
|
13
|
+
clock?: () => number;
|
|
14
|
+
}
|
|
15
|
+
/** Payload of a session's `stt:reconnected`: a new session of the provider took over. */
|
|
16
|
+
export interface SttReconnectedEvent {
|
|
17
|
+
/** The attempt's number among the attempts of the last sixty seconds, from 1. */
|
|
18
|
+
attempt: number;
|
|
19
|
+
/** Milliseconds of buffered audio replayed into the new session; 0 when there was less than `minReplayMs`. */
|
|
20
|
+
replayedMs: number;
|
|
21
|
+
}
|
|
22
|
+
/** Payload of a session's `stt:gap`, emitted right after `stt:reconnected`. */
|
|
23
|
+
export interface SttGapEvent {
|
|
24
|
+
/** The attempt's number, as in {@link SttReconnectedEvent}. */
|
|
25
|
+
attempt: number;
|
|
26
|
+
/**
|
|
27
|
+
* Milliseconds the reconnect took, by the options' clock. The audio pushed in that time was queued for the new
|
|
28
|
+
* session, less the oldest frames a full queue dropped (the session's `droppedFrames`).
|
|
29
|
+
*/
|
|
30
|
+
lostMs: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* An {@link IStreamingSTT} over one provider whose session is reconnected.
|
|
34
|
+
*
|
|
35
|
+
* An `error` or `close` of the provider's session that the caller did not ask
|
|
36
|
+
* for opens a new session of the same provider, at most
|
|
37
|
+
* `maxAttemptsPerMinute` times in any sixty seconds. The new session hears the
|
|
38
|
+
* buffered audio first (the last `ringBufferCapacityMs`, when there is at least
|
|
39
|
+
* `minReplayMs` of it), then the frames pushed while it opened, then live
|
|
40
|
+
* audio. Its `startMs` and `endMs` are moved onto one timeline, the audio
|
|
41
|
+
* pushed since the session began, and a final that repeats one already
|
|
42
|
+
* emitted over the same audio is dropped. Only finals with finite start and end
|
|
43
|
+
* bounds and a positive duration enter the dedupe history; others pass through.
|
|
44
|
+
* Queue overflow leaves a gap after the replay, preserving the original times
|
|
45
|
+
* of both replayed and retained audio. Each reconnect emits
|
|
46
|
+
* `stt:reconnected` ({@link SttReconnectedEvent}) and `stt:gap`
|
|
47
|
+
* ({@link SttGapEvent}). Past the cap the session emits `error`, then `close`.
|
|
48
|
+
*
|
|
49
|
+
* The session forwards `transcript`, `vad`, `speech_start`, `speech_end`,
|
|
50
|
+
* `usage` and `warning` from the provider's sessions; `usage` comes from every
|
|
51
|
+
* one of them, a replaced one too, since a session reports its audio as it
|
|
52
|
+
* closes. `flush()` during a reconnect waits for the replacement, replay and
|
|
53
|
+
* queued audio before flushing it. A close during that flush, or after it with
|
|
54
|
+
* no further provider activity or pushed audio, ends the stream without a
|
|
55
|
+
* reconnect. Activity after a completed flush makes a later close a failure.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const stt = new ReconnectingSTT(new DeepgramStreamingSTT({ apiKey: process.env.DEEPGRAM_API_KEY! }));
|
|
60
|
+
* const session = await stt.startSession({ language: 'en-US' });
|
|
61
|
+
* session.on('stt:gap', ({ lostMs }: SttGapEvent) => console.log(`the transcriber was away for ${lostMs} ms`));
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare class ReconnectingSTT implements IStreamingSTT {
|
|
65
|
+
private readonly inner;
|
|
66
|
+
/** `reconnecting:` followed by the inner provider's id. */
|
|
67
|
+
readonly providerId: string;
|
|
68
|
+
private readonly capacityMs;
|
|
69
|
+
private readonly minReplayMs;
|
|
70
|
+
private readonly maxAttempts;
|
|
71
|
+
private readonly queueCapacityMs;
|
|
72
|
+
private readonly clock;
|
|
73
|
+
/**
|
|
74
|
+
* @param inner - The provider each session opens, again on every reconnect.
|
|
75
|
+
* @param options - The replay buffer, the attempt cap, the queue and the clock.
|
|
76
|
+
*/
|
|
77
|
+
constructor(inner: IStreamingSTT, options?: ReconnectingSTTOptions);
|
|
78
|
+
/** Whether the inner provider has a session open. */
|
|
79
|
+
get isStreaming(): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Opens a session of the inner provider behind a session that reconnects it.
|
|
82
|
+
*
|
|
83
|
+
* @param config - Passed to the inner provider for the first session and for every reconnect.
|
|
84
|
+
* @returns The session, with a read-only `droppedFrames`: the queued frames dropped during reconnects so far.
|
|
85
|
+
* @throws {Error} When the first session fails to open; a session that fails to open on a reconnect is retried
|
|
86
|
+
* within the cap.
|
|
87
|
+
*/
|
|
88
|
+
startSession(config?: StreamingSTTConfig): Promise<StreamingSTTSession>;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=ReconnectingSTT.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReconnectingSTT.d.ts","sourceRoot":"","sources":["../../../src/io/voice-pipeline/ReconnectingSTT.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAc,aAAa,EAAE,kBAAkB,EAAE,mBAAmB,EAAmB,MAAM,YAAY,CAAC;AAEtH,0CAA0C;AAC1C,MAAM,WAAW,sBAAsB;IACrC,uDAAuD;IACvD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,2GAA2G;IAC3G,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yFAAyF;IACzF,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,yFAAyF;AACzF,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,8GAA8G;IAC9G,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,eAAgB,YAAW,aAAa;IAavC,OAAO,CAAC,QAAQ,CAAC,KAAK;IAZlC,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC;;;OAGG;gBAC0B,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,sBAA2B;IASvF,qDAAqD;IACrD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;;;;;;OAOG;IACG,YAAY,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CA6N9E"}
|