@livekit/agents 0.4.6 → 0.5.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.
Files changed (197) hide show
  1. package/README.md +17 -0
  2. package/dist/audio.cjs +77 -0
  3. package/dist/audio.cjs.map +1 -0
  4. package/dist/audio.js +48 -37
  5. package/dist/audio.js.map +1 -1
  6. package/dist/cli.cjs +131 -0
  7. package/dist/cli.cjs.map +1 -0
  8. package/dist/cli.js +96 -122
  9. package/dist/cli.js.map +1 -1
  10. package/dist/generator.cjs +36 -0
  11. package/dist/generator.cjs.map +1 -0
  12. package/dist/generator.js +8 -22
  13. package/dist/generator.js.map +1 -1
  14. package/dist/http_server.cjs +72 -0
  15. package/dist/http_server.cjs.map +1 -0
  16. package/dist/http_server.d.ts +1 -1
  17. package/dist/http_server.js +44 -47
  18. package/dist/http_server.js.map +1 -1
  19. package/dist/index.cjs +78 -0
  20. package/dist/index.cjs.map +1 -0
  21. package/dist/index.js +26 -28
  22. package/dist/index.js.map +1 -1
  23. package/dist/ipc/job_executor.cjs +33 -0
  24. package/dist/ipc/job_executor.cjs.map +1 -0
  25. package/dist/ipc/job_executor.js +7 -4
  26. package/dist/ipc/job_executor.js.map +1 -1
  27. package/dist/ipc/job_main.cjs +147 -0
  28. package/dist/ipc/job_main.cjs.map +1 -0
  29. package/dist/ipc/job_main.d.ts +1 -1
  30. package/dist/ipc/job_main.js +103 -103
  31. package/dist/ipc/job_main.js.map +1 -1
  32. package/dist/ipc/message.cjs +17 -0
  33. package/dist/ipc/message.cjs.map +1 -0
  34. package/dist/ipc/message.js +0 -1
  35. package/dist/ipc/message.js.map +1 -1
  36. package/dist/ipc/proc_job_executor.cjs +174 -0
  37. package/dist/ipc/proc_job_executor.cjs.map +1 -0
  38. package/dist/ipc/proc_job_executor.js +130 -126
  39. package/dist/ipc/proc_job_executor.js.map +1 -1
  40. package/dist/ipc/proc_pool.cjs +126 -0
  41. package/dist/ipc/proc_pool.cjs.map +1 -0
  42. package/dist/ipc/proc_pool.js +93 -96
  43. package/dist/ipc/proc_pool.js.map +1 -1
  44. package/dist/job.cjs +230 -0
  45. package/dist/job.cjs.map +1 -0
  46. package/dist/job.js +195 -198
  47. package/dist/job.js.map +1 -1
  48. package/dist/llm/chat_context.cjs +131 -0
  49. package/dist/llm/chat_context.cjs.map +1 -0
  50. package/dist/llm/chat_context.js +98 -86
  51. package/dist/llm/chat_context.js.map +1 -1
  52. package/dist/llm/function_context.cjs +103 -0
  53. package/dist/llm/function_context.cjs.map +1 -0
  54. package/dist/llm/function_context.js +72 -81
  55. package/dist/llm/function_context.js.map +1 -1
  56. package/dist/llm/function_context.test.cjs +218 -0
  57. package/dist/llm/function_context.test.cjs.map +1 -0
  58. package/dist/llm/function_context.test.js +209 -210
  59. package/dist/llm/function_context.test.js.map +1 -1
  60. package/dist/llm/index.cjs +43 -0
  61. package/dist/llm/index.cjs.map +1 -0
  62. package/dist/llm/index.js +22 -6
  63. package/dist/llm/index.js.map +1 -1
  64. package/dist/llm/llm.cjs +76 -0
  65. package/dist/llm/llm.cjs.map +1 -0
  66. package/dist/llm/llm.js +48 -42
  67. package/dist/llm/llm.js.map +1 -1
  68. package/dist/log.cjs +57 -0
  69. package/dist/log.cjs.map +1 -0
  70. package/dist/log.js +27 -26
  71. package/dist/log.js.map +1 -1
  72. package/dist/multimodal/agent_playout.cjs +228 -0
  73. package/dist/multimodal/agent_playout.cjs.map +1 -0
  74. package/dist/multimodal/agent_playout.d.ts +1 -1
  75. package/dist/multimodal/agent_playout.js +193 -180
  76. package/dist/multimodal/agent_playout.js.map +1 -1
  77. package/dist/multimodal/index.cjs +25 -0
  78. package/dist/multimodal/index.cjs.map +1 -0
  79. package/dist/multimodal/index.js +2 -5
  80. package/dist/multimodal/index.js.map +1 -1
  81. package/dist/multimodal/multimodal_agent.cjs +404 -0
  82. package/dist/multimodal/multimodal_agent.cjs.map +1 -0
  83. package/dist/multimodal/multimodal_agent.d.ts +1 -1
  84. package/dist/multimodal/multimodal_agent.js +351 -330
  85. package/dist/multimodal/multimodal_agent.js.map +1 -1
  86. package/dist/pipeline/agent_output.cjs +172 -0
  87. package/dist/pipeline/agent_output.cjs.map +1 -0
  88. package/dist/pipeline/agent_output.js +136 -138
  89. package/dist/pipeline/agent_output.js.map +1 -1
  90. package/dist/pipeline/agent_playout.cjs +169 -0
  91. package/dist/pipeline/agent_playout.cjs.map +1 -0
  92. package/dist/pipeline/agent_playout.js +126 -136
  93. package/dist/pipeline/agent_playout.js.map +1 -1
  94. package/dist/pipeline/human_input.cjs +158 -0
  95. package/dist/pipeline/human_input.cjs.map +1 -0
  96. package/dist/pipeline/human_input.js +124 -125
  97. package/dist/pipeline/human_input.js.map +1 -1
  98. package/dist/pipeline/index.cjs +31 -0
  99. package/dist/pipeline/index.cjs.map +1 -0
  100. package/dist/pipeline/index.js +8 -4
  101. package/dist/pipeline/index.js.map +1 -1
  102. package/dist/pipeline/pipeline_agent.cjs +642 -0
  103. package/dist/pipeline/pipeline_agent.cjs.map +1 -0
  104. package/dist/pipeline/pipeline_agent.js +595 -651
  105. package/dist/pipeline/pipeline_agent.js.map +1 -1
  106. package/dist/pipeline/speech_handle.cjs +128 -0
  107. package/dist/pipeline/speech_handle.cjs.map +1 -0
  108. package/dist/pipeline/speech_handle.js +102 -100
  109. package/dist/pipeline/speech_handle.js.map +1 -1
  110. package/dist/plugin.cjs +46 -0
  111. package/dist/plugin.cjs.map +1 -0
  112. package/dist/plugin.js +20 -20
  113. package/dist/plugin.js.map +1 -1
  114. package/dist/stt/index.cjs +38 -0
  115. package/dist/stt/index.cjs.map +1 -0
  116. package/dist/stt/index.js +13 -5
  117. package/dist/stt/index.js.map +1 -1
  118. package/dist/stt/stream_adapter.cjs +87 -0
  119. package/dist/stt/stream_adapter.cjs.map +1 -0
  120. package/dist/stt/stream_adapter.js +58 -55
  121. package/dist/stt/stream_adapter.js.map +1 -1
  122. package/dist/stt/stt.cjs +98 -0
  123. package/dist/stt/stt.cjs.map +1 -0
  124. package/dist/stt/stt.js +63 -98
  125. package/dist/stt/stt.js.map +1 -1
  126. package/dist/tokenize/basic/basic.cjs +98 -0
  127. package/dist/tokenize/basic/basic.cjs.map +1 -0
  128. package/dist/tokenize/basic/basic.js +56 -45
  129. package/dist/tokenize/basic/basic.js.map +1 -1
  130. package/dist/tokenize/basic/hyphenator.cjs +425 -0
  131. package/dist/tokenize/basic/hyphenator.cjs.map +1 -0
  132. package/dist/tokenize/basic/hyphenator.js +66 -82
  133. package/dist/tokenize/basic/hyphenator.js.map +1 -1
  134. package/dist/tokenize/basic/index.cjs +35 -0
  135. package/dist/tokenize/basic/index.cjs.map +1 -0
  136. package/dist/tokenize/basic/index.js +7 -4
  137. package/dist/tokenize/basic/index.js.map +1 -1
  138. package/dist/tokenize/basic/paragraph.cjs +57 -0
  139. package/dist/tokenize/basic/paragraph.cjs.map +1 -0
  140. package/dist/tokenize/basic/paragraph.js +30 -35
  141. package/dist/tokenize/basic/paragraph.js.map +1 -1
  142. package/dist/tokenize/basic/sentence.cjs +83 -0
  143. package/dist/tokenize/basic/sentence.cjs.map +1 -0
  144. package/dist/tokenize/basic/sentence.js +56 -57
  145. package/dist/tokenize/basic/sentence.js.map +1 -1
  146. package/dist/tokenize/basic/word.cjs +44 -0
  147. package/dist/tokenize/basic/word.cjs.map +1 -0
  148. package/dist/tokenize/basic/word.js +17 -20
  149. package/dist/tokenize/basic/word.js.map +1 -1
  150. package/dist/tokenize/index.cjs +55 -0
  151. package/dist/tokenize/index.cjs.map +1 -0
  152. package/dist/tokenize/index.js +18 -7
  153. package/dist/tokenize/index.js.map +1 -1
  154. package/dist/tokenize/token_stream.cjs +164 -0
  155. package/dist/tokenize/token_stream.cjs.map +1 -0
  156. package/dist/tokenize/token_stream.js +133 -139
  157. package/dist/tokenize/token_stream.js.map +1 -1
  158. package/dist/tokenize/tokenizer.cjs +184 -0
  159. package/dist/tokenize/tokenizer.cjs.map +1 -0
  160. package/dist/tokenize/tokenizer.js +138 -99
  161. package/dist/tokenize/tokenizer.js.map +1 -1
  162. package/dist/transcription.cjs +131 -0
  163. package/dist/transcription.cjs.map +1 -0
  164. package/dist/transcription.js +99 -96
  165. package/dist/transcription.js.map +1 -1
  166. package/dist/tts/index.cjs +38 -0
  167. package/dist/tts/index.cjs.map +1 -0
  168. package/dist/tts/index.js +13 -5
  169. package/dist/tts/index.js.map +1 -1
  170. package/dist/tts/stream_adapter.cjs +78 -0
  171. package/dist/tts/stream_adapter.cjs.map +1 -0
  172. package/dist/tts/stream_adapter.js +50 -47
  173. package/dist/tts/stream_adapter.js.map +1 -1
  174. package/dist/tts/tts.cjs +127 -0
  175. package/dist/tts/tts.cjs.map +1 -0
  176. package/dist/tts/tts.js +90 -120
  177. package/dist/tts/tts.js.map +1 -1
  178. package/dist/utils.cjs +284 -0
  179. package/dist/utils.cjs.map +1 -0
  180. package/dist/utils.js +242 -247
  181. package/dist/utils.js.map +1 -1
  182. package/dist/vad.cjs +92 -0
  183. package/dist/vad.cjs.map +1 -0
  184. package/dist/vad.js +57 -52
  185. package/dist/vad.js.map +1 -1
  186. package/dist/version.cjs +29 -0
  187. package/dist/version.cjs.map +1 -0
  188. package/dist/version.js +4 -4
  189. package/dist/version.js.map +1 -1
  190. package/dist/worker.cjs +576 -0
  191. package/dist/worker.cjs.map +1 -0
  192. package/dist/worker.d.ts +1 -1
  193. package/dist/worker.js +511 -484
  194. package/dist/worker.js.map +1 -1
  195. package/package.json +18 -8
  196. package/src/ipc/job_main.ts +66 -64
  197. package/src/pipeline/pipeline_agent.ts +23 -23
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var agent_playout_exports = {};
20
+ __export(agent_playout_exports, {
21
+ AgentPlayout: () => AgentPlayout,
22
+ PlayoutHandle: () => PlayoutHandle,
23
+ proto: () => proto
24
+ });
25
+ module.exports = __toCommonJS(agent_playout_exports);
26
+ var import_node_events = require("node:events");
27
+ var import_audio = require("../audio.cjs");
28
+ var import_utils = require("../utils.cjs");
29
+ const proto = {};
30
+ class PlayoutHandle extends import_node_events.EventEmitter {
31
+ #audioSource;
32
+ #sampleRate;
33
+ #itemId;
34
+ #contentIndex;
35
+ /** @internal */
36
+ transcriptionFwd;
37
+ /** @internal */
38
+ doneFut;
39
+ /** @internal */
40
+ intFut;
41
+ /** @internal */
42
+ #interrupted;
43
+ /** @internal */
44
+ pushedDuration;
45
+ /** @internal */
46
+ totalPlayedTime;
47
+ // Set when playout is done
48
+ constructor(audioSource, sampleRate, itemId, contentIndex, transcriptionFwd) {
49
+ super();
50
+ this.#audioSource = audioSource;
51
+ this.#sampleRate = sampleRate;
52
+ this.#itemId = itemId;
53
+ this.#contentIndex = contentIndex;
54
+ this.transcriptionFwd = transcriptionFwd;
55
+ this.doneFut = new import_utils.Future();
56
+ this.intFut = new import_utils.Future();
57
+ this.#interrupted = false;
58
+ this.pushedDuration = 0;
59
+ this.totalPlayedTime = void 0;
60
+ }
61
+ get itemId() {
62
+ return this.#itemId;
63
+ }
64
+ get audioSamples() {
65
+ if (this.totalPlayedTime !== void 0) {
66
+ return Math.floor(this.totalPlayedTime * this.#sampleRate);
67
+ }
68
+ return Math.floor(
69
+ (this.pushedDuration - this.#audioSource.queuedDuration) * (this.#sampleRate / 1e3)
70
+ );
71
+ }
72
+ get textChars() {
73
+ return this.transcriptionFwd.currentCharacterIndex;
74
+ }
75
+ get contentIndex() {
76
+ return this.#contentIndex;
77
+ }
78
+ get interrupted() {
79
+ return this.#interrupted;
80
+ }
81
+ get done() {
82
+ return this.doneFut.done || this.#interrupted;
83
+ }
84
+ interrupt() {
85
+ if (this.doneFut.done) return;
86
+ this.intFut.resolve();
87
+ this.#interrupted = true;
88
+ }
89
+ }
90
+ class AgentPlayout extends import_node_events.EventEmitter {
91
+ #audioSource;
92
+ #playoutTask;
93
+ #sampleRate;
94
+ #numChannels;
95
+ #inFrameSize;
96
+ #outFrameSize;
97
+ constructor(audioSource, sampleRate, numChannels, inFrameSize, outFrameSize) {
98
+ super();
99
+ this.#audioSource = audioSource;
100
+ this.#playoutTask = null;
101
+ this.#sampleRate = sampleRate;
102
+ this.#numChannels = numChannels;
103
+ this.#inFrameSize = inFrameSize;
104
+ this.#outFrameSize = outFrameSize;
105
+ }
106
+ play(itemId, contentIndex, transcriptionFwd, textStream, audioStream) {
107
+ const handle = new PlayoutHandle(
108
+ this.#audioSource,
109
+ this.#sampleRate,
110
+ itemId,
111
+ contentIndex,
112
+ transcriptionFwd
113
+ );
114
+ this.#playoutTask = this.#makePlayoutTask(this.#playoutTask, handle, textStream, audioStream);
115
+ return handle;
116
+ }
117
+ #makePlayoutTask(oldTask, handle, textStream, audioStream) {
118
+ return new import_utils.CancellablePromise((resolve, reject, onCancel) => {
119
+ let cancelled = false;
120
+ onCancel(() => {
121
+ cancelled = true;
122
+ });
123
+ (async () => {
124
+ try {
125
+ if (oldTask) {
126
+ await (0, import_utils.gracefullyCancel)(oldTask);
127
+ }
128
+ let firstFrame = true;
129
+ const readText = () => new import_utils.CancellablePromise((resolveText, rejectText, onCancelText) => {
130
+ let cancelledText = false;
131
+ onCancelText(() => {
132
+ cancelledText = true;
133
+ });
134
+ (async () => {
135
+ try {
136
+ for await (const text of textStream) {
137
+ if (cancelledText || cancelled) {
138
+ break;
139
+ }
140
+ handle.transcriptionFwd.pushText(text);
141
+ }
142
+ resolveText();
143
+ } catch (error) {
144
+ rejectText(error);
145
+ }
146
+ })();
147
+ });
148
+ const capture = () => new import_utils.CancellablePromise((resolveCapture, rejectCapture, onCancelCapture) => {
149
+ let cancelledCapture = false;
150
+ onCancelCapture(() => {
151
+ cancelledCapture = true;
152
+ });
153
+ (async () => {
154
+ try {
155
+ const samplesPerChannel = this.#outFrameSize;
156
+ const bstream = new import_audio.AudioByteStream(
157
+ this.#sampleRate,
158
+ this.#numChannels,
159
+ samplesPerChannel
160
+ );
161
+ for await (const frame of audioStream) {
162
+ if (cancelledCapture || cancelled) {
163
+ break;
164
+ }
165
+ if (firstFrame) {
166
+ handle.transcriptionFwd.start();
167
+ this.emit("playout_started");
168
+ firstFrame = false;
169
+ }
170
+ handle.transcriptionFwd.pushAudio(frame);
171
+ for (const f of bstream.write(frame.data.buffer)) {
172
+ handle.pushedDuration += f.samplesPerChannel / f.sampleRate * 1e3;
173
+ await this.#audioSource.captureFrame(f);
174
+ }
175
+ }
176
+ if (!cancelledCapture && !cancelled) {
177
+ for (const f of bstream.flush()) {
178
+ handle.pushedDuration += f.samplesPerChannel / f.sampleRate * 1e3;
179
+ await this.#audioSource.captureFrame(f);
180
+ }
181
+ handle.transcriptionFwd.markAudioComplete();
182
+ await this.#audioSource.waitForPlayout();
183
+ }
184
+ resolveCapture();
185
+ } catch (error) {
186
+ rejectCapture(error);
187
+ }
188
+ })();
189
+ });
190
+ const readTextTask = readText();
191
+ const captureTask = capture();
192
+ try {
193
+ await Promise.race([captureTask, handle.intFut.await]);
194
+ } finally {
195
+ if (!captureTask.isCancelled) {
196
+ await (0, import_utils.gracefullyCancel)(captureTask);
197
+ }
198
+ handle.totalPlayedTime = handle.pushedDuration - this.#audioSource.queuedDuration;
199
+ if (handle.interrupted || captureTask.error) {
200
+ this.#audioSource.clearQueue();
201
+ }
202
+ if (!readTextTask.isCancelled) {
203
+ await (0, import_utils.gracefullyCancel)(readTextTask);
204
+ }
205
+ if (!firstFrame) {
206
+ if (!handle.interrupted) {
207
+ handle.transcriptionFwd.markTextComplete();
208
+ }
209
+ this.emit("playout_stopped", handle.interrupted);
210
+ }
211
+ handle.doneFut.resolve();
212
+ await handle.transcriptionFwd.close(handle.interrupted);
213
+ }
214
+ resolve();
215
+ } catch (error) {
216
+ reject(error);
217
+ }
218
+ })();
219
+ });
220
+ }
221
+ }
222
+ // Annotate the CommonJS export names for ESM import in node:
223
+ 0 && (module.exports = {
224
+ AgentPlayout,
225
+ PlayoutHandle,
226
+ proto
227
+ });
228
+ //# sourceMappingURL=agent_playout.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/multimodal/agent_playout.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { type AudioSource } from '@livekit/rtc-node';\nimport { EventEmitter } from 'node:events';\nimport { AudioByteStream } from '../audio.js';\nimport type { TranscriptionForwarder } from '../transcription.js';\nimport { type AsyncIterableQueue, CancellablePromise, Future, gracefullyCancel } from '../utils.js';\n\nexport const proto = {};\n\nexport class PlayoutHandle extends EventEmitter {\n #audioSource: AudioSource;\n #sampleRate: number;\n #itemId: string;\n #contentIndex: number;\n /** @internal */\n transcriptionFwd: TranscriptionForwarder;\n /** @internal */\n doneFut: Future;\n /** @internal */\n intFut: Future;\n /** @internal */\n #interrupted: boolean;\n /** @internal */\n pushedDuration: number;\n /** @internal */\n totalPlayedTime: number | undefined; // Set when playout is done\n\n constructor(\n audioSource: AudioSource,\n sampleRate: number,\n itemId: string,\n contentIndex: number,\n transcriptionFwd: TranscriptionForwarder,\n ) {\n super();\n this.#audioSource = audioSource;\n this.#sampleRate = sampleRate;\n this.#itemId = itemId;\n this.#contentIndex = contentIndex;\n this.transcriptionFwd = transcriptionFwd;\n this.doneFut = new Future();\n this.intFut = new Future();\n this.#interrupted = false;\n this.pushedDuration = 0;\n this.totalPlayedTime = undefined;\n }\n\n get itemId(): string {\n return this.#itemId;\n }\n\n get audioSamples(): number {\n if (this.totalPlayedTime !== undefined) {\n return Math.floor(this.totalPlayedTime * this.#sampleRate);\n }\n\n return Math.floor(\n (this.pushedDuration - this.#audioSource.queuedDuration) * (this.#sampleRate / 1000),\n );\n }\n\n get textChars(): number {\n return this.transcriptionFwd.currentCharacterIndex;\n }\n\n get contentIndex(): number {\n return this.#contentIndex;\n }\n\n get interrupted(): boolean {\n return this.#interrupted;\n }\n\n get done(): boolean {\n return this.doneFut.done || this.#interrupted;\n }\n\n interrupt() {\n if (this.doneFut.done) return;\n this.intFut.resolve();\n this.#interrupted = true;\n }\n}\n\nexport class AgentPlayout extends EventEmitter {\n #audioSource: AudioSource;\n #playoutTask: CancellablePromise<void> | null;\n #sampleRate: number;\n #numChannels: number;\n #inFrameSize: number;\n #outFrameSize: number;\n constructor(\n audioSource: AudioSource,\n sampleRate: number,\n numChannels: number,\n inFrameSize: number,\n outFrameSize: number,\n ) {\n super();\n this.#audioSource = audioSource;\n this.#playoutTask = null;\n this.#sampleRate = sampleRate;\n this.#numChannels = numChannels;\n this.#inFrameSize = inFrameSize;\n this.#outFrameSize = outFrameSize;\n }\n\n play(\n itemId: string,\n contentIndex: number,\n transcriptionFwd: TranscriptionForwarder,\n textStream: AsyncIterableQueue<string>,\n audioStream: AsyncIterableQueue<AudioFrame>,\n ): PlayoutHandle {\n const handle = new PlayoutHandle(\n this.#audioSource,\n this.#sampleRate,\n itemId,\n contentIndex,\n transcriptionFwd,\n );\n this.#playoutTask = this.#makePlayoutTask(this.#playoutTask, handle, textStream, audioStream);\n return handle;\n }\n\n #makePlayoutTask(\n oldTask: CancellablePromise<void> | null,\n handle: PlayoutHandle,\n textStream: AsyncIterableQueue<string>,\n audioStream: AsyncIterableQueue<AudioFrame>,\n ): CancellablePromise<void> {\n return new CancellablePromise<void>((resolve, reject, onCancel) => {\n let cancelled = false;\n onCancel(() => {\n cancelled = true;\n });\n\n (async () => {\n try {\n if (oldTask) {\n await gracefullyCancel(oldTask);\n }\n\n let firstFrame = true;\n\n const readText = () =>\n new CancellablePromise<void>((resolveText, rejectText, onCancelText) => {\n let cancelledText = false;\n onCancelText(() => {\n cancelledText = true;\n });\n\n (async () => {\n try {\n for await (const text of textStream) {\n if (cancelledText || cancelled) {\n break;\n }\n handle.transcriptionFwd.pushText(text);\n }\n resolveText();\n } catch (error) {\n rejectText(error);\n }\n })();\n });\n\n const capture = () =>\n new CancellablePromise<void>((resolveCapture, rejectCapture, onCancelCapture) => {\n let cancelledCapture = false;\n onCancelCapture(() => {\n cancelledCapture = true;\n });\n\n (async () => {\n try {\n const samplesPerChannel = this.#outFrameSize;\n const bstream = new AudioByteStream(\n this.#sampleRate,\n this.#numChannels,\n samplesPerChannel,\n );\n\n for await (const frame of audioStream) {\n if (cancelledCapture || cancelled) {\n break;\n }\n if (firstFrame) {\n handle.transcriptionFwd.start();\n this.emit('playout_started');\n firstFrame = false;\n }\n\n handle.transcriptionFwd.pushAudio(frame);\n\n for (const f of bstream.write(frame.data.buffer)) {\n handle.pushedDuration += (f.samplesPerChannel / f.sampleRate) * 1000;\n await this.#audioSource.captureFrame(f);\n }\n }\n\n if (!cancelledCapture && !cancelled) {\n for (const f of bstream.flush()) {\n handle.pushedDuration += (f.samplesPerChannel / f.sampleRate) * 1000;\n await this.#audioSource.captureFrame(f);\n }\n\n handle.transcriptionFwd.markAudioComplete();\n\n await this.#audioSource.waitForPlayout();\n }\n\n resolveCapture();\n } catch (error) {\n rejectCapture(error);\n }\n })();\n });\n\n const readTextTask = readText();\n const captureTask = capture();\n\n try {\n await Promise.race([captureTask, handle.intFut.await]);\n } finally {\n if (!captureTask.isCancelled) {\n await gracefullyCancel(captureTask);\n }\n\n handle.totalPlayedTime = handle.pushedDuration - this.#audioSource.queuedDuration;\n\n if (handle.interrupted || captureTask.error) {\n this.#audioSource.clearQueue(); // make sure to remove any queued frames\n }\n\n if (!readTextTask.isCancelled) {\n await gracefullyCancel(readTextTask);\n }\n\n if (!firstFrame) {\n if (!handle.interrupted) {\n handle.transcriptionFwd.markTextComplete();\n }\n\n this.emit('playout_stopped', handle.interrupted);\n }\n\n handle.doneFut.resolve();\n await handle.transcriptionFwd.close(handle.interrupted);\n }\n\n resolve();\n } catch (error) {\n reject(error);\n }\n })();\n });\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- /// <reference types="node" />
1
+ /// <reference types="node" resolution-mode="require"/>
2
2
  import type { AudioFrame } from '@livekit/rtc-node';
3
3
  import { type AudioSource } from '@livekit/rtc-node';
4
4
  import { EventEmitter } from 'node:events';
@@ -1,189 +1,202 @@
1
- import { EventEmitter } from 'node:events';
2
- import { AudioByteStream } from '../audio.js';
3
- import { CancellablePromise, Future, gracefullyCancel } from '../utils.js';
4
- export const proto = {};
5
- export class PlayoutHandle extends EventEmitter {
6
- #audioSource;
7
- #sampleRate;
8
- #itemId;
9
- #contentIndex;
10
- /** @internal */
11
- transcriptionFwd;
12
- /** @internal */
13
- doneFut;
14
- /** @internal */
15
- intFut;
16
- /** @internal */
17
- #interrupted;
18
- /** @internal */
19
- pushedDuration;
20
- /** @internal */
21
- totalPlayedTime; // Set when playout is done
22
- constructor(audioSource, sampleRate, itemId, contentIndex, transcriptionFwd) {
23
- super();
24
- this.#audioSource = audioSource;
25
- this.#sampleRate = sampleRate;
26
- this.#itemId = itemId;
27
- this.#contentIndex = contentIndex;
28
- this.transcriptionFwd = transcriptionFwd;
29
- this.doneFut = new Future();
30
- this.intFut = new Future();
31
- this.#interrupted = false;
32
- this.pushedDuration = 0;
33
- this.totalPlayedTime = undefined;
34
- }
35
- get itemId() {
36
- return this.#itemId;
37
- }
38
- get audioSamples() {
39
- if (this.totalPlayedTime !== undefined) {
40
- return Math.floor(this.totalPlayedTime * this.#sampleRate);
41
- }
42
- return Math.floor((this.pushedDuration - this.#audioSource.queuedDuration) * (this.#sampleRate / 1000));
43
- }
44
- get textChars() {
45
- return this.transcriptionFwd.currentCharacterIndex;
46
- }
47
- get contentIndex() {
48
- return this.#contentIndex;
49
- }
50
- get interrupted() {
51
- return this.#interrupted;
52
- }
53
- get done() {
54
- return this.doneFut.done || this.#interrupted;
55
- }
56
- interrupt() {
57
- if (this.doneFut.done)
58
- return;
59
- this.intFut.resolve();
60
- this.#interrupted = true;
1
+ import { EventEmitter } from "node:events";
2
+ import { AudioByteStream } from "../audio.js";
3
+ import { CancellablePromise, Future, gracefullyCancel } from "../utils.js";
4
+ const proto = {};
5
+ class PlayoutHandle extends EventEmitter {
6
+ #audioSource;
7
+ #sampleRate;
8
+ #itemId;
9
+ #contentIndex;
10
+ /** @internal */
11
+ transcriptionFwd;
12
+ /** @internal */
13
+ doneFut;
14
+ /** @internal */
15
+ intFut;
16
+ /** @internal */
17
+ #interrupted;
18
+ /** @internal */
19
+ pushedDuration;
20
+ /** @internal */
21
+ totalPlayedTime;
22
+ // Set when playout is done
23
+ constructor(audioSource, sampleRate, itemId, contentIndex, transcriptionFwd) {
24
+ super();
25
+ this.#audioSource = audioSource;
26
+ this.#sampleRate = sampleRate;
27
+ this.#itemId = itemId;
28
+ this.#contentIndex = contentIndex;
29
+ this.transcriptionFwd = transcriptionFwd;
30
+ this.doneFut = new Future();
31
+ this.intFut = new Future();
32
+ this.#interrupted = false;
33
+ this.pushedDuration = 0;
34
+ this.totalPlayedTime = void 0;
35
+ }
36
+ get itemId() {
37
+ return this.#itemId;
38
+ }
39
+ get audioSamples() {
40
+ if (this.totalPlayedTime !== void 0) {
41
+ return Math.floor(this.totalPlayedTime * this.#sampleRate);
61
42
  }
43
+ return Math.floor(
44
+ (this.pushedDuration - this.#audioSource.queuedDuration) * (this.#sampleRate / 1e3)
45
+ );
46
+ }
47
+ get textChars() {
48
+ return this.transcriptionFwd.currentCharacterIndex;
49
+ }
50
+ get contentIndex() {
51
+ return this.#contentIndex;
52
+ }
53
+ get interrupted() {
54
+ return this.#interrupted;
55
+ }
56
+ get done() {
57
+ return this.doneFut.done || this.#interrupted;
58
+ }
59
+ interrupt() {
60
+ if (this.doneFut.done) return;
61
+ this.intFut.resolve();
62
+ this.#interrupted = true;
63
+ }
62
64
  }
63
- export class AgentPlayout extends EventEmitter {
64
- #audioSource;
65
- #playoutTask;
66
- #sampleRate;
67
- #numChannels;
68
- #inFrameSize;
69
- #outFrameSize;
70
- constructor(audioSource, sampleRate, numChannels, inFrameSize, outFrameSize) {
71
- super();
72
- this.#audioSource = audioSource;
73
- this.#playoutTask = null;
74
- this.#sampleRate = sampleRate;
75
- this.#numChannels = numChannels;
76
- this.#inFrameSize = inFrameSize;
77
- this.#outFrameSize = outFrameSize;
78
- }
79
- play(itemId, contentIndex, transcriptionFwd, textStream, audioStream) {
80
- const handle = new PlayoutHandle(this.#audioSource, this.#sampleRate, itemId, contentIndex, transcriptionFwd);
81
- this.#playoutTask = this.#makePlayoutTask(this.#playoutTask, handle, textStream, audioStream);
82
- return handle;
83
- }
84
- #makePlayoutTask(oldTask, handle, textStream, audioStream) {
85
- return new CancellablePromise((resolve, reject, onCancel) => {
86
- let cancelled = false;
87
- onCancel(() => {
88
- cancelled = true;
65
+ class AgentPlayout extends EventEmitter {
66
+ #audioSource;
67
+ #playoutTask;
68
+ #sampleRate;
69
+ #numChannels;
70
+ #inFrameSize;
71
+ #outFrameSize;
72
+ constructor(audioSource, sampleRate, numChannels, inFrameSize, outFrameSize) {
73
+ super();
74
+ this.#audioSource = audioSource;
75
+ this.#playoutTask = null;
76
+ this.#sampleRate = sampleRate;
77
+ this.#numChannels = numChannels;
78
+ this.#inFrameSize = inFrameSize;
79
+ this.#outFrameSize = outFrameSize;
80
+ }
81
+ play(itemId, contentIndex, transcriptionFwd, textStream, audioStream) {
82
+ const handle = new PlayoutHandle(
83
+ this.#audioSource,
84
+ this.#sampleRate,
85
+ itemId,
86
+ contentIndex,
87
+ transcriptionFwd
88
+ );
89
+ this.#playoutTask = this.#makePlayoutTask(this.#playoutTask, handle, textStream, audioStream);
90
+ return handle;
91
+ }
92
+ #makePlayoutTask(oldTask, handle, textStream, audioStream) {
93
+ return new CancellablePromise((resolve, reject, onCancel) => {
94
+ let cancelled = false;
95
+ onCancel(() => {
96
+ cancelled = true;
97
+ });
98
+ (async () => {
99
+ try {
100
+ if (oldTask) {
101
+ await gracefullyCancel(oldTask);
102
+ }
103
+ let firstFrame = true;
104
+ const readText = () => new CancellablePromise((resolveText, rejectText, onCancelText) => {
105
+ let cancelledText = false;
106
+ onCancelText(() => {
107
+ cancelledText = true;
108
+ });
109
+ (async () => {
110
+ try {
111
+ for await (const text of textStream) {
112
+ if (cancelledText || cancelled) {
113
+ break;
114
+ }
115
+ handle.transcriptionFwd.pushText(text);
116
+ }
117
+ resolveText();
118
+ } catch (error) {
119
+ rejectText(error);
120
+ }
121
+ })();
122
+ });
123
+ const capture = () => new CancellablePromise((resolveCapture, rejectCapture, onCancelCapture) => {
124
+ let cancelledCapture = false;
125
+ onCancelCapture(() => {
126
+ cancelledCapture = true;
89
127
  });
90
128
  (async () => {
91
- try {
92
- if (oldTask) {
93
- await gracefullyCancel(oldTask);
94
- }
95
- let firstFrame = true;
96
- const readText = () => new CancellablePromise((resolveText, rejectText, onCancelText) => {
97
- let cancelledText = false;
98
- onCancelText(() => {
99
- cancelledText = true;
100
- });
101
- (async () => {
102
- try {
103
- for await (const text of textStream) {
104
- if (cancelledText || cancelled) {
105
- break;
106
- }
107
- handle.transcriptionFwd.pushText(text);
108
- }
109
- resolveText();
110
- }
111
- catch (error) {
112
- rejectText(error);
113
- }
114
- })();
115
- });
116
- const capture = () => new CancellablePromise((resolveCapture, rejectCapture, onCancelCapture) => {
117
- let cancelledCapture = false;
118
- onCancelCapture(() => {
119
- cancelledCapture = true;
120
- });
121
- (async () => {
122
- try {
123
- const samplesPerChannel = this.#outFrameSize;
124
- const bstream = new AudioByteStream(this.#sampleRate, this.#numChannels, samplesPerChannel);
125
- for await (const frame of audioStream) {
126
- if (cancelledCapture || cancelled) {
127
- break;
128
- }
129
- if (firstFrame) {
130
- handle.transcriptionFwd.start();
131
- this.emit('playout_started');
132
- firstFrame = false;
133
- }
134
- handle.transcriptionFwd.pushAudio(frame);
135
- for (const f of bstream.write(frame.data.buffer)) {
136
- handle.pushedDuration += (f.samplesPerChannel / f.sampleRate) * 1000;
137
- await this.#audioSource.captureFrame(f);
138
- }
139
- }
140
- if (!cancelledCapture && !cancelled) {
141
- for (const f of bstream.flush()) {
142
- handle.pushedDuration += (f.samplesPerChannel / f.sampleRate) * 1000;
143
- await this.#audioSource.captureFrame(f);
144
- }
145
- handle.transcriptionFwd.markAudioComplete();
146
- await this.#audioSource.waitForPlayout();
147
- }
148
- resolveCapture();
149
- }
150
- catch (error) {
151
- rejectCapture(error);
152
- }
153
- })();
154
- });
155
- const readTextTask = readText();
156
- const captureTask = capture();
157
- try {
158
- await Promise.race([captureTask, handle.intFut.await]);
159
- }
160
- finally {
161
- if (!captureTask.isCancelled) {
162
- await gracefullyCancel(captureTask);
163
- }
164
- handle.totalPlayedTime = handle.pushedDuration - this.#audioSource.queuedDuration;
165
- if (handle.interrupted || captureTask.error) {
166
- this.#audioSource.clearQueue(); // make sure to remove any queued frames
167
- }
168
- if (!readTextTask.isCancelled) {
169
- await gracefullyCancel(readTextTask);
170
- }
171
- if (!firstFrame) {
172
- if (!handle.interrupted) {
173
- handle.transcriptionFwd.markTextComplete();
174
- }
175
- this.emit('playout_stopped', handle.interrupted);
176
- }
177
- handle.doneFut.resolve();
178
- await handle.transcriptionFwd.close(handle.interrupted);
179
- }
180
- resolve();
129
+ try {
130
+ const samplesPerChannel = this.#outFrameSize;
131
+ const bstream = new AudioByteStream(
132
+ this.#sampleRate,
133
+ this.#numChannels,
134
+ samplesPerChannel
135
+ );
136
+ for await (const frame of audioStream) {
137
+ if (cancelledCapture || cancelled) {
138
+ break;
139
+ }
140
+ if (firstFrame) {
141
+ handle.transcriptionFwd.start();
142
+ this.emit("playout_started");
143
+ firstFrame = false;
144
+ }
145
+ handle.transcriptionFwd.pushAudio(frame);
146
+ for (const f of bstream.write(frame.data.buffer)) {
147
+ handle.pushedDuration += f.samplesPerChannel / f.sampleRate * 1e3;
148
+ await this.#audioSource.captureFrame(f);
149
+ }
181
150
  }
182
- catch (error) {
183
- reject(error);
151
+ if (!cancelledCapture && !cancelled) {
152
+ for (const f of bstream.flush()) {
153
+ handle.pushedDuration += f.samplesPerChannel / f.sampleRate * 1e3;
154
+ await this.#audioSource.captureFrame(f);
155
+ }
156
+ handle.transcriptionFwd.markAudioComplete();
157
+ await this.#audioSource.waitForPlayout();
184
158
  }
159
+ resolveCapture();
160
+ } catch (error) {
161
+ rejectCapture(error);
162
+ }
185
163
  })();
186
- });
187
- }
164
+ });
165
+ const readTextTask = readText();
166
+ const captureTask = capture();
167
+ try {
168
+ await Promise.race([captureTask, handle.intFut.await]);
169
+ } finally {
170
+ if (!captureTask.isCancelled) {
171
+ await gracefullyCancel(captureTask);
172
+ }
173
+ handle.totalPlayedTime = handle.pushedDuration - this.#audioSource.queuedDuration;
174
+ if (handle.interrupted || captureTask.error) {
175
+ this.#audioSource.clearQueue();
176
+ }
177
+ if (!readTextTask.isCancelled) {
178
+ await gracefullyCancel(readTextTask);
179
+ }
180
+ if (!firstFrame) {
181
+ if (!handle.interrupted) {
182
+ handle.transcriptionFwd.markTextComplete();
183
+ }
184
+ this.emit("playout_stopped", handle.interrupted);
185
+ }
186
+ handle.doneFut.resolve();
187
+ await handle.transcriptionFwd.close(handle.interrupted);
188
+ }
189
+ resolve();
190
+ } catch (error) {
191
+ reject(error);
192
+ }
193
+ })();
194
+ });
195
+ }
188
196
  }
197
+ export {
198
+ AgentPlayout,
199
+ PlayoutHandle,
200
+ proto
201
+ };
189
202
  //# sourceMappingURL=agent_playout.js.map