@livekit/agents 1.1.0 → 1.2.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 (942) hide show
  1. package/dist/audio.cjs +89 -3
  2. package/dist/audio.cjs.map +1 -1
  3. package/dist/audio.d.cts +36 -1
  4. package/dist/audio.d.ts +36 -1
  5. package/dist/audio.d.ts.map +1 -1
  6. package/dist/audio.js +76 -2
  7. package/dist/audio.js.map +1 -1
  8. package/dist/beta/index.cjs +29 -0
  9. package/dist/beta/index.cjs.map +1 -0
  10. package/dist/beta/index.d.cts +2 -0
  11. package/dist/beta/index.d.ts +2 -0
  12. package/dist/beta/index.d.ts.map +1 -0
  13. package/dist/beta/index.js +7 -0
  14. package/dist/beta/index.js.map +1 -0
  15. package/dist/beta/workflows/index.cjs +29 -0
  16. package/dist/beta/workflows/index.cjs.map +1 -0
  17. package/dist/beta/workflows/index.d.cts +2 -0
  18. package/dist/beta/workflows/index.d.ts +2 -0
  19. package/dist/beta/workflows/index.d.ts.map +1 -0
  20. package/dist/beta/workflows/index.js +7 -0
  21. package/dist/beta/workflows/index.js.map +1 -0
  22. package/dist/beta/workflows/task_group.cjs +162 -0
  23. package/dist/beta/workflows/task_group.cjs.map +1 -0
  24. package/dist/beta/workflows/task_group.d.cts +32 -0
  25. package/dist/beta/workflows/task_group.d.ts +32 -0
  26. package/dist/beta/workflows/task_group.d.ts.map +1 -0
  27. package/dist/beta/workflows/task_group.js +138 -0
  28. package/dist/beta/workflows/task_group.js.map +1 -0
  29. package/dist/cli.cjs +44 -46
  30. package/dist/cli.cjs.map +1 -1
  31. package/dist/cli.d.cts +3 -3
  32. package/dist/cli.d.ts +3 -3
  33. package/dist/cli.d.ts.map +1 -1
  34. package/dist/cli.js +45 -47
  35. package/dist/cli.js.map +1 -1
  36. package/dist/connection_pool.cjs +242 -0
  37. package/dist/connection_pool.cjs.map +1 -0
  38. package/dist/connection_pool.d.cts +123 -0
  39. package/dist/connection_pool.d.ts +123 -0
  40. package/dist/connection_pool.d.ts.map +1 -0
  41. package/dist/connection_pool.js +218 -0
  42. package/dist/connection_pool.js.map +1 -0
  43. package/dist/connection_pool.test.cjs +256 -0
  44. package/dist/connection_pool.test.cjs.map +1 -0
  45. package/dist/connection_pool.test.js +255 -0
  46. package/dist/connection_pool.test.js.map +1 -0
  47. package/dist/constants.cjs +30 -0
  48. package/dist/constants.cjs.map +1 -1
  49. package/dist/constants.d.cts +10 -0
  50. package/dist/constants.d.ts +10 -0
  51. package/dist/constants.d.ts.map +1 -1
  52. package/dist/constants.js +20 -0
  53. package/dist/constants.js.map +1 -1
  54. package/dist/cpu.cjs +189 -0
  55. package/dist/cpu.cjs.map +1 -0
  56. package/dist/cpu.d.cts +24 -0
  57. package/dist/cpu.d.ts +24 -0
  58. package/dist/cpu.d.ts.map +1 -0
  59. package/dist/cpu.js +152 -0
  60. package/dist/cpu.js.map +1 -0
  61. package/dist/cpu.test.cjs +227 -0
  62. package/dist/cpu.test.cjs.map +1 -0
  63. package/dist/cpu.test.js +204 -0
  64. package/dist/cpu.test.js.map +1 -0
  65. package/dist/http_server.cjs +9 -6
  66. package/dist/http_server.cjs.map +1 -1
  67. package/dist/http_server.d.cts +5 -1
  68. package/dist/http_server.d.ts +5 -1
  69. package/dist/http_server.d.ts.map +1 -1
  70. package/dist/http_server.js +9 -6
  71. package/dist/http_server.js.map +1 -1
  72. package/dist/index.cjs +24 -9
  73. package/dist/index.cjs.map +1 -1
  74. package/dist/index.d.cts +15 -11
  75. package/dist/index.d.ts +15 -11
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +18 -9
  78. package/dist/index.js.map +1 -1
  79. package/dist/inference/api_protos.cjs +70 -2
  80. package/dist/inference/api_protos.cjs.map +1 -1
  81. package/dist/inference/api_protos.d.cts +373 -32
  82. package/dist/inference/api_protos.d.ts +373 -32
  83. package/dist/inference/api_protos.d.ts.map +1 -1
  84. package/dist/inference/api_protos.js +62 -2
  85. package/dist/inference/api_protos.js.map +1 -1
  86. package/dist/inference/index.cjs +8 -0
  87. package/dist/inference/index.cjs.map +1 -1
  88. package/dist/inference/index.d.cts +3 -4
  89. package/dist/inference/index.d.ts +3 -4
  90. package/dist/inference/index.d.ts.map +1 -1
  91. package/dist/inference/index.js +18 -3
  92. package/dist/inference/index.js.map +1 -1
  93. package/dist/inference/interruption/defaults.cjs +81 -0
  94. package/dist/inference/interruption/defaults.cjs.map +1 -0
  95. package/dist/inference/interruption/defaults.d.cts +19 -0
  96. package/dist/inference/interruption/defaults.d.ts +19 -0
  97. package/dist/inference/interruption/defaults.d.ts.map +1 -0
  98. package/dist/inference/interruption/defaults.js +46 -0
  99. package/dist/inference/interruption/defaults.js.map +1 -0
  100. package/dist/inference/interruption/errors.cjs +44 -0
  101. package/dist/inference/interruption/errors.cjs.map +1 -0
  102. package/dist/inference/interruption/errors.d.cts +12 -0
  103. package/dist/inference/interruption/errors.d.ts +12 -0
  104. package/dist/inference/interruption/errors.d.ts.map +1 -0
  105. package/dist/inference/interruption/errors.js +20 -0
  106. package/dist/inference/interruption/errors.js.map +1 -0
  107. package/dist/inference/interruption/http_transport.cjs +163 -0
  108. package/dist/inference/interruption/http_transport.cjs.map +1 -0
  109. package/dist/inference/interruption/http_transport.d.cts +63 -0
  110. package/dist/inference/interruption/http_transport.d.ts +63 -0
  111. package/dist/inference/interruption/http_transport.d.ts.map +1 -0
  112. package/dist/inference/interruption/http_transport.js +137 -0
  113. package/dist/inference/interruption/http_transport.js.map +1 -0
  114. package/dist/inference/interruption/interruption_cache_entry.cjs +58 -0
  115. package/dist/inference/interruption/interruption_cache_entry.cjs.map +1 -0
  116. package/dist/inference/interruption/interruption_cache_entry.d.cts +30 -0
  117. package/dist/inference/interruption/interruption_cache_entry.d.ts +30 -0
  118. package/dist/inference/interruption/interruption_cache_entry.d.ts.map +1 -0
  119. package/dist/inference/interruption/interruption_cache_entry.js +34 -0
  120. package/dist/inference/interruption/interruption_cache_entry.js.map +1 -0
  121. package/dist/inference/interruption/interruption_detector.cjs +198 -0
  122. package/dist/inference/interruption/interruption_detector.cjs.map +1 -0
  123. package/dist/inference/interruption/interruption_detector.d.cts +59 -0
  124. package/dist/inference/interruption/interruption_detector.d.ts +59 -0
  125. package/dist/inference/interruption/interruption_detector.d.ts.map +1 -0
  126. package/dist/inference/interruption/interruption_detector.js +164 -0
  127. package/dist/inference/interruption/interruption_detector.js.map +1 -0
  128. package/dist/inference/interruption/interruption_stream.cjs +368 -0
  129. package/dist/inference/interruption/interruption_stream.cjs.map +1 -0
  130. package/dist/inference/interruption/interruption_stream.d.cts +46 -0
  131. package/dist/inference/interruption/interruption_stream.d.ts +46 -0
  132. package/dist/inference/interruption/interruption_stream.d.ts.map +1 -0
  133. package/dist/inference/interruption/interruption_stream.js +344 -0
  134. package/dist/inference/interruption/interruption_stream.js.map +1 -0
  135. package/dist/inference/interruption/types.cjs +17 -0
  136. package/dist/inference/interruption/types.cjs.map +1 -0
  137. package/dist/inference/interruption/types.d.cts +66 -0
  138. package/dist/inference/interruption/types.d.ts +66 -0
  139. package/dist/inference/interruption/types.d.ts.map +1 -0
  140. package/dist/inference/interruption/types.js +1 -0
  141. package/dist/inference/interruption/types.js.map +1 -0
  142. package/dist/inference/interruption/utils.cjs +130 -0
  143. package/dist/inference/interruption/utils.cjs.map +1 -0
  144. package/dist/inference/interruption/utils.d.cts +41 -0
  145. package/dist/inference/interruption/utils.d.ts +41 -0
  146. package/dist/inference/interruption/utils.d.ts.map +1 -0
  147. package/dist/inference/interruption/utils.js +105 -0
  148. package/dist/inference/interruption/utils.js.map +1 -0
  149. package/dist/inference/interruption/utils.test.cjs +105 -0
  150. package/dist/inference/interruption/utils.test.cjs.map +1 -0
  151. package/dist/inference/interruption/utils.test.js +104 -0
  152. package/dist/inference/interruption/utils.test.js.map +1 -0
  153. package/dist/inference/interruption/ws_transport.cjs +342 -0
  154. package/dist/inference/interruption/ws_transport.cjs.map +1 -0
  155. package/dist/inference/interruption/ws_transport.d.cts +33 -0
  156. package/dist/inference/interruption/ws_transport.d.ts +33 -0
  157. package/dist/inference/interruption/ws_transport.d.ts.map +1 -0
  158. package/dist/inference/interruption/ws_transport.js +308 -0
  159. package/dist/inference/interruption/ws_transport.js.map +1 -0
  160. package/dist/inference/llm.cjs +106 -66
  161. package/dist/inference/llm.cjs.map +1 -1
  162. package/dist/inference/llm.d.cts +65 -43
  163. package/dist/inference/llm.d.ts +65 -43
  164. package/dist/inference/llm.d.ts.map +1 -1
  165. package/dist/inference/llm.js +100 -66
  166. package/dist/inference/llm.js.map +1 -1
  167. package/dist/inference/stt.cjs +319 -170
  168. package/dist/inference/stt.cjs.map +1 -1
  169. package/dist/inference/stt.d.cts +64 -15
  170. package/dist/inference/stt.d.ts +64 -15
  171. package/dist/inference/stt.d.ts.map +1 -1
  172. package/dist/inference/stt.js +319 -170
  173. package/dist/inference/stt.js.map +1 -1
  174. package/dist/inference/stt.test.cjs +218 -0
  175. package/dist/inference/stt.test.cjs.map +1 -0
  176. package/dist/inference/stt.test.js +217 -0
  177. package/dist/inference/stt.test.js.map +1 -0
  178. package/dist/inference/tts.cjs +249 -71
  179. package/dist/inference/tts.cjs.map +1 -1
  180. package/dist/inference/tts.d.cts +55 -16
  181. package/dist/inference/tts.d.ts +55 -16
  182. package/dist/inference/tts.d.ts.map +1 -1
  183. package/dist/inference/tts.js +249 -77
  184. package/dist/inference/tts.js.map +1 -1
  185. package/dist/inference/tts.test.cjs +233 -0
  186. package/dist/inference/tts.test.cjs.map +1 -0
  187. package/dist/inference/tts.test.js +232 -0
  188. package/dist/inference/tts.test.js.map +1 -0
  189. package/dist/inference/utils.cjs +26 -7
  190. package/dist/inference/utils.cjs.map +1 -1
  191. package/dist/inference/utils.d.cts +14 -1
  192. package/dist/inference/utils.d.ts +14 -1
  193. package/dist/inference/utils.d.ts.map +1 -1
  194. package/dist/inference/utils.js +18 -2
  195. package/dist/inference/utils.js.map +1 -1
  196. package/dist/ipc/inference_proc_executor.cjs +6 -3
  197. package/dist/ipc/inference_proc_executor.cjs.map +1 -1
  198. package/dist/ipc/inference_proc_executor.d.ts.map +1 -1
  199. package/dist/ipc/inference_proc_executor.js +6 -3
  200. package/dist/ipc/inference_proc_executor.js.map +1 -1
  201. package/dist/ipc/inference_proc_lazy_main.cjs +13 -1
  202. package/dist/ipc/inference_proc_lazy_main.cjs.map +1 -1
  203. package/dist/ipc/inference_proc_lazy_main.js +13 -1
  204. package/dist/ipc/inference_proc_lazy_main.js.map +1 -1
  205. package/dist/ipc/job_proc_executor.cjs +6 -1
  206. package/dist/ipc/job_proc_executor.cjs.map +1 -1
  207. package/dist/ipc/job_proc_executor.d.ts.map +1 -1
  208. package/dist/ipc/job_proc_executor.js +6 -1
  209. package/dist/ipc/job_proc_executor.js.map +1 -1
  210. package/dist/ipc/job_proc_lazy_main.cjs +89 -17
  211. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  212. package/dist/ipc/job_proc_lazy_main.js +68 -18
  213. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  214. package/dist/ipc/supervised_proc.cjs +34 -8
  215. package/dist/ipc/supervised_proc.cjs.map +1 -1
  216. package/dist/ipc/supervised_proc.d.cts +8 -0
  217. package/dist/ipc/supervised_proc.d.ts +8 -0
  218. package/dist/ipc/supervised_proc.d.ts.map +1 -1
  219. package/dist/ipc/supervised_proc.js +34 -8
  220. package/dist/ipc/supervised_proc.js.map +1 -1
  221. package/dist/ipc/supervised_proc.test.cjs +145 -0
  222. package/dist/ipc/supervised_proc.test.cjs.map +1 -0
  223. package/dist/ipc/supervised_proc.test.js +122 -0
  224. package/dist/ipc/supervised_proc.test.js.map +1 -0
  225. package/dist/job.cjs +109 -1
  226. package/dist/job.cjs.map +1 -1
  227. package/dist/job.d.cts +14 -0
  228. package/dist/job.d.ts +14 -0
  229. package/dist/job.d.ts.map +1 -1
  230. package/dist/job.js +99 -1
  231. package/dist/job.js.map +1 -1
  232. package/dist/language.cjs +394 -0
  233. package/dist/language.cjs.map +1 -0
  234. package/dist/language.d.cts +15 -0
  235. package/dist/language.d.ts +15 -0
  236. package/dist/language.d.ts.map +1 -0
  237. package/dist/language.js +363 -0
  238. package/dist/language.js.map +1 -0
  239. package/dist/language.test.cjs +43 -0
  240. package/dist/language.test.cjs.map +1 -0
  241. package/dist/language.test.js +49 -0
  242. package/dist/language.test.js.map +1 -0
  243. package/dist/llm/chat_context.cjs +274 -3
  244. package/dist/llm/chat_context.cjs.map +1 -1
  245. package/dist/llm/chat_context.d.cts +86 -2
  246. package/dist/llm/chat_context.d.ts +86 -2
  247. package/dist/llm/chat_context.d.ts.map +1 -1
  248. package/dist/llm/chat_context.js +273 -3
  249. package/dist/llm/chat_context.js.map +1 -1
  250. package/dist/llm/chat_context.test.cjs +574 -0
  251. package/dist/llm/chat_context.test.cjs.map +1 -1
  252. package/dist/llm/chat_context.test.js +574 -0
  253. package/dist/llm/chat_context.test.js.map +1 -1
  254. package/dist/llm/fallback_adapter.cjs +278 -0
  255. package/dist/llm/fallback_adapter.cjs.map +1 -0
  256. package/dist/llm/fallback_adapter.d.cts +73 -0
  257. package/dist/llm/fallback_adapter.d.ts +73 -0
  258. package/dist/llm/fallback_adapter.d.ts.map +1 -0
  259. package/dist/llm/fallback_adapter.js +254 -0
  260. package/dist/llm/fallback_adapter.js.map +1 -0
  261. package/dist/llm/fallback_adapter.test.cjs +176 -0
  262. package/dist/llm/fallback_adapter.test.cjs.map +1 -0
  263. package/dist/llm/fallback_adapter.test.js +175 -0
  264. package/dist/llm/fallback_adapter.test.js.map +1 -0
  265. package/dist/llm/index.cjs +9 -0
  266. package/dist/llm/index.cjs.map +1 -1
  267. package/dist/llm/index.d.cts +4 -3
  268. package/dist/llm/index.d.ts +4 -3
  269. package/dist/llm/index.d.ts.map +1 -1
  270. package/dist/llm/index.js +11 -1
  271. package/dist/llm/index.js.map +1 -1
  272. package/dist/llm/llm.cjs +65 -11
  273. package/dist/llm/llm.cjs.map +1 -1
  274. package/dist/llm/llm.d.cts +13 -2
  275. package/dist/llm/llm.d.ts +13 -2
  276. package/dist/llm/llm.d.ts.map +1 -1
  277. package/dist/llm/llm.js +65 -11
  278. package/dist/llm/llm.js.map +1 -1
  279. package/dist/llm/provider_format/google.cjs +6 -2
  280. package/dist/llm/provider_format/google.cjs.map +1 -1
  281. package/dist/llm/provider_format/google.d.cts +1 -1
  282. package/dist/llm/provider_format/google.d.ts +1 -1
  283. package/dist/llm/provider_format/google.d.ts.map +1 -1
  284. package/dist/llm/provider_format/google.js +6 -2
  285. package/dist/llm/provider_format/google.js.map +1 -1
  286. package/dist/llm/provider_format/google.test.cjs +48 -0
  287. package/dist/llm/provider_format/google.test.cjs.map +1 -1
  288. package/dist/llm/provider_format/google.test.js +54 -1
  289. package/dist/llm/provider_format/google.test.js.map +1 -1
  290. package/dist/llm/provider_format/index.cjs +2 -0
  291. package/dist/llm/provider_format/index.cjs.map +1 -1
  292. package/dist/llm/provider_format/index.d.cts +2 -2
  293. package/dist/llm/provider_format/index.d.ts +2 -2
  294. package/dist/llm/provider_format/index.d.ts.map +1 -1
  295. package/dist/llm/provider_format/index.js +6 -1
  296. package/dist/llm/provider_format/index.js.map +1 -1
  297. package/dist/llm/provider_format/openai.cjs +126 -24
  298. package/dist/llm/provider_format/openai.cjs.map +1 -1
  299. package/dist/llm/provider_format/openai.d.cts +1 -0
  300. package/dist/llm/provider_format/openai.d.ts +1 -0
  301. package/dist/llm/provider_format/openai.d.ts.map +1 -1
  302. package/dist/llm/provider_format/openai.js +124 -23
  303. package/dist/llm/provider_format/openai.js.map +1 -1
  304. package/dist/llm/provider_format/openai.test.cjs +393 -0
  305. package/dist/llm/provider_format/openai.test.cjs.map +1 -1
  306. package/dist/llm/provider_format/openai.test.js +400 -2
  307. package/dist/llm/provider_format/openai.test.js.map +1 -1
  308. package/dist/llm/provider_format/utils.cjs +5 -4
  309. package/dist/llm/provider_format/utils.cjs.map +1 -1
  310. package/dist/llm/provider_format/utils.d.ts.map +1 -1
  311. package/dist/llm/provider_format/utils.js +5 -4
  312. package/dist/llm/provider_format/utils.js.map +1 -1
  313. package/dist/llm/realtime.cjs +3 -0
  314. package/dist/llm/realtime.cjs.map +1 -1
  315. package/dist/llm/realtime.d.cts +15 -1
  316. package/dist/llm/realtime.d.ts +15 -1
  317. package/dist/llm/realtime.d.ts.map +1 -1
  318. package/dist/llm/realtime.js +3 -0
  319. package/dist/llm/realtime.js.map +1 -1
  320. package/dist/llm/remote_chat_context.cjs.map +1 -1
  321. package/dist/llm/remote_chat_context.d.cts +2 -0
  322. package/dist/llm/remote_chat_context.d.ts +2 -0
  323. package/dist/llm/remote_chat_context.d.ts.map +1 -1
  324. package/dist/llm/remote_chat_context.js.map +1 -1
  325. package/dist/llm/tool_context.cjs +50 -2
  326. package/dist/llm/tool_context.cjs.map +1 -1
  327. package/dist/llm/tool_context.d.cts +47 -11
  328. package/dist/llm/tool_context.d.ts +47 -11
  329. package/dist/llm/tool_context.d.ts.map +1 -1
  330. package/dist/llm/tool_context.js +48 -3
  331. package/dist/llm/tool_context.js.map +1 -1
  332. package/dist/llm/tool_context.test.cjs +197 -0
  333. package/dist/llm/tool_context.test.cjs.map +1 -1
  334. package/dist/llm/tool_context.test.js +175 -0
  335. package/dist/llm/tool_context.test.js.map +1 -1
  336. package/dist/llm/utils.cjs +18 -12
  337. package/dist/llm/utils.cjs.map +1 -1
  338. package/dist/llm/utils.d.cts +2 -3
  339. package/dist/llm/utils.d.ts +2 -3
  340. package/dist/llm/utils.d.ts.map +1 -1
  341. package/dist/llm/utils.js +18 -12
  342. package/dist/llm/utils.js.map +1 -1
  343. package/dist/llm/zod-utils.cjs +102 -0
  344. package/dist/llm/zod-utils.cjs.map +1 -0
  345. package/dist/llm/zod-utils.d.cts +65 -0
  346. package/dist/llm/zod-utils.d.ts +65 -0
  347. package/dist/llm/zod-utils.d.ts.map +1 -0
  348. package/dist/llm/zod-utils.js +64 -0
  349. package/dist/llm/zod-utils.js.map +1 -0
  350. package/dist/llm/zod-utils.test.cjs +472 -0
  351. package/dist/llm/zod-utils.test.cjs.map +1 -0
  352. package/dist/llm/zod-utils.test.js +455 -0
  353. package/dist/llm/zod-utils.test.js.map +1 -0
  354. package/dist/log.cjs +45 -14
  355. package/dist/log.cjs.map +1 -1
  356. package/dist/log.d.cts +8 -1
  357. package/dist/log.d.ts +8 -1
  358. package/dist/log.d.ts.map +1 -1
  359. package/dist/log.js +45 -15
  360. package/dist/log.js.map +1 -1
  361. package/dist/metrics/base.cjs.map +1 -1
  362. package/dist/metrics/base.d.cts +75 -19
  363. package/dist/metrics/base.d.ts +75 -19
  364. package/dist/metrics/base.d.ts.map +1 -1
  365. package/dist/metrics/index.cjs +5 -0
  366. package/dist/metrics/index.cjs.map +1 -1
  367. package/dist/metrics/index.d.cts +2 -1
  368. package/dist/metrics/index.d.ts +2 -1
  369. package/dist/metrics/index.d.ts.map +1 -1
  370. package/dist/metrics/index.js +6 -0
  371. package/dist/metrics/index.js.map +1 -1
  372. package/dist/metrics/model_usage.cjs +189 -0
  373. package/dist/metrics/model_usage.cjs.map +1 -0
  374. package/dist/metrics/model_usage.d.cts +92 -0
  375. package/dist/metrics/model_usage.d.ts +92 -0
  376. package/dist/metrics/model_usage.d.ts.map +1 -0
  377. package/dist/metrics/model_usage.js +164 -0
  378. package/dist/metrics/model_usage.js.map +1 -0
  379. package/dist/metrics/model_usage.test.cjs +474 -0
  380. package/dist/metrics/model_usage.test.cjs.map +1 -0
  381. package/dist/metrics/model_usage.test.js +476 -0
  382. package/dist/metrics/model_usage.test.js.map +1 -0
  383. package/dist/metrics/usage_collector.cjs +5 -2
  384. package/dist/metrics/usage_collector.cjs.map +1 -1
  385. package/dist/metrics/usage_collector.d.cts +10 -1
  386. package/dist/metrics/usage_collector.d.ts +10 -1
  387. package/dist/metrics/usage_collector.d.ts.map +1 -1
  388. package/dist/metrics/usage_collector.js +5 -2
  389. package/dist/metrics/usage_collector.js.map +1 -1
  390. package/dist/metrics/utils.cjs +23 -7
  391. package/dist/metrics/utils.cjs.map +1 -1
  392. package/dist/metrics/utils.d.ts.map +1 -1
  393. package/dist/metrics/utils.js +23 -7
  394. package/dist/metrics/utils.js.map +1 -1
  395. package/dist/stream/deferred_stream.cjs +31 -10
  396. package/dist/stream/deferred_stream.cjs.map +1 -1
  397. package/dist/stream/deferred_stream.d.cts +6 -1
  398. package/dist/stream/deferred_stream.d.ts +6 -1
  399. package/dist/stream/deferred_stream.d.ts.map +1 -1
  400. package/dist/stream/deferred_stream.js +31 -10
  401. package/dist/stream/deferred_stream.js.map +1 -1
  402. package/dist/stream/deferred_stream.test.cjs +2 -2
  403. package/dist/stream/deferred_stream.test.cjs.map +1 -1
  404. package/dist/stream/deferred_stream.test.js +2 -2
  405. package/dist/stream/deferred_stream.test.js.map +1 -1
  406. package/dist/stream/index.cjs +3 -0
  407. package/dist/stream/index.cjs.map +1 -1
  408. package/dist/stream/index.d.cts +1 -0
  409. package/dist/stream/index.d.ts +1 -0
  410. package/dist/stream/index.d.ts.map +1 -1
  411. package/dist/stream/index.js +2 -0
  412. package/dist/stream/index.js.map +1 -1
  413. package/dist/stream/multi_input_stream.cjs +139 -0
  414. package/dist/stream/multi_input_stream.cjs.map +1 -0
  415. package/dist/stream/multi_input_stream.d.cts +55 -0
  416. package/dist/stream/multi_input_stream.d.ts +55 -0
  417. package/dist/stream/multi_input_stream.d.ts.map +1 -0
  418. package/dist/stream/multi_input_stream.js +115 -0
  419. package/dist/stream/multi_input_stream.js.map +1 -0
  420. package/dist/stream/multi_input_stream.test.cjs +344 -0
  421. package/dist/stream/multi_input_stream.test.cjs.map +1 -0
  422. package/dist/stream/multi_input_stream.test.js +343 -0
  423. package/dist/stream/multi_input_stream.test.js.map +1 -0
  424. package/dist/stream/stream_channel.cjs +39 -1
  425. package/dist/stream/stream_channel.cjs.map +1 -1
  426. package/dist/stream/stream_channel.d.cts +5 -2
  427. package/dist/stream/stream_channel.d.ts +5 -2
  428. package/dist/stream/stream_channel.d.ts.map +1 -1
  429. package/dist/stream/stream_channel.js +39 -1
  430. package/dist/stream/stream_channel.js.map +1 -1
  431. package/dist/stream/stream_channel.test.cjs +27 -0
  432. package/dist/stream/stream_channel.test.cjs.map +1 -1
  433. package/dist/stream/stream_channel.test.js +27 -0
  434. package/dist/stream/stream_channel.test.js.map +1 -1
  435. package/dist/stt/stream_adapter.cjs +24 -9
  436. package/dist/stt/stream_adapter.cjs.map +1 -1
  437. package/dist/stt/stream_adapter.d.cts +7 -3
  438. package/dist/stt/stream_adapter.d.ts +7 -3
  439. package/dist/stt/stream_adapter.d.ts.map +1 -1
  440. package/dist/stt/stream_adapter.js +24 -9
  441. package/dist/stt/stream_adapter.js.map +1 -1
  442. package/dist/stt/stt.cjs +86 -19
  443. package/dist/stt/stt.cjs.map +1 -1
  444. package/dist/stt/stt.d.cts +60 -5
  445. package/dist/stt/stt.d.ts +60 -5
  446. package/dist/stt/stt.d.ts.map +1 -1
  447. package/dist/stt/stt.js +88 -21
  448. package/dist/stt/stt.js.map +1 -1
  449. package/dist/telemetry/index.cjs +72 -0
  450. package/dist/telemetry/index.cjs.map +1 -0
  451. package/dist/telemetry/index.d.cts +7 -0
  452. package/dist/telemetry/index.d.ts +7 -0
  453. package/dist/telemetry/index.d.ts.map +1 -0
  454. package/dist/telemetry/index.js +37 -0
  455. package/dist/telemetry/index.js.map +1 -0
  456. package/dist/telemetry/logging.cjs +65 -0
  457. package/dist/telemetry/logging.cjs.map +1 -0
  458. package/dist/telemetry/logging.d.cts +21 -0
  459. package/dist/telemetry/logging.d.ts +21 -0
  460. package/dist/telemetry/logging.d.ts.map +1 -0
  461. package/dist/telemetry/logging.js +40 -0
  462. package/dist/telemetry/logging.js.map +1 -0
  463. package/dist/telemetry/otel_http_exporter.cjs +166 -0
  464. package/dist/telemetry/otel_http_exporter.cjs.map +1 -0
  465. package/dist/telemetry/otel_http_exporter.d.cts +63 -0
  466. package/dist/telemetry/otel_http_exporter.d.ts +63 -0
  467. package/dist/telemetry/otel_http_exporter.d.ts.map +1 -0
  468. package/dist/telemetry/otel_http_exporter.js +142 -0
  469. package/dist/telemetry/otel_http_exporter.js.map +1 -0
  470. package/dist/telemetry/pino_otel_transport.cjs +217 -0
  471. package/dist/telemetry/pino_otel_transport.cjs.map +1 -0
  472. package/dist/telemetry/pino_otel_transport.d.cts +58 -0
  473. package/dist/telemetry/pino_otel_transport.d.ts +58 -0
  474. package/dist/telemetry/pino_otel_transport.d.ts.map +1 -0
  475. package/dist/telemetry/pino_otel_transport.js +189 -0
  476. package/dist/telemetry/pino_otel_transport.js.map +1 -0
  477. package/dist/telemetry/trace_types.cjs +233 -0
  478. package/dist/telemetry/trace_types.cjs.map +1 -0
  479. package/dist/telemetry/trace_types.d.cts +74 -0
  480. package/dist/telemetry/trace_types.d.ts +74 -0
  481. package/dist/telemetry/trace_types.d.ts.map +1 -0
  482. package/dist/telemetry/trace_types.js +141 -0
  483. package/dist/telemetry/trace_types.js.map +1 -0
  484. package/dist/telemetry/traces.cjs +484 -0
  485. package/dist/telemetry/traces.cjs.map +1 -0
  486. package/dist/telemetry/traces.d.cts +116 -0
  487. package/dist/telemetry/traces.d.ts +116 -0
  488. package/dist/telemetry/traces.d.ts.map +1 -0
  489. package/dist/telemetry/traces.js +449 -0
  490. package/dist/telemetry/traces.js.map +1 -0
  491. package/dist/telemetry/utils.cjs +86 -0
  492. package/dist/telemetry/utils.cjs.map +1 -0
  493. package/dist/telemetry/utils.d.cts +5 -0
  494. package/dist/telemetry/utils.d.ts +5 -0
  495. package/dist/telemetry/utils.d.ts.map +1 -0
  496. package/dist/telemetry/utils.js +51 -0
  497. package/dist/telemetry/utils.js.map +1 -0
  498. package/dist/tokenize/basic/sentence.cjs +3 -3
  499. package/dist/tokenize/basic/sentence.cjs.map +1 -1
  500. package/dist/tokenize/basic/sentence.js +3 -3
  501. package/dist/tokenize/basic/sentence.js.map +1 -1
  502. package/dist/tokenize/tokenizer.test.cjs +3 -1
  503. package/dist/tokenize/tokenizer.test.cjs.map +1 -1
  504. package/dist/tokenize/tokenizer.test.js +3 -1
  505. package/dist/tokenize/tokenizer.test.js.map +1 -1
  506. package/dist/transcription.cjs.map +1 -1
  507. package/dist/transcription.d.cts +6 -0
  508. package/dist/transcription.d.ts +6 -0
  509. package/dist/transcription.d.ts.map +1 -1
  510. package/dist/transcription.js.map +1 -1
  511. package/dist/tts/fallback_adapter.cjs +466 -0
  512. package/dist/tts/fallback_adapter.cjs.map +1 -0
  513. package/dist/tts/fallback_adapter.d.cts +110 -0
  514. package/dist/tts/fallback_adapter.d.ts +110 -0
  515. package/dist/tts/fallback_adapter.d.ts.map +1 -0
  516. package/dist/tts/fallback_adapter.js +442 -0
  517. package/dist/tts/fallback_adapter.js.map +1 -0
  518. package/dist/tts/index.cjs +3 -0
  519. package/dist/tts/index.cjs.map +1 -1
  520. package/dist/tts/index.d.cts +1 -0
  521. package/dist/tts/index.d.ts +1 -0
  522. package/dist/tts/index.d.ts.map +1 -1
  523. package/dist/tts/index.js +2 -0
  524. package/dist/tts/index.js.map +1 -1
  525. package/dist/tts/stream_adapter.cjs +25 -8
  526. package/dist/tts/stream_adapter.cjs.map +1 -1
  527. package/dist/tts/stream_adapter.d.cts +6 -3
  528. package/dist/tts/stream_adapter.d.ts +6 -3
  529. package/dist/tts/stream_adapter.d.ts.map +1 -1
  530. package/dist/tts/stream_adapter.js +25 -8
  531. package/dist/tts/stream_adapter.js.map +1 -1
  532. package/dist/tts/tts.cjs +189 -57
  533. package/dist/tts/tts.cjs.map +1 -1
  534. package/dist/tts/tts.d.cts +58 -6
  535. package/dist/tts/tts.d.ts +58 -6
  536. package/dist/tts/tts.d.ts.map +1 -1
  537. package/dist/tts/tts.js +191 -59
  538. package/dist/tts/tts.js.map +1 -1
  539. package/dist/types.cjs +24 -32
  540. package/dist/types.cjs.map +1 -1
  541. package/dist/types.d.cts +45 -10
  542. package/dist/types.d.ts +45 -10
  543. package/dist/types.d.ts.map +1 -1
  544. package/dist/types.js +20 -30
  545. package/dist/types.js.map +1 -1
  546. package/dist/utils.cjs +122 -26
  547. package/dist/utils.cjs.map +1 -1
  548. package/dist/utils.d.cts +41 -1
  549. package/dist/utils.d.ts +41 -1
  550. package/dist/utils.d.ts.map +1 -1
  551. package/dist/utils.js +117 -25
  552. package/dist/utils.js.map +1 -1
  553. package/dist/utils.test.cjs +73 -1
  554. package/dist/utils.test.cjs.map +1 -1
  555. package/dist/utils.test.js +74 -10
  556. package/dist/utils.test.js.map +1 -1
  557. package/dist/vad.cjs +35 -15
  558. package/dist/vad.cjs.map +1 -1
  559. package/dist/vad.d.cts +15 -5
  560. package/dist/vad.d.ts +15 -5
  561. package/dist/vad.d.ts.map +1 -1
  562. package/dist/vad.js +35 -15
  563. package/dist/vad.js.map +1 -1
  564. package/dist/version.cjs +1 -1
  565. package/dist/version.cjs.map +1 -1
  566. package/dist/version.d.cts +1 -1
  567. package/dist/version.d.ts +1 -1
  568. package/dist/version.d.ts.map +1 -1
  569. package/dist/version.js +1 -1
  570. package/dist/version.js.map +1 -1
  571. package/dist/voice/agent.cjs +258 -35
  572. package/dist/voice/agent.cjs.map +1 -1
  573. package/dist/voice/agent.d.cts +54 -13
  574. package/dist/voice/agent.d.ts +54 -13
  575. package/dist/voice/agent.d.ts.map +1 -1
  576. package/dist/voice/agent.js +254 -34
  577. package/dist/voice/agent.js.map +1 -1
  578. package/dist/voice/agent.test.cjs +314 -0
  579. package/dist/voice/agent.test.cjs.map +1 -1
  580. package/dist/voice/agent.test.js +316 -2
  581. package/dist/voice/agent.test.js.map +1 -1
  582. package/dist/voice/agent_activity.cjs +1116 -385
  583. package/dist/voice/agent_activity.cjs.map +1 -1
  584. package/dist/voice/agent_activity.d.cts +72 -11
  585. package/dist/voice/agent_activity.d.ts +72 -11
  586. package/dist/voice/agent_activity.d.ts.map +1 -1
  587. package/dist/voice/agent_activity.js +1119 -383
  588. package/dist/voice/agent_activity.js.map +1 -1
  589. package/dist/voice/agent_activity.test.cjs +135 -0
  590. package/dist/voice/agent_activity.test.cjs.map +1 -0
  591. package/dist/voice/agent_activity.test.js +134 -0
  592. package/dist/voice/agent_activity.test.js.map +1 -0
  593. package/dist/voice/agent_session.cjs +550 -90
  594. package/dist/voice/agent_session.cjs.map +1 -1
  595. package/dist/voice/agent_session.d.cts +185 -25
  596. package/dist/voice/agent_session.d.ts +185 -25
  597. package/dist/voice/agent_session.d.ts.map +1 -1
  598. package/dist/voice/agent_session.js +556 -91
  599. package/dist/voice/agent_session.js.map +1 -1
  600. package/dist/voice/audio_recognition.cjs +605 -46
  601. package/dist/voice/audio_recognition.cjs.map +1 -1
  602. package/dist/voice/audio_recognition.d.cts +96 -4
  603. package/dist/voice/audio_recognition.d.ts +96 -4
  604. package/dist/voice/audio_recognition.d.ts.map +1 -1
  605. package/dist/voice/audio_recognition.js +611 -47
  606. package/dist/voice/audio_recognition.js.map +1 -1
  607. package/dist/voice/audio_recognition_span.test.cjs +295 -0
  608. package/dist/voice/audio_recognition_span.test.cjs.map +1 -0
  609. package/dist/voice/audio_recognition_span.test.js +299 -0
  610. package/dist/voice/audio_recognition_span.test.js.map +1 -0
  611. package/dist/voice/avatar/datastream_io.cjs +7 -1
  612. package/dist/voice/avatar/datastream_io.cjs.map +1 -1
  613. package/dist/voice/avatar/datastream_io.d.cts +1 -0
  614. package/dist/voice/avatar/datastream_io.d.ts +1 -0
  615. package/dist/voice/avatar/datastream_io.d.ts.map +1 -1
  616. package/dist/voice/avatar/datastream_io.js +7 -1
  617. package/dist/voice/avatar/datastream_io.js.map +1 -1
  618. package/dist/voice/background_audio.cjs +367 -0
  619. package/dist/voice/background_audio.cjs.map +1 -0
  620. package/dist/voice/background_audio.d.cts +123 -0
  621. package/dist/voice/background_audio.d.ts +123 -0
  622. package/dist/voice/background_audio.d.ts.map +1 -0
  623. package/dist/voice/background_audio.js +343 -0
  624. package/dist/voice/background_audio.js.map +1 -0
  625. package/dist/voice/events.cjs +3 -0
  626. package/dist/voice/events.cjs.map +1 -1
  627. package/dist/voice/events.d.cts +16 -9
  628. package/dist/voice/events.d.ts +16 -9
  629. package/dist/voice/events.d.ts.map +1 -1
  630. package/dist/voice/events.js +3 -0
  631. package/dist/voice/events.js.map +1 -1
  632. package/dist/voice/generation.cjs +205 -41
  633. package/dist/voice/generation.cjs.map +1 -1
  634. package/dist/voice/generation.d.cts +21 -5
  635. package/dist/voice/generation.d.ts +21 -5
  636. package/dist/voice/generation.d.ts.map +1 -1
  637. package/dist/voice/generation.js +215 -43
  638. package/dist/voice/generation.js.map +1 -1
  639. package/dist/voice/generation_tools.test.cjs +236 -0
  640. package/dist/voice/generation_tools.test.cjs.map +1 -0
  641. package/dist/voice/generation_tools.test.js +235 -0
  642. package/dist/voice/generation_tools.test.js.map +1 -0
  643. package/dist/voice/index.cjs +33 -2
  644. package/dist/voice/index.cjs.map +1 -1
  645. package/dist/voice/index.d.cts +8 -2
  646. package/dist/voice/index.d.ts +8 -2
  647. package/dist/voice/index.d.ts.map +1 -1
  648. package/dist/voice/index.js +19 -2
  649. package/dist/voice/index.js.map +1 -1
  650. package/dist/voice/interruption_detection.test.cjs +114 -0
  651. package/dist/voice/interruption_detection.test.cjs.map +1 -0
  652. package/dist/voice/interruption_detection.test.js +113 -0
  653. package/dist/voice/interruption_detection.test.js.map +1 -0
  654. package/dist/voice/io.cjs +66 -6
  655. package/dist/voice/io.cjs.map +1 -1
  656. package/dist/voice/io.d.cts +67 -7
  657. package/dist/voice/io.d.ts +67 -7
  658. package/dist/voice/io.d.ts.map +1 -1
  659. package/dist/voice/io.js +62 -5
  660. package/dist/voice/io.js.map +1 -1
  661. package/dist/voice/recorder_io/index.cjs +23 -0
  662. package/dist/voice/recorder_io/index.cjs.map +1 -0
  663. package/dist/voice/recorder_io/index.d.cts +2 -0
  664. package/dist/voice/recorder_io/index.d.ts +2 -0
  665. package/dist/voice/recorder_io/index.d.ts.map +1 -0
  666. package/dist/voice/recorder_io/index.js +2 -0
  667. package/dist/voice/recorder_io/index.js.map +1 -0
  668. package/dist/voice/recorder_io/recorder_io.cjs +607 -0
  669. package/dist/voice/recorder_io/recorder_io.cjs.map +1 -0
  670. package/dist/voice/recorder_io/recorder_io.d.cts +106 -0
  671. package/dist/voice/recorder_io/recorder_io.d.ts +106 -0
  672. package/dist/voice/recorder_io/recorder_io.d.ts.map +1 -0
  673. package/dist/voice/recorder_io/recorder_io.js +573 -0
  674. package/dist/voice/recorder_io/recorder_io.js.map +1 -0
  675. package/dist/voice/remote_session.cjs +922 -0
  676. package/dist/voice/remote_session.cjs.map +1 -0
  677. package/dist/voice/remote_session.d.cts +108 -0
  678. package/dist/voice/remote_session.d.ts +108 -0
  679. package/dist/voice/remote_session.d.ts.map +1 -0
  680. package/dist/voice/remote_session.js +887 -0
  681. package/dist/voice/remote_session.js.map +1 -0
  682. package/dist/voice/report.cjs +88 -0
  683. package/dist/voice/report.cjs.map +1 -0
  684. package/dist/voice/report.d.cts +49 -0
  685. package/dist/voice/report.d.ts +49 -0
  686. package/dist/voice/report.d.ts.map +1 -0
  687. package/dist/voice/report.js +63 -0
  688. package/dist/voice/report.js.map +1 -0
  689. package/dist/voice/report.test.cjs +121 -0
  690. package/dist/voice/report.test.cjs.map +1 -0
  691. package/dist/voice/report.test.js +120 -0
  692. package/dist/voice/report.test.js.map +1 -0
  693. package/dist/voice/room_io/_input.cjs +40 -7
  694. package/dist/voice/room_io/_input.cjs.map +1 -1
  695. package/dist/voice/room_io/_input.d.cts +5 -2
  696. package/dist/voice/room_io/_input.d.ts +5 -2
  697. package/dist/voice/room_io/_input.d.ts.map +1 -1
  698. package/dist/voice/room_io/_input.js +41 -8
  699. package/dist/voice/room_io/_input.js.map +1 -1
  700. package/dist/voice/room_io/_output.cjs +19 -11
  701. package/dist/voice/room_io/_output.cjs.map +1 -1
  702. package/dist/voice/room_io/_output.d.cts +7 -4
  703. package/dist/voice/room_io/_output.d.ts +7 -4
  704. package/dist/voice/room_io/_output.d.ts.map +1 -1
  705. package/dist/voice/room_io/_output.js +20 -12
  706. package/dist/voice/room_io/_output.js.map +1 -1
  707. package/dist/voice/room_io/room_io.cjs +33 -6
  708. package/dist/voice/room_io/room_io.cjs.map +1 -1
  709. package/dist/voice/room_io/room_io.d.cts +29 -9
  710. package/dist/voice/room_io/room_io.d.ts +29 -9
  711. package/dist/voice/room_io/room_io.d.ts.map +1 -1
  712. package/dist/voice/room_io/room_io.js +33 -7
  713. package/dist/voice/room_io/room_io.js.map +1 -1
  714. package/dist/voice/speech_handle.cjs +22 -4
  715. package/dist/voice/speech_handle.cjs.map +1 -1
  716. package/dist/voice/speech_handle.d.cts +17 -2
  717. package/dist/voice/speech_handle.d.ts +17 -2
  718. package/dist/voice/speech_handle.d.ts.map +1 -1
  719. package/dist/voice/speech_handle.js +21 -4
  720. package/dist/voice/speech_handle.js.map +1 -1
  721. package/dist/voice/testing/fake_llm.cjs +127 -0
  722. package/dist/voice/testing/fake_llm.cjs.map +1 -0
  723. package/dist/voice/testing/fake_llm.d.cts +30 -0
  724. package/dist/voice/testing/fake_llm.d.ts +30 -0
  725. package/dist/voice/testing/fake_llm.d.ts.map +1 -0
  726. package/dist/voice/testing/fake_llm.js +103 -0
  727. package/dist/voice/testing/fake_llm.js.map +1 -0
  728. package/dist/voice/testing/index.cjs +57 -0
  729. package/dist/voice/testing/index.cjs.map +1 -0
  730. package/dist/voice/testing/index.d.cts +21 -0
  731. package/dist/voice/testing/index.d.ts +21 -0
  732. package/dist/voice/testing/index.d.ts.map +1 -0
  733. package/dist/voice/testing/index.js +35 -0
  734. package/dist/voice/testing/index.js.map +1 -0
  735. package/dist/voice/testing/run_result.cjs +817 -0
  736. package/dist/voice/testing/run_result.cjs.map +1 -0
  737. package/dist/voice/testing/run_result.d.cts +385 -0
  738. package/dist/voice/testing/run_result.d.ts +385 -0
  739. package/dist/voice/testing/run_result.d.ts.map +1 -0
  740. package/dist/voice/testing/run_result.js +790 -0
  741. package/dist/voice/testing/run_result.js.map +1 -0
  742. package/dist/voice/testing/types.cjs +46 -0
  743. package/dist/voice/testing/types.cjs.map +1 -0
  744. package/dist/voice/testing/types.d.cts +83 -0
  745. package/dist/voice/testing/types.d.ts +83 -0
  746. package/dist/voice/testing/types.d.ts.map +1 -0
  747. package/dist/voice/testing/types.js +19 -0
  748. package/dist/voice/testing/types.js.map +1 -0
  749. package/dist/voice/transcription/synchronizer.cjs +139 -15
  750. package/dist/voice/transcription/synchronizer.cjs.map +1 -1
  751. package/dist/voice/transcription/synchronizer.d.cts +35 -4
  752. package/dist/voice/transcription/synchronizer.d.ts +35 -4
  753. package/dist/voice/transcription/synchronizer.d.ts.map +1 -1
  754. package/dist/voice/transcription/synchronizer.js +143 -16
  755. package/dist/voice/transcription/synchronizer.js.map +1 -1
  756. package/dist/voice/transcription/synchronizer.test.cjs +151 -0
  757. package/dist/voice/transcription/synchronizer.test.cjs.map +1 -0
  758. package/dist/voice/transcription/synchronizer.test.js +150 -0
  759. package/dist/voice/transcription/synchronizer.test.js.map +1 -0
  760. package/dist/voice/turn_config/endpointing.cjs +33 -0
  761. package/dist/voice/turn_config/endpointing.cjs.map +1 -0
  762. package/dist/voice/turn_config/endpointing.d.cts +30 -0
  763. package/dist/voice/turn_config/endpointing.d.ts +30 -0
  764. package/dist/voice/turn_config/endpointing.d.ts.map +1 -0
  765. package/dist/voice/turn_config/endpointing.js +9 -0
  766. package/dist/voice/turn_config/endpointing.js.map +1 -0
  767. package/dist/voice/turn_config/interruption.cjs +37 -0
  768. package/dist/voice/turn_config/interruption.cjs.map +1 -0
  769. package/dist/voice/turn_config/interruption.d.cts +53 -0
  770. package/dist/voice/turn_config/interruption.d.ts +53 -0
  771. package/dist/voice/turn_config/interruption.d.ts.map +1 -0
  772. package/dist/voice/turn_config/interruption.js +13 -0
  773. package/dist/voice/turn_config/interruption.js.map +1 -0
  774. package/dist/voice/turn_config/turn_handling.cjs +35 -0
  775. package/dist/voice/turn_config/turn_handling.cjs.map +1 -0
  776. package/dist/voice/turn_config/turn_handling.d.cts +36 -0
  777. package/dist/voice/turn_config/turn_handling.d.ts +36 -0
  778. package/dist/voice/turn_config/turn_handling.d.ts.map +1 -0
  779. package/dist/voice/turn_config/turn_handling.js +11 -0
  780. package/dist/voice/turn_config/turn_handling.js.map +1 -0
  781. package/dist/voice/turn_config/utils.cjs +157 -0
  782. package/dist/voice/turn_config/utils.cjs.map +1 -0
  783. package/dist/voice/turn_config/utils.d.cts +37 -0
  784. package/dist/voice/turn_config/utils.d.ts +37 -0
  785. package/dist/voice/turn_config/utils.d.ts.map +1 -0
  786. package/dist/voice/turn_config/utils.js +131 -0
  787. package/dist/voice/turn_config/utils.js.map +1 -0
  788. package/dist/voice/turn_config/utils.test.cjs +128 -0
  789. package/dist/voice/turn_config/utils.test.cjs.map +1 -0
  790. package/dist/voice/turn_config/utils.test.js +127 -0
  791. package/dist/voice/turn_config/utils.test.js.map +1 -0
  792. package/dist/voice/utils.cjs +47 -0
  793. package/dist/voice/utils.cjs.map +1 -0
  794. package/dist/voice/utils.d.cts +4 -0
  795. package/dist/voice/utils.d.ts +4 -0
  796. package/dist/voice/utils.d.ts.map +1 -0
  797. package/dist/voice/utils.js +23 -0
  798. package/dist/voice/utils.js.map +1 -0
  799. package/dist/worker.cjs +44 -52
  800. package/dist/worker.cjs.map +1 -1
  801. package/dist/worker.d.cts +18 -8
  802. package/dist/worker.d.ts +18 -8
  803. package/dist/worker.d.ts.map +1 -1
  804. package/dist/worker.js +43 -43
  805. package/dist/worker.js.map +1 -1
  806. package/package.json +32 -12
  807. package/resources/NOTICE +2 -0
  808. package/resources/keyboard-typing.ogg +0 -0
  809. package/resources/keyboard-typing2.ogg +0 -0
  810. package/resources/office-ambience.ogg +0 -0
  811. package/src/audio.ts +132 -1
  812. package/src/beta/index.ts +9 -0
  813. package/src/beta/workflows/index.ts +9 -0
  814. package/src/beta/workflows/task_group.ts +194 -0
  815. package/src/cli.ts +57 -66
  816. package/src/connection_pool.test.ts +346 -0
  817. package/src/connection_pool.ts +307 -0
  818. package/src/constants.ts +14 -0
  819. package/src/cpu.test.ts +239 -0
  820. package/src/cpu.ts +173 -0
  821. package/src/http_server.ts +18 -6
  822. package/src/index.ts +15 -13
  823. package/src/inference/api_protos.ts +85 -2
  824. package/src/inference/index.ts +32 -4
  825. package/src/inference/interruption/defaults.ts +51 -0
  826. package/src/inference/interruption/errors.ts +25 -0
  827. package/src/inference/interruption/http_transport.ts +206 -0
  828. package/src/inference/interruption/interruption_cache_entry.ts +50 -0
  829. package/src/inference/interruption/interruption_detector.ts +204 -0
  830. package/src/inference/interruption/interruption_stream.ts +467 -0
  831. package/src/inference/interruption/types.ts +84 -0
  832. package/src/inference/interruption/utils.test.ts +132 -0
  833. package/src/inference/interruption/utils.ts +137 -0
  834. package/src/inference/interruption/ws_transport.ts +406 -0
  835. package/src/inference/llm.ts +214 -163
  836. package/src/inference/stt.test.ts +253 -0
  837. package/src/inference/stt.ts +449 -208
  838. package/src/inference/tts.test.ts +267 -0
  839. package/src/inference/tts.ts +377 -115
  840. package/src/inference/utils.ts +30 -2
  841. package/src/ipc/inference_proc_executor.ts +11 -3
  842. package/src/ipc/inference_proc_lazy_main.ts +13 -1
  843. package/src/ipc/job_proc_executor.ts +11 -1
  844. package/src/ipc/job_proc_lazy_main.ts +86 -20
  845. package/src/ipc/supervised_proc.test.ts +153 -0
  846. package/src/ipc/supervised_proc.ts +39 -10
  847. package/src/job.ts +120 -1
  848. package/src/language.test.ts +62 -0
  849. package/src/language.ts +380 -0
  850. package/src/llm/__snapshots__/zod-utils.test.ts.snap +559 -0
  851. package/src/llm/chat_context.test.ts +655 -0
  852. package/src/llm/chat_context.ts +412 -2
  853. package/src/llm/fallback_adapter.test.ts +238 -0
  854. package/src/llm/fallback_adapter.ts +391 -0
  855. package/src/llm/index.ts +11 -0
  856. package/src/llm/llm.ts +77 -12
  857. package/src/llm/provider_format/google.test.ts +72 -1
  858. package/src/llm/provider_format/google.ts +10 -6
  859. package/src/llm/provider_format/index.ts +7 -2
  860. package/src/llm/provider_format/openai.test.ts +480 -2
  861. package/src/llm/provider_format/openai.ts +152 -21
  862. package/src/llm/provider_format/utils.ts +11 -5
  863. package/src/llm/realtime.ts +23 -2
  864. package/src/llm/remote_chat_context.ts +2 -2
  865. package/src/llm/tool_context.test.ts +210 -1
  866. package/src/llm/tool_context.ts +115 -17
  867. package/src/llm/utils.ts +24 -16
  868. package/src/llm/zod-utils.test.ts +577 -0
  869. package/src/llm/zod-utils.ts +153 -0
  870. package/src/log.ts +71 -19
  871. package/src/metrics/base.ts +78 -19
  872. package/src/metrics/index.ts +12 -0
  873. package/src/metrics/model_usage.test.ts +545 -0
  874. package/src/metrics/model_usage.ts +262 -0
  875. package/src/metrics/usage_collector.ts +14 -3
  876. package/src/metrics/utils.ts +27 -7
  877. package/src/stream/deferred_stream.test.ts +3 -3
  878. package/src/stream/deferred_stream.ts +43 -11
  879. package/src/stream/index.ts +1 -0
  880. package/src/stream/multi_input_stream.test.ts +545 -0
  881. package/src/stream/multi_input_stream.ts +172 -0
  882. package/src/stream/stream_channel.test.ts +37 -0
  883. package/src/stream/stream_channel.ts +43 -3
  884. package/src/stt/stream_adapter.ts +30 -9
  885. package/src/stt/stt.ts +131 -22
  886. package/src/telemetry/index.ts +28 -0
  887. package/src/telemetry/logging.ts +55 -0
  888. package/src/telemetry/otel_http_exporter.ts +218 -0
  889. package/src/telemetry/pino_otel_transport.ts +265 -0
  890. package/src/telemetry/trace_types.ts +109 -0
  891. package/src/telemetry/traces.ts +673 -0
  892. package/src/telemetry/utils.ts +61 -0
  893. package/src/tokenize/basic/sentence.ts +3 -3
  894. package/src/tokenize/tokenizer.test.ts +4 -0
  895. package/src/transcription.ts +6 -0
  896. package/src/tts/fallback_adapter.ts +579 -0
  897. package/src/tts/index.ts +1 -0
  898. package/src/tts/stream_adapter.ts +38 -8
  899. package/src/tts/tts.ts +245 -62
  900. package/src/types.ts +62 -33
  901. package/src/utils.test.ts +90 -10
  902. package/src/utils.ts +176 -31
  903. package/src/vad.ts +42 -18
  904. package/src/version.ts +1 -1
  905. package/src/voice/agent.test.ts +347 -2
  906. package/src/voice/agent.ts +346 -44
  907. package/src/voice/agent_activity.test.ts +194 -0
  908. package/src/voice/agent_activity.ts +1457 -388
  909. package/src/voice/agent_session.ts +817 -112
  910. package/src/voice/audio_recognition.ts +845 -70
  911. package/src/voice/audio_recognition_span.test.ts +341 -0
  912. package/src/voice/avatar/datastream_io.ts +9 -1
  913. package/src/voice/background_audio.ts +494 -0
  914. package/src/voice/events.ts +27 -7
  915. package/src/voice/generation.ts +310 -56
  916. package/src/voice/generation_tools.test.ts +268 -0
  917. package/src/voice/index.ts +17 -3
  918. package/src/voice/interruption_detection.test.ts +151 -0
  919. package/src/voice/io.ts +115 -12
  920. package/src/voice/recorder_io/index.ts +4 -0
  921. package/src/voice/recorder_io/recorder_io.ts +783 -0
  922. package/src/voice/remote_session.ts +1083 -0
  923. package/src/voice/report.test.ts +136 -0
  924. package/src/voice/report.ts +140 -0
  925. package/src/voice/room_io/_input.ts +45 -10
  926. package/src/voice/room_io/_output.ts +26 -14
  927. package/src/voice/room_io/room_io.ts +67 -22
  928. package/src/voice/speech_handle.ts +38 -6
  929. package/src/voice/testing/fake_llm.ts +138 -0
  930. package/src/voice/testing/index.ts +52 -0
  931. package/src/voice/testing/run_result.ts +995 -0
  932. package/src/voice/testing/types.ts +118 -0
  933. package/src/voice/transcription/synchronizer.test.ts +206 -0
  934. package/src/voice/transcription/synchronizer.ts +204 -19
  935. package/src/voice/turn_config/endpointing.ts +33 -0
  936. package/src/voice/turn_config/interruption.ts +56 -0
  937. package/src/voice/turn_config/turn_handling.ts +45 -0
  938. package/src/voice/turn_config/utils.test.ts +148 -0
  939. package/src/voice/turn_config/utils.ts +167 -0
  940. package/src/voice/utils.ts +29 -0
  941. package/src/worker.ts +92 -78
  942. package/src/llm/__snapshots__/utils.test.ts.snap +0 -65
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { AudioFrame } from '@livekit/rtc-node';\nimport { ReadableStream } from 'node:stream/web';\nimport { describe, expect, it } from 'vitest';\nimport { initializeLogger } from '../src/log.js';\nimport {\n Event,\n TASK_TIMEOUT_ERROR,\n Task,\n TaskResult,\n delay,\n isPending,\n resampleStream,\n} from '../src/utils.js';\n\ndescribe('utils', () => {\n // initialize logger\n initializeLogger({ pretty: true, level: 'debug' });\n\n describe('Task', () => {\n it('should execute task successfully and return result', async () => {\n const expectedResult = 'task completed';\n const task = Task.from(async () => {\n await delay(10);\n return expectedResult;\n });\n\n expect(task.done).toBe(false);\n const result = await task.result;\n expect(result).toBe(expectedResult);\n expect(task.done).toBe(true);\n });\n\n it('should handle task errors properly', async () => {\n const expectedError = new Error('Task failed');\n const task = Task.from(async () => {\n await delay(10);\n throw expectedError;\n });\n\n expect(task.done).toBe(false);\n await expect(task.result).rejects.toThrow(expectedError);\n expect(task.done).toBe(true);\n });\n\n it('should cancel task when cancel is called', async () => {\n let taskStarted = false;\n let taskCompleted = false;\n\n const task = Task.from(async (controller) => {\n taskStarted = true;\n await delay(100, { signal: controller.signal });\n taskCompleted = true;\n return 'should not complete';\n });\n\n // Wait a bit to ensure task starts\n await delay(10);\n expect(taskStarted).toBe(true);\n expect(task.done).toBe(false);\n\n // Cancel the task\n task.cancel();\n\n // The task should reject with AbortError\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(taskCompleted).toBe(false);\n expect(task.done).toBe(true);\n });\n\n it('should use provided AbortController', async () => {\n const controller = new AbortController();\n const task = Task.from(async (ctrl) => {\n expect(ctrl).toBe(controller);\n await delay(100, { signal: ctrl.signal });\n return 'completed';\n }, controller);\n\n await delay(10);\n controller.abort();\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle immediate resolution', async () => {\n const task = Task.from(async () => {\n return 'immediate';\n });\n\n const result = await task.result;\n expect(result).toBe('immediate');\n expect(task.done).toBe(true);\n });\n\n it('should handle immediate rejection', async () => {\n const expectedError = new Error('Immediate error');\n const task = Task.from(async () => {\n throw expectedError;\n });\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect(error).toBe(expectedError);\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle multiple calls to cancel', async () => {\n const task = Task.from(async (controller) => {\n await delay(100, { signal: controller.signal });\n return 'should not complete';\n });\n\n await delay(10);\n\n // Multiple cancellations should not cause issues\n task.cancel();\n task.cancel();\n task.cancel();\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle task that checks abort signal manually', async () => {\n const arr: number[] = [];\n const task = Task.from(async (controller) => {\n for (let i = 0; i < 10; i++) {\n if (controller.signal.aborted) {\n throw new Error('Task was aborted');\n }\n await delay(10);\n arr.push(i);\n }\n return 'completed';\n });\n\n await delay(39);\n task.cancel();\n\n expect(arr).toEqual([0, 1, 2]);\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).message).toBe('Task was aborted');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle cleanup in finally block', async () => {\n let cleanupExecuted = false;\n\n const task = Task.from(async (controller) => {\n try {\n await delay(100, { signal: controller.signal });\n return 'completed';\n } finally {\n cleanupExecuted = true;\n }\n });\n\n await delay(10);\n task.cancel();\n\n try {\n await task.result;\n } catch {\n // Ignore the abort error\n }\n\n // Cleanup should still execute even when cancelled\n expect(cleanupExecuted).toBe(true);\n });\n\n it('should handle accessing result multiple times', async () => {\n const task = Task.from(async () => {\n await delay(10);\n return 'result';\n });\n\n const result1 = await task.result;\n const result2 = await task.result;\n const result3 = await task.result;\n\n expect(result1).toBe('result');\n expect(result2).toBe('result');\n expect(result3).toBe('result');\n expect(task.done).toBe(true);\n });\n\n it('should handle accessing result promise before completion', async () => {\n const task = Task.from(async () => {\n await delay(50);\n return 'delayed result';\n });\n\n // Get references to result promise before completion\n const resultPromise1 = task.result;\n const resultPromise2 = task.result;\n\n expect(task.done).toBe(false);\n\n // Both promises should resolve to the same value\n const [result1, result2] = await Promise.all([resultPromise1, resultPromise2]);\n\n expect(result1).toBe('delayed result');\n expect(result2).toBe('delayed result');\n expect(task.done).toBe(true);\n });\n\n it('should cancel child tasks when parent task is canceled', async () => {\n let parentStarted = false;\n let child1Started = false;\n let child2Started = false;\n let parentCompleted = false;\n let child1Completed = false;\n let child2Completed = false;\n\n let child1Task: Task<string> | undefined = undefined;\n let child2Task: Task<string> | undefined = undefined;\n\n const parentTask = Task.from(async (controller) => {\n parentStarted = true;\n\n // Create two child tasks using the parent's controller\n child1Task = Task.from(async (childController) => {\n child1Started = true;\n await delay(100, { signal: childController.signal });\n child1Completed = true;\n return 'child1';\n }, controller);\n\n child2Task = Task.from(async (childController) => {\n child2Started = true;\n await delay(100, { signal: childController.signal });\n child2Completed = true;\n return 'child2';\n }, controller);\n\n // Wait for both child tasks\n const results = await Promise.all([child1Task.result, child2Task.result]);\n parentCompleted = true;\n return results;\n });\n\n // Let tasks start\n await delay(20);\n\n // Verify tasks have started\n expect(parentStarted).toBe(true);\n expect(child1Started).toBe(true);\n expect(child2Started).toBe(true);\n\n // Cancel parent task\n parentTask.cancel();\n\n // Use Promise.allSettled to handle all promise settlements\n const [parentResult, child1Result, child2Result] = await Promise.allSettled([\n parentTask.result,\n child1Task!.result,\n child2Task!.result,\n ]);\n\n // Verify all tasks were rejected with AbortError\n expect(parentResult.status).toBe('rejected');\n expect((parentResult as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n expect(child1Result.status).toBe('rejected');\n expect((child1Result as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n expect(child2Result.status).toBe('rejected');\n expect((child2Result as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n // Verify none of the tasks completed\n expect(parentCompleted).toBe(false);\n expect(child1Completed).toBe(false);\n expect(child2Completed).toBe(false);\n expect(parentTask.done).toBe(true);\n expect(child1Task!.done).toBe(true);\n expect(child2Task!.done).toBe(true);\n });\n\n it('should handle nested tasks that complete successfully', async () => {\n const results: string[] = [];\n\n const parentTask = Task.from(async (controller) => {\n results.push('parent-start');\n\n // Create first child task\n const child1Task = Task.from(async () => {\n results.push('child1-start');\n await delay(25);\n results.push('child1-end');\n return 'child1-result';\n }, controller);\n\n // Create second child task that depends on first\n const child2Task = Task.from(async (childController) => {\n results.push('child2-start');\n\n // Create a grandchild task\n const grandchildTask = Task.from(async () => {\n results.push('grandchild-start');\n await delay(10);\n results.push('grandchild-end');\n return 'grandchild-result';\n }, childController);\n\n const grandchildResult = await grandchildTask.result;\n await delay(10);\n results.push('child2-end');\n return `child2-result-with-${grandchildResult}`;\n }, controller);\n\n // Wait for all tasks\n const [child1Result, child2Result] = await Promise.all([\n child1Task.result,\n child2Task.result,\n ]);\n\n results.push('parent-end');\n return {\n parent: 'parent-result',\n child1: child1Result,\n child2: child2Result,\n };\n });\n\n // Wait for everything to complete\n const finalResult = await parentTask.result;\n\n // Verify results\n expect(finalResult).toEqual({\n parent: 'parent-result',\n child1: 'child1-result',\n child2: 'child2-result-with-grandchild-result',\n });\n\n // Verify execution order\n // Check important ordering constraints without being strict about parallel task ordering\n expect(results).toEqual([\n 'parent-start',\n 'child1-start',\n 'child2-start',\n 'grandchild-start',\n 'grandchild-end',\n 'child2-end',\n 'child1-end',\n 'parent-end',\n ]);\n\n // All tasks should be done\n expect(parentTask.done).toBe(true);\n });\n\n it('should propagate errors from nested tasks', async () => {\n let parentError: Error | null = null;\n let child1Completed = false;\n let child2Started = false;\n\n const parentTask = Task.from(async (controller) => {\n const child1Task = Task.from(async () => {\n await delay(20);\n throw new Error('child1 error');\n }, controller);\n\n const child2Task = Task.from(async () => {\n child2Started = true;\n await delay(30);\n child1Completed = true;\n return 'child2-result';\n }, controller);\n\n // This will throw when child1 fails\n const results = await Promise.all([child1Task.result, child2Task.result]);\n return results;\n });\n\n // Wait for the parent task to fail\n try {\n await parentTask.result;\n expect.fail('Parent task should have thrown');\n } catch (error: unknown) {\n parentError = error as Error;\n }\n\n // Verify the error propagated correctly\n expect(parentError?.message).toBe('child1 error');\n expect(child1Completed).toBe(false);\n expect(child2Started).toBe(true);\n expect(parentTask.done).toBe(true);\n });\n\n it('should cancel and wait for task completion', async () => {\n let taskCompleted = false;\n\n const task = Task.from(async (controller) => {\n await delay(5000, { signal: controller.signal });\n taskCompleted = true;\n return 'should not complete';\n });\n\n // Cancel and wait should complete quickly when task is aborted\n const start = Date.now();\n const result = await task.cancelAndWait(1000);\n const duration = Date.now() - start;\n\n expect(result).toBe(TaskResult.Aborted);\n expect(duration).toBeLessThan(100); // Should not wait for full timeout\n expect(taskCompleted).toBe(false);\n expect(task.done).toBe(true);\n });\n\n it('should timeout if task does not respond to cancellation', async () => {\n const task = Task.from(async () => {\n await delay(1000);\n });\n\n // This should timeout because the task ignores cancellation\n try {\n await task.cancelAndWait(200);\n expect.fail('Task should have timed out');\n } catch (error: unknown) {\n expect(error).toBe(TASK_TIMEOUT_ERROR);\n }\n });\n\n it('should handle task that completes before timeout', async () => {\n const task = Task.from(async () => {\n await delay(50);\n });\n\n // Start the task\n await delay(10);\n\n // Cancel and wait - but task will complete normally before being canceled\n const result = await task.cancelAndWait(1000);\n\n // Task should have completed normally\n expect(result).toBe(TaskResult.Completed);\n expect(task.done).toBe(true);\n });\n\n it('should propagate non-abort errors from cancelAndWait', async () => {\n const task = Task.from(async () => {\n await delay(10);\n throw new TypeError('Custom error');\n });\n\n try {\n await task.cancelAndWait(1000);\n expect.fail('Task should have thrown');\n } catch (error: unknown) {\n expect((error as Error).message).toBe('Custom error');\n expect((error as Error).name).toBe('TypeError');\n }\n });\n });\n\n describe('Event', () => {\n it('wait resolves immediately when the event is already set', async () => {\n const event = new Event();\n event.set();\n\n const result = await event.wait();\n expect(result).toBe(true);\n });\n\n it('wait resolves after set is called', async () => {\n // check promise is pending\n const event = new Event();\n const waiterPromise = event.wait();\n\n await delay(10);\n expect(await isPending(waiterPromise)).toBe(true);\n\n // check promise is resolved after set is called\n event.set();\n const result = await waiterPromise;\n expect(result).toBe(true);\n });\n\n it('all waiters resolve once set is called', async () => {\n const event = new Event();\n const waiters = [event.wait(), event.wait(), event.wait()];\n\n await delay(10);\n const pendings = await Promise.all(waiters.map((w) => isPending(w)));\n expect(pendings).toEqual([true, true, true]);\n\n event.set();\n const results = await Promise.all(waiters);\n expect(results).toEqual([true, true, true]);\n });\n\n it('wait after 2 seconds is still pending before set', async () => {\n const event = new Event();\n const waiter = event.wait();\n\n await delay(2000);\n expect(await isPending(waiter)).toBe(true);\n\n event.set();\n const result = await waiter;\n expect(result).toBe(true);\n });\n\n it('wait after set and clear should be pending', async () => {\n const event = new Event();\n const waiterBeforeSet = event.wait();\n event.set();\n event.clear();\n\n const waiterAfterSet = event.wait();\n\n const result = await Promise.race([\n waiterBeforeSet.then(() => 'before'),\n waiterAfterSet.then(() => 'after'),\n ]);\n\n expect(result).toBe('before');\n expect(await isPending(waiterBeforeSet)).toBe(false);\n expect(await isPending(waiterAfterSet)).toBe(true);\n\n event.set();\n expect(await waiterAfterSet).toBe(true);\n });\n });\n\n describe('resampleStream', () => {\n const createAudioFrame = (sampleRate: number, samples: number, channels = 1): AudioFrame => {\n const data = new Int16Array(samples * channels);\n for (let i = 0; i < data.length; i++) {\n data[i] = Math.sin((i / samples) * Math.PI * 2) * 16000;\n }\n return new AudioFrame(data, sampleRate, channels, samples);\n };\n\n const streamToArray = async (stream: ReadableStream<AudioFrame>): Promise<AudioFrame[]> => {\n const reader = stream.getReader();\n const chunks: AudioFrame[] = [];\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n return chunks;\n };\n\n it('should resample audio frames to target sample rate', async () => {\n const inputRate = 48000;\n const outputRate = 16000;\n const inputFrame = createAudioFrame(inputRate, 960); // 20ms at 48kHz\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(inputFrame);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(outputRate);\n expect(frame.channels).toBe(inputFrame.channels);\n }\n });\n\n it('should handle same input and output rate', async () => {\n const sampleRate = 44100;\n const inputFrame = createAudioFrame(sampleRate, 1024);\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(inputFrame);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate: sampleRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(sampleRate);\n expect(frame.channels).toBe(inputFrame.channels);\n }\n });\n\n it('should handle multiple input frames', async () => {\n const inputRate = 32000;\n const outputRate = 48000;\n const frame1 = createAudioFrame(inputRate, 640);\n const frame2 = createAudioFrame(inputRate, 640);\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(frame1);\n controller.enqueue(frame2);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(outputRate);\n expect(frame.channels).toBe(frame1.channels);\n }\n });\n\n it('should handle empty stream', async () => {\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate: 44100 });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames).toEqual([]);\n });\n });\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { AudioFrame } from '@livekit/rtc-node';\nimport { ReadableStream } from 'node:stream/web';\nimport { describe, expect, it } from 'vitest';\nimport { initializeLogger } from '../src/log.js';\nimport { Event, Task, TaskResult, delay, isPending, resampleStream } from '../src/utils.js';\n\ndescribe('utils', () => {\n // initialize logger\n initializeLogger({ pretty: true, level: 'debug' });\n\n describe('Task', () => {\n it('should execute task successfully and return result', async () => {\n const expectedResult = 'task completed';\n const task = Task.from(async () => {\n await delay(10);\n return expectedResult;\n });\n\n expect(task.done).toBe(false);\n const result = await task.result;\n expect(result).toBe(expectedResult);\n expect(task.done).toBe(true);\n });\n\n it('should handle task errors properly', async () => {\n const expectedError = new Error('Task failed');\n const task = Task.from(async () => {\n await delay(10);\n throw expectedError;\n });\n\n expect(task.done).toBe(false);\n await expect(task.result).rejects.toThrow(expectedError);\n expect(task.done).toBe(true);\n });\n\n it('should cancel task when cancel is called', async () => {\n let taskStarted = false;\n let taskCompleted = false;\n\n const task = Task.from(async (controller) => {\n taskStarted = true;\n await delay(100, { signal: controller.signal });\n taskCompleted = true;\n return 'should not complete';\n });\n\n // Wait a bit to ensure task starts\n await delay(10);\n expect(taskStarted).toBe(true);\n expect(task.done).toBe(false);\n\n // Cancel the task\n task.cancel();\n\n // The task should reject with AbortError\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(taskCompleted).toBe(false);\n expect(task.done).toBe(true);\n });\n\n it('should use provided AbortController', async () => {\n const controller = new AbortController();\n const task = Task.from(async (ctrl) => {\n expect(ctrl).toBe(controller);\n await delay(100, { signal: ctrl.signal });\n return 'completed';\n }, controller);\n\n await delay(10);\n controller.abort();\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle immediate resolution', async () => {\n const task = Task.from(async () => {\n return 'immediate';\n });\n\n const result = await task.result;\n expect(result).toBe('immediate');\n expect(task.done).toBe(true);\n });\n\n it('should handle immediate rejection', async () => {\n const expectedError = new Error('Immediate error');\n const task = Task.from(async () => {\n throw expectedError;\n });\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect(error).toBe(expectedError);\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle multiple calls to cancel', async () => {\n const task = Task.from(async (controller) => {\n await delay(100, { signal: controller.signal });\n return 'should not complete';\n });\n\n await delay(10);\n\n // Multiple cancellations should not cause issues\n task.cancel();\n task.cancel();\n task.cancel();\n\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).name).toBe('AbortError');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle task that checks abort signal manually', async () => {\n const arr: number[] = [];\n const task = Task.from(async (controller) => {\n for (let i = 0; i < 10; i++) {\n if (controller.signal.aborted) {\n throw new Error('Task was aborted');\n }\n await delay(10);\n arr.push(i);\n }\n return 'completed';\n });\n\n await delay(39);\n task.cancel();\n\n expect(arr).toEqual([0, 1, 2]);\n try {\n await task.result;\n } catch (error: unknown) {\n expect((error as Error).message).toBe('Task was aborted');\n }\n\n expect(task.done).toBe(true);\n });\n\n it('should handle cleanup in finally block', async () => {\n let cleanupExecuted = false;\n\n const task = Task.from(async (controller) => {\n try {\n await delay(100, { signal: controller.signal });\n return 'completed';\n } finally {\n cleanupExecuted = true;\n }\n });\n\n await delay(10);\n task.cancel();\n\n try {\n await task.result;\n } catch {\n // Ignore the abort error\n }\n\n // Cleanup should still execute even when cancelled\n expect(cleanupExecuted).toBe(true);\n });\n\n it('should handle accessing result multiple times', async () => {\n const task = Task.from(async () => {\n await delay(10);\n return 'result';\n });\n\n const result1 = await task.result;\n const result2 = await task.result;\n const result3 = await task.result;\n\n expect(result1).toBe('result');\n expect(result2).toBe('result');\n expect(result3).toBe('result');\n expect(task.done).toBe(true);\n });\n\n it('should handle accessing result promise before completion', async () => {\n const task = Task.from(async () => {\n await delay(50);\n return 'delayed result';\n });\n\n // Get references to result promise before completion\n const resultPromise1 = task.result;\n const resultPromise2 = task.result;\n\n expect(task.done).toBe(false);\n\n // Both promises should resolve to the same value\n const [result1, result2] = await Promise.all([resultPromise1, resultPromise2]);\n\n expect(result1).toBe('delayed result');\n expect(result2).toBe('delayed result');\n expect(task.done).toBe(true);\n });\n\n it('should cancel child tasks when parent task is canceled', async () => {\n let parentStarted = false;\n let child1Started = false;\n let child2Started = false;\n let parentCompleted = false;\n let child1Completed = false;\n let child2Completed = false;\n\n let child1Task: Task<string> | undefined = undefined;\n let child2Task: Task<string> | undefined = undefined;\n\n const parentTask = Task.from(async (controller) => {\n parentStarted = true;\n\n // Create two child tasks using the parent's controller\n child1Task = Task.from(async (childController) => {\n child1Started = true;\n await delay(100, { signal: childController.signal });\n child1Completed = true;\n return 'child1';\n }, controller);\n\n child2Task = Task.from(async (childController) => {\n child2Started = true;\n await delay(100, { signal: childController.signal });\n child2Completed = true;\n return 'child2';\n }, controller);\n\n // Wait for both child tasks\n const results = await Promise.all([child1Task.result, child2Task.result]);\n parentCompleted = true;\n return results;\n });\n\n // Let tasks start\n await delay(20);\n\n // Verify tasks have started\n expect(parentStarted).toBe(true);\n expect(child1Started).toBe(true);\n expect(child2Started).toBe(true);\n\n // Cancel parent task\n parentTask.cancel();\n\n // Use Promise.allSettled to handle all promise settlements\n const [parentResult, child1Result, child2Result] = await Promise.allSettled([\n parentTask.result,\n child1Task!.result,\n child2Task!.result,\n ]);\n\n // Verify all tasks were rejected with AbortError\n expect(parentResult.status).toBe('rejected');\n expect((parentResult as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n expect(child1Result.status).toBe('rejected');\n expect((child1Result as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n expect(child2Result.status).toBe('rejected');\n expect((child2Result as PromiseRejectedResult).reason.name).toBe('AbortError');\n\n // Verify none of the tasks completed\n expect(parentCompleted).toBe(false);\n expect(child1Completed).toBe(false);\n expect(child2Completed).toBe(false);\n expect(parentTask.done).toBe(true);\n expect(child1Task!.done).toBe(true);\n expect(child2Task!.done).toBe(true);\n });\n\n it('should handle nested tasks that complete successfully', async () => {\n const results: string[] = [];\n\n const parentTask = Task.from(async (controller) => {\n results.push('parent-start');\n\n // Create first child task\n const child1Task = Task.from(async () => {\n results.push('child1-start');\n await delay(25);\n results.push('child1-end');\n return 'child1-result';\n }, controller);\n\n // Create second child task that depends on first\n const child2Task = Task.from(async (childController) => {\n results.push('child2-start');\n\n // Create a grandchild task\n const grandchildTask = Task.from(async () => {\n results.push('grandchild-start');\n await delay(10);\n results.push('grandchild-end');\n return 'grandchild-result';\n }, childController);\n\n const grandchildResult = await grandchildTask.result;\n await delay(10);\n results.push('child2-end');\n return `child2-result-with-${grandchildResult}`;\n }, controller);\n\n // Wait for all tasks\n const [child1Result, child2Result] = await Promise.all([\n child1Task.result,\n child2Task.result,\n ]);\n\n results.push('parent-end');\n return {\n parent: 'parent-result',\n child1: child1Result,\n child2: child2Result,\n };\n });\n\n // Wait for everything to complete\n const finalResult = await parentTask.result;\n\n // Verify results\n expect(finalResult).toEqual({\n parent: 'parent-result',\n child1: 'child1-result',\n child2: 'child2-result-with-grandchild-result',\n });\n\n // Verify execution order\n // Check important ordering constraints without being strict about parallel task ordering\n expect(results).toEqual([\n 'parent-start',\n 'child1-start',\n 'child2-start',\n 'grandchild-start',\n 'grandchild-end',\n 'child2-end',\n 'child1-end',\n 'parent-end',\n ]);\n\n // All tasks should be done\n expect(parentTask.done).toBe(true);\n });\n\n it('should propagate errors from nested tasks', async () => {\n let parentError: Error | null = null;\n let child1Completed = false;\n let child2Started = false;\n\n const parentTask = Task.from(async (controller) => {\n const child1Task = Task.from(async () => {\n await delay(20);\n throw new Error('child1 error');\n }, controller);\n\n const child2Task = Task.from(async () => {\n child2Started = true;\n await delay(30);\n child1Completed = true;\n return 'child2-result';\n }, controller);\n\n // This will throw when child1 fails\n const results = await Promise.all([child1Task.result, child2Task.result]);\n return results;\n });\n\n // Wait for the parent task to fail\n try {\n await parentTask.result;\n expect.fail('Parent task should have thrown');\n } catch (error: unknown) {\n parentError = error as Error;\n }\n\n // Verify the error propagated correctly\n expect(parentError?.message).toBe('child1 error');\n expect(child1Completed).toBe(false);\n expect(child2Started).toBe(true);\n expect(parentTask.done).toBe(true);\n });\n\n it('should cancel and wait for task completion', async () => {\n let taskCompleted = false;\n\n const task = Task.from(async (controller) => {\n await delay(5000, { signal: controller.signal });\n taskCompleted = true;\n return 'should not complete';\n });\n\n // Cancel and wait should complete quickly when task is aborted\n const start = Date.now();\n const result = await task.cancelAndWait(1000);\n const duration = Date.now() - start;\n\n expect(result).toBe(TaskResult.Aborted);\n expect(duration).toBeLessThan(100); // Should not wait for full timeout\n expect(taskCompleted).toBe(false);\n expect(task.done).toBe(true);\n });\n\n it('should timeout if task does not respond to cancellation', async () => {\n const task = Task.from(async () => {\n await delay(1000);\n });\n\n // This should timeout because the task ignores cancellation\n try {\n await task.cancelAndWait(200);\n expect.fail('Task should have timed out');\n } catch (error: unknown) {\n expect(error).instanceof(Error);\n expect((error as Error).message).toBe('Task cancellation timed out');\n }\n });\n\n it('should handle task that completes before timeout', async () => {\n const task = Task.from(async () => {\n await delay(50);\n });\n\n // Start the task\n await delay(10);\n\n // Cancel and wait - but task will complete normally before being canceled\n const result = await task.cancelAndWait(1000);\n\n // Task should have completed normally\n expect(result).toBe(TaskResult.Completed);\n expect(task.done).toBe(true);\n });\n\n it('should propagate non-abort errors from cancelAndWait', async () => {\n const task = Task.from(async () => {\n await delay(10);\n throw new TypeError('Custom error');\n });\n\n try {\n await task.cancelAndWait(1000);\n expect.fail('Task should have thrown');\n } catch (error: unknown) {\n expect((error as Error).message).toBe('Custom error');\n expect((error as Error).name).toBe('TypeError');\n }\n });\n\n it('should return undefined for Task.current outside task context', () => {\n expect(Task.current()).toBeUndefined();\n });\n\n it('should preserve Task.current inside a task across awaits', async () => {\n const task = Task.from(\n async () => {\n const currentAtStart = Task.current();\n await delay(5);\n const currentAfterAwait = Task.current();\n\n expect(currentAtStart).toBeDefined();\n expect(currentAfterAwait).toBe(currentAtStart);\n\n return currentAtStart;\n },\n undefined,\n 'current-context-test',\n );\n\n const currentFromResult = await task.result;\n expect(currentFromResult).toBe(task);\n });\n\n it('should isolate nested Task.current context and restore parent context', async () => {\n const parentTask = Task.from(\n async (controller) => {\n const parentCurrent = Task.current();\n expect(parentCurrent).toBeDefined();\n\n const childTask = Task.from(\n async () => {\n const childCurrentStart = Task.current();\n await delay(5);\n const childCurrentAfterAwait = Task.current();\n\n expect(childCurrentStart).toBeDefined();\n expect(childCurrentAfterAwait).toBe(childCurrentStart);\n expect(childCurrentStart).not.toBe(parentCurrent);\n\n return childCurrentStart;\n },\n controller,\n 'child-current-context-test',\n );\n\n const childCurrent = await childTask.result;\n const parentCurrentAfterChild = Task.current();\n\n expect(parentCurrentAfterChild).toBe(parentCurrent);\n\n return { parentCurrent, childCurrent };\n },\n undefined,\n 'parent-current-context-test',\n );\n\n const { parentCurrent, childCurrent } = await parentTask.result;\n expect(parentCurrent).toBe(parentTask);\n expect(childCurrent).not.toBe(parentCurrent);\n expect(Task.current()).toBeUndefined();\n });\n\n it('should always expose Task.current for concurrent task callbacks', async () => {\n const tasks = Array.from({ length: 25 }, (_, idx) =>\n Task.from(\n async () => {\n const currentAtStart = Task.current();\n await delay(1);\n const currentAfterAwait = Task.current();\n\n expect(currentAtStart).toBeDefined();\n expect(currentAfterAwait).toBe(currentAtStart);\n\n return currentAtStart;\n },\n undefined,\n `current-context-stress-${idx}`,\n ),\n );\n\n const currentTasks = await Promise.all(tasks.map((task) => task.result));\n currentTasks.forEach((currentTask, idx) => {\n expect(currentTask).toBe(tasks[idx]);\n });\n });\n });\n\n describe('Event', () => {\n it('wait resolves immediately when the event is already set', async () => {\n const event = new Event();\n event.set();\n\n const result = await event.wait();\n expect(result).toBe(true);\n });\n\n it('wait resolves after set is called', async () => {\n // check promise is pending\n const event = new Event();\n const waiterPromise = event.wait();\n\n await delay(10);\n expect(await isPending(waiterPromise)).toBe(true);\n\n // check promise is resolved after set is called\n event.set();\n const result = await waiterPromise;\n expect(result).toBe(true);\n });\n\n it('all waiters resolve once set is called', async () => {\n const event = new Event();\n const waiters = [event.wait(), event.wait(), event.wait()];\n\n await delay(10);\n const pendings = await Promise.all(waiters.map((w) => isPending(w)));\n expect(pendings).toEqual([true, true, true]);\n\n event.set();\n const results = await Promise.all(waiters);\n expect(results).toEqual([true, true, true]);\n });\n\n it('wait after 2 seconds is still pending before set', async () => {\n const event = new Event();\n const waiter = event.wait();\n\n await delay(2000);\n expect(await isPending(waiter)).toBe(true);\n\n event.set();\n const result = await waiter;\n expect(result).toBe(true);\n });\n\n it('wait after set and clear should be pending', async () => {\n const event = new Event();\n const waiterBeforeSet = event.wait();\n event.set();\n event.clear();\n\n const waiterAfterSet = event.wait();\n\n const result = await Promise.race([\n waiterBeforeSet.then(() => 'before'),\n waiterAfterSet.then(() => 'after'),\n ]);\n\n expect(result).toBe('before');\n expect(await isPending(waiterBeforeSet)).toBe(false);\n expect(await isPending(waiterAfterSet)).toBe(true);\n\n event.set();\n expect(await waiterAfterSet).toBe(true);\n });\n });\n\n describe('resampleStream', () => {\n const createAudioFrame = (sampleRate: number, samples: number, channels = 1): AudioFrame => {\n const data = new Int16Array(samples * channels);\n for (let i = 0; i < data.length; i++) {\n data[i] = Math.sin((i / samples) * Math.PI * 2) * 16000;\n }\n return new AudioFrame(data, sampleRate, channels, samples);\n };\n\n const streamToArray = async (stream: ReadableStream<AudioFrame>): Promise<AudioFrame[]> => {\n const reader = stream.getReader();\n const chunks: AudioFrame[] = [];\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n return chunks;\n };\n\n it('should resample audio frames to target sample rate', async () => {\n const inputRate = 48000;\n const outputRate = 16000;\n const inputFrame = createAudioFrame(inputRate, 960); // 20ms at 48kHz\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(inputFrame);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(outputRate);\n expect(frame.channels).toBe(inputFrame.channels);\n }\n });\n\n it('should handle same input and output rate', async () => {\n const sampleRate = 44100;\n const inputFrame = createAudioFrame(sampleRate, 1024);\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(inputFrame);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate: sampleRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(sampleRate);\n expect(frame.channels).toBe(inputFrame.channels);\n }\n });\n\n it('should handle multiple input frames', async () => {\n const inputRate = 32000;\n const outputRate = 48000;\n const frame1 = createAudioFrame(inputRate, 640);\n const frame2 = createAudioFrame(inputRate, 640);\n\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.enqueue(frame1);\n controller.enqueue(frame2);\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames.length).toBeGreaterThan(0);\n\n for (const frame of outputFrames) {\n expect(frame.sampleRate).toBe(outputRate);\n expect(frame.channels).toBe(frame1.channels);\n }\n });\n\n it('should handle empty stream', async () => {\n const inputStream = new ReadableStream<AudioFrame>({\n start(controller) {\n controller.close();\n },\n });\n\n const outputStream = resampleStream({ stream: inputStream, outputRate: 44100 });\n const outputFrames = await streamToArray(outputStream);\n\n expect(outputFrames).toEqual([]);\n });\n });\n});\n"],"mappings":"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","names":["parentCurrent","childCurrent"]}
package/dist/vad.cjs CHANGED
@@ -43,6 +43,9 @@ class VAD extends import_node_events.EventEmitter {
43
43
  get capabilities() {
44
44
  return this.#capabilities;
45
45
  }
46
+ async close() {
47
+ return;
48
+ }
46
49
  }
47
50
  class VADStream {
48
51
  static FLUSH_SENTINEL = Symbol("FLUSH_SENTINEL");
@@ -54,13 +57,14 @@ class VADStream {
54
57
  outputReader;
55
58
  closed = false;
56
59
  inputClosed = false;
57
- #vad;
58
- #lastActivityTime = BigInt(0);
59
- logger = (0, import_log.log)();
60
+ vad;
61
+ lastActivityTime = BigInt(0);
62
+ logger;
60
63
  deferredInputStream;
61
64
  metricsStream;
62
65
  constructor(vad) {
63
- this.#vad = vad;
66
+ this.logger = (0, import_log.log)();
67
+ this.vad = vad;
64
68
  this.deferredInputStream = new import_deferred_stream.DeferredReadableStream();
65
69
  this.inputWriter = this.input.writable.getWriter();
66
70
  this.inputReader = this.input.readable.getReader();
@@ -94,7 +98,7 @@ class VADStream {
94
98
  }
95
99
  }
96
100
  async monitorMetrics() {
97
- let inferenceDurationTotal = 0;
101
+ let inferenceDurationTotalMs = 0;
98
102
  let inferenceCount = 0;
99
103
  const metricsReader = this.metricsStream.getReader();
100
104
  while (true) {
@@ -105,31 +109,47 @@ class VADStream {
105
109
  switch (value.type) {
106
110
  case 0 /* START_OF_SPEECH */:
107
111
  inferenceCount++;
108
- if (inferenceCount >= 1 / this.#vad.capabilities.updateInterval) {
109
- this.#vad.emit("metrics_collected", {
112
+ if (inferenceCount >= 1e3 / this.vad.capabilities.updateInterval) {
113
+ this.vad.emit("metrics_collected", {
110
114
  type: "vad_metrics",
111
115
  timestamp: Date.now(),
112
- idleTime: Math.trunc(
113
- Number((process.hrtime.bigint() - this.#lastActivityTime) / BigInt(1e6))
116
+ idleTimeMs: Math.trunc(
117
+ Number((process.hrtime.bigint() - this.lastActivityTime) / BigInt(1e6))
114
118
  ),
115
- inferenceDurationTotal,
119
+ inferenceDurationTotalMs,
116
120
  inferenceCount,
117
- label: this.#vad.label
121
+ label: this.vad.label
118
122
  });
119
123
  inferenceCount = 0;
120
- inferenceDurationTotal = 0;
124
+ inferenceDurationTotalMs = 0;
121
125
  }
122
126
  break;
123
127
  case 1 /* INFERENCE_DONE */:
124
- inferenceDurationTotal += value.inferenceDuration;
125
- this.#lastActivityTime = process.hrtime.bigint();
128
+ inferenceDurationTotalMs += Math.round(value.inferenceDuration);
129
+ this.lastActivityTime = process.hrtime.bigint();
126
130
  break;
127
131
  case 2 /* END_OF_SPEECH */:
128
- this.#lastActivityTime = process.hrtime.bigint();
132
+ this.lastActivityTime = process.hrtime.bigint();
129
133
  break;
130
134
  }
131
135
  }
132
136
  }
137
+ /**
138
+ * Safely send a VAD event to the output stream, handling writer release errors during shutdown.
139
+ * @returns true if the event was sent, false if the stream is closing
140
+ * @throws Error if an unexpected error occurs
141
+ */
142
+ sendVADEvent(event) {
143
+ if (this.closed) {
144
+ return false;
145
+ }
146
+ try {
147
+ this.outputWriter.write(event);
148
+ return true;
149
+ } catch (e) {
150
+ throw e;
151
+ }
152
+ }
133
153
  updateInputStream(audioStream) {
134
154
  this.deferredInputStream.setSource(audioStream);
135
155
  }
package/dist/vad.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vad.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport type {\n ReadableStream,\n ReadableStreamDefaultReader,\n WritableStreamDefaultWriter,\n} from 'node:stream/web';\nimport { log } from './log.js';\nimport type { VADMetrics } from './metrics/base.js';\nimport { DeferredReadableStream } from './stream/deferred_stream.js';\nimport { IdentityTransform } from './stream/identity_transform.js';\n\nexport enum VADEventType {\n START_OF_SPEECH,\n INFERENCE_DONE,\n END_OF_SPEECH,\n METRICS_COLLECTED,\n}\n\nexport interface VADEvent {\n /** Type of the VAD event (e.g., start of speech, end of speech, inference done). */\n type: VADEventType;\n /**\n * Index of the audio sample where the event occurred, relative to the inference sample rate.\n */\n samplesIndex: number;\n /** Timestamp when the event was fired. */\n timestamp: number;\n /** Duration of the speech segment. */\n speechDuration: number;\n /** Duration of the silence segment. */\n silenceDuration: number;\n /**\n * List of audio frames associated with the speech.\n *\n * @remarks\n * - For `start_of_speech` events, this contains the audio chunks that triggered the detection.\n * - For `inference_done` events, this contains the audio chunks that were processed.\n * - For `end_of_speech` events, this contains the complete user speech.\n */\n frames: AudioFrame[];\n /** Probability that speech is present (only for `INFERENCE_DONE` events). */\n probability: number;\n /** Time taken to perform the inference, in seconds (only for `INFERENCE_DONE` events). */\n inferenceDuration: number;\n /** Indicates whether speech was detected in the frames. */\n speaking: boolean;\n /** Threshold used to detect silence. */\n rawAccumulatedSilence: number;\n /** Threshold used to detect speech. */\n rawAccumulatedSpeech: number;\n}\n\nexport interface VADCapabilities {\n updateInterval: number;\n}\n\nexport type VADCallbacks = {\n ['metrics_collected']: (metrics: VADMetrics) => void;\n};\n\nexport abstract class VAD extends (EventEmitter as new () => TypedEmitter<VADCallbacks>) {\n #capabilities: VADCapabilities;\n abstract label: string;\n\n constructor(capabilities: VADCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n get capabilities(): VADCapabilities {\n return this.#capabilities;\n }\n\n /**\n * Returns a {@link VADStream} that can be used to push audio frames and receive VAD events.\n */\n abstract stream(): VADStream;\n}\n\nexport abstract class VADStream implements AsyncIterableIterator<VADEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new IdentityTransform<AudioFrame | typeof VADStream.FLUSH_SENTINEL>();\n protected output = new IdentityTransform<VADEvent>();\n protected inputWriter: WritableStreamDefaultWriter<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;\n protected inputReader: ReadableStreamDefaultReader<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;\n protected outputWriter: WritableStreamDefaultWriter<VADEvent>;\n protected outputReader: ReadableStreamDefaultReader<VADEvent>;\n protected closed = false;\n protected inputClosed = false;\n\n #vad: VAD;\n #lastActivityTime = BigInt(0);\n private logger = log();\n private deferredInputStream: DeferredReadableStream<AudioFrame>;\n\n private metricsStream: ReadableStream<VADEvent>;\n constructor(vad: VAD) {\n this.#vad = vad;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n\n this.inputWriter = this.input.writable.getWriter();\n this.inputReader = this.input.readable.getReader();\n this.outputWriter = this.output.writable.getWriter();\n\n const [outputStream, metricsStream] = this.output.readable.tee();\n this.metricsStream = metricsStream;\n this.outputReader = outputStream.getReader();\n\n this.pumpDeferredStream();\n this.monitorMetrics();\n }\n\n /**\n * Reads from the deferred input stream and forwards chunks to the input writer.\n *\n * Note: we can't just do this.deferredInputStream.stream.pipeTo(this.input.writable)\n * because the inputWriter locks the this.input.writable stream. All writes must go through\n * the inputWriter.\n */\n private async pumpDeferredStream() {\n const reader = this.deferredInputStream.stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n await this.inputWriter.write(value);\n }\n } catch (e) {\n this.logger.error(`Error pumping deferred stream: ${e}`);\n throw e;\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n let inferenceDurationTotal = 0;\n let inferenceCount = 0;\n const metricsReader = this.metricsStream.getReader();\n while (true) {\n const { done, value } = await metricsReader.read();\n if (done) {\n break;\n }\n switch (value.type) {\n case VADEventType.START_OF_SPEECH:\n inferenceCount++;\n if (inferenceCount >= 1 / this.#vad.capabilities.updateInterval) {\n this.#vad.emit('metrics_collected', {\n type: 'vad_metrics',\n timestamp: Date.now(),\n idleTime: Math.trunc(\n Number((process.hrtime.bigint() - this.#lastActivityTime) / BigInt(1000000)),\n ),\n inferenceDurationTotal,\n inferenceCount,\n label: this.#vad.label,\n });\n\n inferenceCount = 0;\n inferenceDurationTotal = 0;\n }\n break;\n case VADEventType.INFERENCE_DONE:\n inferenceDurationTotal += value.inferenceDuration;\n this.#lastActivityTime = process.hrtime.bigint();\n break;\n case VADEventType.END_OF_SPEECH:\n this.#lastActivityTime = process.hrtime.bigint();\n break;\n }\n }\n }\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** @deprecated Use `updateInputStream` instead */\n pushFrame(frame: AudioFrame) {\n // TODO(AJS-395): remove this method\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputWriter.write(frame);\n }\n\n flush() {\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputWriter.write(VADStream.FLUSH_SENTINEL);\n }\n\n endInput() {\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputClosed = true;\n this.input.writable.close();\n }\n\n async next(): Promise<IteratorResult<VADEvent>> {\n return this.outputReader.read().then(({ done, value }) => {\n if (done) {\n return { done: true, value: undefined };\n }\n return { done: false, value };\n });\n }\n\n close() {\n this.outputWriter.releaseLock();\n this.outputReader.cancel();\n this.output.writable.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): VADStream {\n return this;\n }\n}\n"],"mappings":"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","names":["VADEventType"]}
1
+ {"version":3,"sources":["../src/vad.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport type {\n ReadableStream,\n ReadableStreamDefaultReader,\n WritableStreamDefaultWriter,\n} from 'node:stream/web';\nimport { log } from './log.js';\nimport type { VADMetrics } from './metrics/base.js';\nimport { DeferredReadableStream } from './stream/deferred_stream.js';\nimport { IdentityTransform } from './stream/identity_transform.js';\n\nexport enum VADEventType {\n START_OF_SPEECH,\n INFERENCE_DONE,\n END_OF_SPEECH,\n METRICS_COLLECTED,\n}\n\nexport interface VADEvent {\n /** Type of the VAD event (e.g., start of speech, end of speech, inference done). */\n type: VADEventType;\n /**\n * Index of the audio sample where the event occurred, relative to the inference sample rate.\n */\n samplesIndex: number;\n /** Timestamp when the event was fired. */\n timestamp: number;\n /** Duration of the speech segment in seconds. */\n speechDuration: number;\n /** Duration of the silence segment in seconds. */\n silenceDuration: number;\n /**\n * List of audio frames associated with the speech.\n *\n * @remarks\n * - For `start_of_speech` events, this contains the audio chunks that triggered the detection.\n * - For `inference_done` events, this contains the audio chunks that were processed.\n * - For `end_of_speech` events, this contains the complete user speech.\n */\n frames: AudioFrame[];\n /** Probability that speech is present (only for `INFERENCE_DONE` events). */\n probability: number;\n /** Time taken to perform the inference, in seconds (only for `INFERENCE_DONE` events). */\n inferenceDuration: number;\n /** Indicates whether speech was detected in the frames. */\n speaking: boolean;\n /** Threshold used to detect silence. */\n rawAccumulatedSilence: number;\n /** Threshold used to detect speech. */\n rawAccumulatedSpeech: number;\n}\n\nexport interface VADCapabilities {\n /** Duration of each VAD inference window in milliseconds. Used to batch metrics emissions to roughly once per second. */\n updateInterval: number;\n}\n\nexport type VADCallbacks = {\n ['metrics_collected']: (metrics: VADMetrics) => void;\n};\n\nexport abstract class VAD extends (EventEmitter as new () => TypedEmitter<VADCallbacks>) {\n #capabilities: VADCapabilities;\n abstract label: string;\n\n constructor(capabilities: VADCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n get capabilities(): VADCapabilities {\n return this.#capabilities;\n }\n\n /**\n * Returns a {@link VADStream} that can be used to push audio frames and receive VAD events.\n */\n abstract stream(): VADStream;\n\n async close(): Promise<void> {\n return;\n }\n}\n\nexport abstract class VADStream implements AsyncIterableIterator<VADEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new IdentityTransform<AudioFrame | typeof VADStream.FLUSH_SENTINEL>();\n protected output = new IdentityTransform<VADEvent>();\n protected inputWriter: WritableStreamDefaultWriter<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;\n protected inputReader: ReadableStreamDefaultReader<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;\n protected outputWriter: WritableStreamDefaultWriter<VADEvent>;\n protected outputReader: ReadableStreamDefaultReader<VADEvent>;\n protected closed = false;\n protected inputClosed = false;\n\n protected vad: VAD;\n protected lastActivityTime = BigInt(0);\n protected logger;\n protected deferredInputStream: DeferredReadableStream<AudioFrame>;\n\n private metricsStream: ReadableStream<VADEvent>;\n constructor(vad: VAD) {\n this.logger = log();\n this.vad = vad;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n\n this.inputWriter = this.input.writable.getWriter();\n this.inputReader = this.input.readable.getReader();\n this.outputWriter = this.output.writable.getWriter();\n\n const [outputStream, metricsStream] = this.output.readable.tee();\n this.metricsStream = metricsStream;\n this.outputReader = outputStream.getReader();\n\n this.pumpDeferredStream();\n this.monitorMetrics();\n }\n\n /**\n * Reads from the deferred input stream and forwards chunks to the input writer.\n *\n * Note: we can't just do this.deferredInputStream.stream.pipeTo(this.input.writable)\n * because the inputWriter locks the this.input.writable stream. All writes must go through\n * the inputWriter.\n */\n private async pumpDeferredStream() {\n const reader = this.deferredInputStream.stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n await this.inputWriter.write(value);\n }\n } catch (e) {\n this.logger.error(`Error pumping deferred stream: ${e}`);\n throw e;\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n let inferenceDurationTotalMs = 0;\n let inferenceCount = 0;\n const metricsReader = this.metricsStream.getReader();\n while (true) {\n const { done, value } = await metricsReader.read();\n if (done) {\n break;\n }\n switch (value.type) {\n case VADEventType.START_OF_SPEECH:\n inferenceCount++;\n if (inferenceCount >= 1000 / this.vad.capabilities.updateInterval) {\n this.vad.emit('metrics_collected', {\n type: 'vad_metrics',\n timestamp: Date.now(),\n idleTimeMs: Math.trunc(\n Number((process.hrtime.bigint() - this.lastActivityTime) / BigInt(1000000)),\n ),\n inferenceDurationTotalMs,\n inferenceCount,\n label: this.vad.label,\n });\n\n inferenceCount = 0;\n inferenceDurationTotalMs = 0;\n }\n break;\n case VADEventType.INFERENCE_DONE:\n inferenceDurationTotalMs += Math.round(value.inferenceDuration);\n this.lastActivityTime = process.hrtime.bigint();\n break;\n case VADEventType.END_OF_SPEECH:\n this.lastActivityTime = process.hrtime.bigint();\n break;\n }\n }\n }\n\n /**\n * Safely send a VAD event to the output stream, handling writer release errors during shutdown.\n * @returns true if the event was sent, false if the stream is closing\n * @throws Error if an unexpected error occurs\n */\n protected sendVADEvent(event: VADEvent): boolean {\n if (this.closed) {\n return false;\n }\n\n try {\n this.outputWriter.write(event);\n return true;\n } catch (e) {\n throw e;\n }\n }\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** @deprecated Use `updateInputStream` instead */\n pushFrame(frame: AudioFrame) {\n // TODO(AJS-395): remove this method\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputWriter.write(frame);\n }\n\n flush() {\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputWriter.write(VADStream.FLUSH_SENTINEL);\n }\n\n endInput() {\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputClosed = true;\n this.input.writable.close();\n }\n\n async next(): Promise<IteratorResult<VADEvent>> {\n return this.outputReader.read().then(({ done, value }) => {\n if (done) {\n return { done: true, value: undefined };\n }\n return { done: false, value };\n });\n }\n\n close() {\n this.outputWriter.releaseLock();\n this.outputReader.cancel();\n this.output.writable.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): VADStream {\n return this;\n }\n}\n"],"mappings":"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","names":["VADEventType"]}
package/dist/vad.d.cts CHANGED
@@ -3,6 +3,7 @@ import type { AudioFrame } from '@livekit/rtc-node';
3
3
  import type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';
4
4
  import type { ReadableStream, ReadableStreamDefaultReader, WritableStreamDefaultWriter } from 'node:stream/web';
5
5
  import type { VADMetrics } from './metrics/base.js';
6
+ import { DeferredReadableStream } from './stream/deferred_stream.js';
6
7
  import { IdentityTransform } from './stream/identity_transform.js';
7
8
  export declare enum VADEventType {
8
9
  START_OF_SPEECH = 0,
@@ -19,9 +20,9 @@ export interface VADEvent {
19
20
  samplesIndex: number;
20
21
  /** Timestamp when the event was fired. */
21
22
  timestamp: number;
22
- /** Duration of the speech segment. */
23
+ /** Duration of the speech segment in seconds. */
23
24
  speechDuration: number;
24
- /** Duration of the silence segment. */
25
+ /** Duration of the silence segment in seconds. */
25
26
  silenceDuration: number;
26
27
  /**
27
28
  * List of audio frames associated with the speech.
@@ -44,6 +45,7 @@ export interface VADEvent {
44
45
  rawAccumulatedSpeech: number;
45
46
  }
46
47
  export interface VADCapabilities {
48
+ /** Duration of each VAD inference window in milliseconds. Used to batch metrics emissions to roughly once per second. */
47
49
  updateInterval: number;
48
50
  }
49
51
  export type VADCallbacks = {
@@ -59,9 +61,9 @@ export declare abstract class VAD extends VAD_base {
59
61
  * Returns a {@link VADStream} that can be used to push audio frames and receive VAD events.
60
62
  */
61
63
  abstract stream(): VADStream;
64
+ close(): Promise<void>;
62
65
  }
63
66
  export declare abstract class VADStream implements AsyncIterableIterator<VADEvent> {
64
- #private;
65
67
  protected static readonly FLUSH_SENTINEL: unique symbol;
66
68
  protected input: IdentityTransform<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;
67
69
  protected output: IdentityTransform<VADEvent>;
@@ -71,8 +73,10 @@ export declare abstract class VADStream implements AsyncIterableIterator<VADEven
71
73
  protected outputReader: ReadableStreamDefaultReader<VADEvent>;
72
74
  protected closed: boolean;
73
75
  protected inputClosed: boolean;
74
- private logger;
75
- private deferredInputStream;
76
+ protected vad: VAD;
77
+ protected lastActivityTime: bigint;
78
+ protected logger: import("pino").Logger;
79
+ protected deferredInputStream: DeferredReadableStream<AudioFrame>;
76
80
  private metricsStream;
77
81
  constructor(vad: VAD);
78
82
  /**
@@ -84,6 +88,12 @@ export declare abstract class VADStream implements AsyncIterableIterator<VADEven
84
88
  */
85
89
  private pumpDeferredStream;
86
90
  protected monitorMetrics(): Promise<void>;
91
+ /**
92
+ * Safely send a VAD event to the output stream, handling writer release errors during shutdown.
93
+ * @returns true if the event was sent, false if the stream is closing
94
+ * @throws Error if an unexpected error occurs
95
+ */
96
+ protected sendVADEvent(event: VADEvent): boolean;
87
97
  updateInputStream(audioStream: ReadableStream<AudioFrame>): void;
88
98
  detachInputStream(): void;
89
99
  /** @deprecated Use `updateInputStream` instead */
package/dist/vad.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { AudioFrame } from '@livekit/rtc-node';
3
3
  import type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';
4
4
  import type { ReadableStream, ReadableStreamDefaultReader, WritableStreamDefaultWriter } from 'node:stream/web';
5
5
  import type { VADMetrics } from './metrics/base.js';
6
+ import { DeferredReadableStream } from './stream/deferred_stream.js';
6
7
  import { IdentityTransform } from './stream/identity_transform.js';
7
8
  export declare enum VADEventType {
8
9
  START_OF_SPEECH = 0,
@@ -19,9 +20,9 @@ export interface VADEvent {
19
20
  samplesIndex: number;
20
21
  /** Timestamp when the event was fired. */
21
22
  timestamp: number;
22
- /** Duration of the speech segment. */
23
+ /** Duration of the speech segment in seconds. */
23
24
  speechDuration: number;
24
- /** Duration of the silence segment. */
25
+ /** Duration of the silence segment in seconds. */
25
26
  silenceDuration: number;
26
27
  /**
27
28
  * List of audio frames associated with the speech.
@@ -44,6 +45,7 @@ export interface VADEvent {
44
45
  rawAccumulatedSpeech: number;
45
46
  }
46
47
  export interface VADCapabilities {
48
+ /** Duration of each VAD inference window in milliseconds. Used to batch metrics emissions to roughly once per second. */
47
49
  updateInterval: number;
48
50
  }
49
51
  export type VADCallbacks = {
@@ -59,9 +61,9 @@ export declare abstract class VAD extends VAD_base {
59
61
  * Returns a {@link VADStream} that can be used to push audio frames and receive VAD events.
60
62
  */
61
63
  abstract stream(): VADStream;
64
+ close(): Promise<void>;
62
65
  }
63
66
  export declare abstract class VADStream implements AsyncIterableIterator<VADEvent> {
64
- #private;
65
67
  protected static readonly FLUSH_SENTINEL: unique symbol;
66
68
  protected input: IdentityTransform<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;
67
69
  protected output: IdentityTransform<VADEvent>;
@@ -71,8 +73,10 @@ export declare abstract class VADStream implements AsyncIterableIterator<VADEven
71
73
  protected outputReader: ReadableStreamDefaultReader<VADEvent>;
72
74
  protected closed: boolean;
73
75
  protected inputClosed: boolean;
74
- private logger;
75
- private deferredInputStream;
76
+ protected vad: VAD;
77
+ protected lastActivityTime: bigint;
78
+ protected logger: import("pino").Logger;
79
+ protected deferredInputStream: DeferredReadableStream<AudioFrame>;
76
80
  private metricsStream;
77
81
  constructor(vad: VAD);
78
82
  /**
@@ -84,6 +88,12 @@ export declare abstract class VADStream implements AsyncIterableIterator<VADEven
84
88
  */
85
89
  private pumpDeferredStream;
86
90
  protected monitorMetrics(): Promise<void>;
91
+ /**
92
+ * Safely send a VAD event to the output stream, handling writer release errors during shutdown.
93
+ * @returns true if the event was sent, false if the stream is closing
94
+ * @throws Error if an unexpected error occurs
95
+ */
96
+ protected sendVADEvent(event: VADEvent): boolean;
87
97
  updateInputStream(audioStream: ReadableStream<AudioFrame>): void;
88
98
  detachInputStream(): void;
89
99
  /** @deprecated Use `updateInputStream` instead */
package/dist/vad.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vad.d.ts","sourceRoot":"","sources":["../src/vad.ts"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,IAAI,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,KAAK,EACV,cAAc,EACd,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,oBAAY,YAAY;IACtB,eAAe,IAAA;IACf,cAAc,IAAA;IACd,aAAa,IAAA;IACb,iBAAiB,IAAA;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,oFAAoF;IACpF,IAAI,EAAE,YAAY,CAAC;IACnB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,0FAA0F;IAC1F,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,EAAE,OAAO,CAAC;IAClB,wCAAwC;IACxC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,uCAAuC;IACvC,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;CACtD,CAAC;kCAE2D,aAAa,YAAY,CAAC;AAAvF,8BAAsB,GAAI,SAAQ,QAAsD;;IAEtF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,YAAY,EAAE,eAAe;IAKzC,IAAI,YAAY,IAAI,eAAe,CAElC;IAED;;OAEG;IACH,QAAQ,CAAC,MAAM,IAAI,SAAS;CAC7B;AAED,8BAAsB,SAAU,YAAW,qBAAqB,CAAC,QAAQ,CAAC;;IACxE,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,gBAA4B;IACpE,SAAS,CAAC,KAAK,kEAAyE;IACxF,SAAS,CAAC,MAAM,8BAAqC;IACrD,SAAS,CAAC,WAAW,EAAE,2BAA2B,CAAC,UAAU,GAAG,OAAO,SAAS,CAAC,cAAc,CAAC,CAAC;IACjG,SAAS,CAAC,WAAW,EAAE,2BAA2B,CAAC,UAAU,GAAG,OAAO,SAAS,CAAC,cAAc,CAAC,CAAC;IACjG,SAAS,CAAC,YAAY,EAAE,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IAC9D,SAAS,CAAC,YAAY,EAAE,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IAC9D,SAAS,CAAC,MAAM,UAAS;IACzB,SAAS,CAAC,WAAW,UAAS;IAI9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,mBAAmB,CAAqC;IAEhE,OAAO,CAAC,aAAa,CAA2B;gBACpC,GAAG,EAAE,GAAG;IAgBpB;;;;;;OAMG;YACW,kBAAkB;cAgBhB,cAAc;IAuC9B,iBAAiB,CAAC,WAAW,EAAE,cAAc,CAAC,UAAU,CAAC;IAIzD,iBAAiB;IAIjB,kDAAkD;IAClD,SAAS,CAAC,KAAK,EAAE,UAAU;IAW3B,KAAK;IAUL,QAAQ;IAWF,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAS/C,KAAK;IAOL,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,SAAS;CAGpC"}
1
+ {"version":3,"file":"vad.d.ts","sourceRoot":"","sources":["../src/vad.ts"],"names":[],"mappings":"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"}
package/dist/vad.js CHANGED
@@ -18,6 +18,9 @@ class VAD extends EventEmitter {
18
18
  get capabilities() {
19
19
  return this.#capabilities;
20
20
  }
21
+ async close() {
22
+ return;
23
+ }
21
24
  }
22
25
  class VADStream {
23
26
  static FLUSH_SENTINEL = Symbol("FLUSH_SENTINEL");
@@ -29,13 +32,14 @@ class VADStream {
29
32
  outputReader;
30
33
  closed = false;
31
34
  inputClosed = false;
32
- #vad;
33
- #lastActivityTime = BigInt(0);
34
- logger = log();
35
+ vad;
36
+ lastActivityTime = BigInt(0);
37
+ logger;
35
38
  deferredInputStream;
36
39
  metricsStream;
37
40
  constructor(vad) {
38
- this.#vad = vad;
41
+ this.logger = log();
42
+ this.vad = vad;
39
43
  this.deferredInputStream = new DeferredReadableStream();
40
44
  this.inputWriter = this.input.writable.getWriter();
41
45
  this.inputReader = this.input.readable.getReader();
@@ -69,7 +73,7 @@ class VADStream {
69
73
  }
70
74
  }
71
75
  async monitorMetrics() {
72
- let inferenceDurationTotal = 0;
76
+ let inferenceDurationTotalMs = 0;
73
77
  let inferenceCount = 0;
74
78
  const metricsReader = this.metricsStream.getReader();
75
79
  while (true) {
@@ -80,31 +84,47 @@ class VADStream {
80
84
  switch (value.type) {
81
85
  case 0 /* START_OF_SPEECH */:
82
86
  inferenceCount++;
83
- if (inferenceCount >= 1 / this.#vad.capabilities.updateInterval) {
84
- this.#vad.emit("metrics_collected", {
87
+ if (inferenceCount >= 1e3 / this.vad.capabilities.updateInterval) {
88
+ this.vad.emit("metrics_collected", {
85
89
  type: "vad_metrics",
86
90
  timestamp: Date.now(),
87
- idleTime: Math.trunc(
88
- Number((process.hrtime.bigint() - this.#lastActivityTime) / BigInt(1e6))
91
+ idleTimeMs: Math.trunc(
92
+ Number((process.hrtime.bigint() - this.lastActivityTime) / BigInt(1e6))
89
93
  ),
90
- inferenceDurationTotal,
94
+ inferenceDurationTotalMs,
91
95
  inferenceCount,
92
- label: this.#vad.label
96
+ label: this.vad.label
93
97
  });
94
98
  inferenceCount = 0;
95
- inferenceDurationTotal = 0;
99
+ inferenceDurationTotalMs = 0;
96
100
  }
97
101
  break;
98
102
  case 1 /* INFERENCE_DONE */:
99
- inferenceDurationTotal += value.inferenceDuration;
100
- this.#lastActivityTime = process.hrtime.bigint();
103
+ inferenceDurationTotalMs += Math.round(value.inferenceDuration);
104
+ this.lastActivityTime = process.hrtime.bigint();
101
105
  break;
102
106
  case 2 /* END_OF_SPEECH */:
103
- this.#lastActivityTime = process.hrtime.bigint();
107
+ this.lastActivityTime = process.hrtime.bigint();
104
108
  break;
105
109
  }
106
110
  }
107
111
  }
112
+ /**
113
+ * Safely send a VAD event to the output stream, handling writer release errors during shutdown.
114
+ * @returns true if the event was sent, false if the stream is closing
115
+ * @throws Error if an unexpected error occurs
116
+ */
117
+ sendVADEvent(event) {
118
+ if (this.closed) {
119
+ return false;
120
+ }
121
+ try {
122
+ this.outputWriter.write(event);
123
+ return true;
124
+ } catch (e) {
125
+ throw e;
126
+ }
127
+ }
108
128
  updateInputStream(audioStream) {
109
129
  this.deferredInputStream.setSource(audioStream);
110
130
  }
package/dist/vad.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vad.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport type {\n ReadableStream,\n ReadableStreamDefaultReader,\n WritableStreamDefaultWriter,\n} from 'node:stream/web';\nimport { log } from './log.js';\nimport type { VADMetrics } from './metrics/base.js';\nimport { DeferredReadableStream } from './stream/deferred_stream.js';\nimport { IdentityTransform } from './stream/identity_transform.js';\n\nexport enum VADEventType {\n START_OF_SPEECH,\n INFERENCE_DONE,\n END_OF_SPEECH,\n METRICS_COLLECTED,\n}\n\nexport interface VADEvent {\n /** Type of the VAD event (e.g., start of speech, end of speech, inference done). */\n type: VADEventType;\n /**\n * Index of the audio sample where the event occurred, relative to the inference sample rate.\n */\n samplesIndex: number;\n /** Timestamp when the event was fired. */\n timestamp: number;\n /** Duration of the speech segment. */\n speechDuration: number;\n /** Duration of the silence segment. */\n silenceDuration: number;\n /**\n * List of audio frames associated with the speech.\n *\n * @remarks\n * - For `start_of_speech` events, this contains the audio chunks that triggered the detection.\n * - For `inference_done` events, this contains the audio chunks that were processed.\n * - For `end_of_speech` events, this contains the complete user speech.\n */\n frames: AudioFrame[];\n /** Probability that speech is present (only for `INFERENCE_DONE` events). */\n probability: number;\n /** Time taken to perform the inference, in seconds (only for `INFERENCE_DONE` events). */\n inferenceDuration: number;\n /** Indicates whether speech was detected in the frames. */\n speaking: boolean;\n /** Threshold used to detect silence. */\n rawAccumulatedSilence: number;\n /** Threshold used to detect speech. */\n rawAccumulatedSpeech: number;\n}\n\nexport interface VADCapabilities {\n updateInterval: number;\n}\n\nexport type VADCallbacks = {\n ['metrics_collected']: (metrics: VADMetrics) => void;\n};\n\nexport abstract class VAD extends (EventEmitter as new () => TypedEmitter<VADCallbacks>) {\n #capabilities: VADCapabilities;\n abstract label: string;\n\n constructor(capabilities: VADCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n get capabilities(): VADCapabilities {\n return this.#capabilities;\n }\n\n /**\n * Returns a {@link VADStream} that can be used to push audio frames and receive VAD events.\n */\n abstract stream(): VADStream;\n}\n\nexport abstract class VADStream implements AsyncIterableIterator<VADEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new IdentityTransform<AudioFrame | typeof VADStream.FLUSH_SENTINEL>();\n protected output = new IdentityTransform<VADEvent>();\n protected inputWriter: WritableStreamDefaultWriter<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;\n protected inputReader: ReadableStreamDefaultReader<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;\n protected outputWriter: WritableStreamDefaultWriter<VADEvent>;\n protected outputReader: ReadableStreamDefaultReader<VADEvent>;\n protected closed = false;\n protected inputClosed = false;\n\n #vad: VAD;\n #lastActivityTime = BigInt(0);\n private logger = log();\n private deferredInputStream: DeferredReadableStream<AudioFrame>;\n\n private metricsStream: ReadableStream<VADEvent>;\n constructor(vad: VAD) {\n this.#vad = vad;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n\n this.inputWriter = this.input.writable.getWriter();\n this.inputReader = this.input.readable.getReader();\n this.outputWriter = this.output.writable.getWriter();\n\n const [outputStream, metricsStream] = this.output.readable.tee();\n this.metricsStream = metricsStream;\n this.outputReader = outputStream.getReader();\n\n this.pumpDeferredStream();\n this.monitorMetrics();\n }\n\n /**\n * Reads from the deferred input stream and forwards chunks to the input writer.\n *\n * Note: we can't just do this.deferredInputStream.stream.pipeTo(this.input.writable)\n * because the inputWriter locks the this.input.writable stream. All writes must go through\n * the inputWriter.\n */\n private async pumpDeferredStream() {\n const reader = this.deferredInputStream.stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n await this.inputWriter.write(value);\n }\n } catch (e) {\n this.logger.error(`Error pumping deferred stream: ${e}`);\n throw e;\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n let inferenceDurationTotal = 0;\n let inferenceCount = 0;\n const metricsReader = this.metricsStream.getReader();\n while (true) {\n const { done, value } = await metricsReader.read();\n if (done) {\n break;\n }\n switch (value.type) {\n case VADEventType.START_OF_SPEECH:\n inferenceCount++;\n if (inferenceCount >= 1 / this.#vad.capabilities.updateInterval) {\n this.#vad.emit('metrics_collected', {\n type: 'vad_metrics',\n timestamp: Date.now(),\n idleTime: Math.trunc(\n Number((process.hrtime.bigint() - this.#lastActivityTime) / BigInt(1000000)),\n ),\n inferenceDurationTotal,\n inferenceCount,\n label: this.#vad.label,\n });\n\n inferenceCount = 0;\n inferenceDurationTotal = 0;\n }\n break;\n case VADEventType.INFERENCE_DONE:\n inferenceDurationTotal += value.inferenceDuration;\n this.#lastActivityTime = process.hrtime.bigint();\n break;\n case VADEventType.END_OF_SPEECH:\n this.#lastActivityTime = process.hrtime.bigint();\n break;\n }\n }\n }\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** @deprecated Use `updateInputStream` instead */\n pushFrame(frame: AudioFrame) {\n // TODO(AJS-395): remove this method\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputWriter.write(frame);\n }\n\n flush() {\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputWriter.write(VADStream.FLUSH_SENTINEL);\n }\n\n endInput() {\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputClosed = true;\n this.input.writable.close();\n }\n\n async next(): Promise<IteratorResult<VADEvent>> {\n return this.outputReader.read().then(({ done, value }) => {\n if (done) {\n return { done: true, value: undefined };\n }\n return { done: false, value };\n });\n }\n\n close() {\n this.outputWriter.releaseLock();\n this.outputReader.cancel();\n this.output.writable.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): VADStream {\n return this;\n }\n}\n"],"mappings":"AAKA,SAAS,oBAAoB;AAM7B,SAAS,WAAW;AAEpB,SAAS,8BAA8B;AACvC,SAAS,yBAAyB;AAE3B,IAAK,eAAL,kBAAKA,kBAAL;AACL,EAAAA,4BAAA;AACA,EAAAA,4BAAA;AACA,EAAAA,4BAAA;AACA,EAAAA,4BAAA;AAJU,SAAAA;AAAA,GAAA;AAiDL,MAAe,YAAa,aAAsD;AAAA,EACvF;AAAA,EAGA,YAAY,cAA+B;AACzC,UAAM;AACN,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,IAAI,eAAgC;AAClC,WAAO,KAAK;AAAA,EACd;AAMF;AAEO,MAAe,UAAqD;AAAA,EACzE,OAA0B,iBAAiB,OAAO,gBAAgB;AAAA,EACxD,QAAQ,IAAI,kBAAgE;AAAA,EAC5E,SAAS,IAAI,kBAA4B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,cAAc;AAAA,EAExB;AAAA,EACA,oBAAoB,OAAO,CAAC;AAAA,EACpB,SAAS,IAAI;AAAA,EACb;AAAA,EAEA;AAAA,EACR,YAAY,KAAU;AACpB,SAAK,OAAO;AACZ,SAAK,sBAAsB,IAAI,uBAAmC;AAElE,SAAK,cAAc,KAAK,MAAM,SAAS,UAAU;AACjD,SAAK,cAAc,KAAK,MAAM,SAAS,UAAU;AACjD,SAAK,eAAe,KAAK,OAAO,SAAS,UAAU;AAEnD,UAAM,CAAC,cAAc,aAAa,IAAI,KAAK,OAAO,SAAS,IAAI;AAC/D,SAAK,gBAAgB;AACrB,SAAK,eAAe,aAAa,UAAU;AAE3C,SAAK,mBAAmB;AACxB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,qBAAqB;AACjC,UAAM,SAAS,KAAK,oBAAoB,OAAO,UAAU;AACzD,QAAI;AACF,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,KAAM;AACV,cAAM,KAAK,YAAY,MAAM,KAAK;AAAA,MACpC;AAAA,IACF,SAAS,GAAG;AACV,WAAK,OAAO,MAAM,kCAAkC,CAAC,EAAE;AACvD,YAAM;AAAA,IACR,UAAE;AACA,aAAO,YAAY;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,MAAgB,iBAAiB;AAC/B,QAAI,yBAAyB;AAC7B,QAAI,iBAAiB;AACrB,UAAM,gBAAgB,KAAK,cAAc,UAAU;AACnD,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,cAAc,KAAK;AACjD,UAAI,MAAM;AACR;AAAA,MACF;AACA,cAAQ,MAAM,MAAM;AAAA,QAClB,KAAK;AACH;AACA,cAAI,kBAAkB,IAAI,KAAK,KAAK,aAAa,gBAAgB;AAC/D,iBAAK,KAAK,KAAK,qBAAqB;AAAA,cAClC,MAAM;AAAA,cACN,WAAW,KAAK,IAAI;AAAA,cACpB,UAAU,KAAK;AAAA,gBACb,QAAQ,QAAQ,OAAO,OAAO,IAAI,KAAK,qBAAqB,OAAO,GAAO,CAAC;AAAA,cAC7E;AAAA,cACA;AAAA,cACA;AAAA,cACA,OAAO,KAAK,KAAK;AAAA,YACnB,CAAC;AAED,6BAAiB;AACjB,qCAAyB;AAAA,UAC3B;AACA;AAAA,QACF,KAAK;AACH,oCAA0B,MAAM;AAChC,eAAK,oBAAoB,QAAQ,OAAO,OAAO;AAC/C;AAAA,QACF,KAAK;AACH,eAAK,oBAAoB,QAAQ,OAAO,OAAO;AAC/C;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAAA,EAEA,kBAAkB,aAAyC;AACzD,SAAK,oBAAoB,UAAU,WAAW;AAAA,EAChD;AAAA,EAEA,oBAAoB;AAClB,SAAK,oBAAoB,aAAa;AAAA,EACxC;AAAA;AAAA,EAGA,UAAU,OAAmB;AAE3B,QAAI,KAAK,aAAa;AACpB,YAAM,IAAI,MAAM,iBAAiB;AAAA,IACnC;AACA,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,MAAM,kBAAkB;AAAA,IACpC;AACA,SAAK,YAAY,MAAM,KAAK;AAAA,EAC9B;AAAA,EAEA,QAAQ;AACN,QAAI,KAAK,aAAa;AACpB,YAAM,IAAI,MAAM,iBAAiB;AAAA,IACnC;AACA,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,MAAM,kBAAkB;AAAA,IACpC;AACA,SAAK,YAAY,MAAM,UAAU,cAAc;AAAA,EACjD;AAAA,EAEA,WAAW;AACT,QAAI,KAAK,aAAa;AACpB,YAAM,IAAI,MAAM,iBAAiB;AAAA,IACnC;AACA,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,MAAM,kBAAkB;AAAA,IACpC;AACA,SAAK,cAAc;AACnB,SAAK,MAAM,SAAS,MAAM;AAAA,EAC5B;AAAA,EAEA,MAAM,OAA0C;AAC9C,WAAO,KAAK,aAAa,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,MAAM,MAAM;AACxD,UAAI,MAAM;AACR,eAAO,EAAE,MAAM,MAAM,OAAO,OAAU;AAAA,MACxC;AACA,aAAO,EAAE,MAAM,OAAO,MAAM;AAAA,IAC9B,CAAC;AAAA,EACH;AAAA,EAEA,QAAQ;AACN,SAAK,aAAa,YAAY;AAC9B,SAAK,aAAa,OAAO;AACzB,SAAK,OAAO,SAAS,MAAM;AAC3B,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,CAAC,OAAO,aAAa,IAAe;AAClC,WAAO;AAAA,EACT;AACF;","names":["VADEventType"]}
1
+ {"version":3,"sources":["../src/vad.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport { EventEmitter } from 'node:events';\nimport type {\n ReadableStream,\n ReadableStreamDefaultReader,\n WritableStreamDefaultWriter,\n} from 'node:stream/web';\nimport { log } from './log.js';\nimport type { VADMetrics } from './metrics/base.js';\nimport { DeferredReadableStream } from './stream/deferred_stream.js';\nimport { IdentityTransform } from './stream/identity_transform.js';\n\nexport enum VADEventType {\n START_OF_SPEECH,\n INFERENCE_DONE,\n END_OF_SPEECH,\n METRICS_COLLECTED,\n}\n\nexport interface VADEvent {\n /** Type of the VAD event (e.g., start of speech, end of speech, inference done). */\n type: VADEventType;\n /**\n * Index of the audio sample where the event occurred, relative to the inference sample rate.\n */\n samplesIndex: number;\n /** Timestamp when the event was fired. */\n timestamp: number;\n /** Duration of the speech segment in seconds. */\n speechDuration: number;\n /** Duration of the silence segment in seconds. */\n silenceDuration: number;\n /**\n * List of audio frames associated with the speech.\n *\n * @remarks\n * - For `start_of_speech` events, this contains the audio chunks that triggered the detection.\n * - For `inference_done` events, this contains the audio chunks that were processed.\n * - For `end_of_speech` events, this contains the complete user speech.\n */\n frames: AudioFrame[];\n /** Probability that speech is present (only for `INFERENCE_DONE` events). */\n probability: number;\n /** Time taken to perform the inference, in seconds (only for `INFERENCE_DONE` events). */\n inferenceDuration: number;\n /** Indicates whether speech was detected in the frames. */\n speaking: boolean;\n /** Threshold used to detect silence. */\n rawAccumulatedSilence: number;\n /** Threshold used to detect speech. */\n rawAccumulatedSpeech: number;\n}\n\nexport interface VADCapabilities {\n /** Duration of each VAD inference window in milliseconds. Used to batch metrics emissions to roughly once per second. */\n updateInterval: number;\n}\n\nexport type VADCallbacks = {\n ['metrics_collected']: (metrics: VADMetrics) => void;\n};\n\nexport abstract class VAD extends (EventEmitter as new () => TypedEmitter<VADCallbacks>) {\n #capabilities: VADCapabilities;\n abstract label: string;\n\n constructor(capabilities: VADCapabilities) {\n super();\n this.#capabilities = capabilities;\n }\n\n get capabilities(): VADCapabilities {\n return this.#capabilities;\n }\n\n /**\n * Returns a {@link VADStream} that can be used to push audio frames and receive VAD events.\n */\n abstract stream(): VADStream;\n\n async close(): Promise<void> {\n return;\n }\n}\n\nexport abstract class VADStream implements AsyncIterableIterator<VADEvent> {\n protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');\n protected input = new IdentityTransform<AudioFrame | typeof VADStream.FLUSH_SENTINEL>();\n protected output = new IdentityTransform<VADEvent>();\n protected inputWriter: WritableStreamDefaultWriter<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;\n protected inputReader: ReadableStreamDefaultReader<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;\n protected outputWriter: WritableStreamDefaultWriter<VADEvent>;\n protected outputReader: ReadableStreamDefaultReader<VADEvent>;\n protected closed = false;\n protected inputClosed = false;\n\n protected vad: VAD;\n protected lastActivityTime = BigInt(0);\n protected logger;\n protected deferredInputStream: DeferredReadableStream<AudioFrame>;\n\n private metricsStream: ReadableStream<VADEvent>;\n constructor(vad: VAD) {\n this.logger = log();\n this.vad = vad;\n this.deferredInputStream = new DeferredReadableStream<AudioFrame>();\n\n this.inputWriter = this.input.writable.getWriter();\n this.inputReader = this.input.readable.getReader();\n this.outputWriter = this.output.writable.getWriter();\n\n const [outputStream, metricsStream] = this.output.readable.tee();\n this.metricsStream = metricsStream;\n this.outputReader = outputStream.getReader();\n\n this.pumpDeferredStream();\n this.monitorMetrics();\n }\n\n /**\n * Reads from the deferred input stream and forwards chunks to the input writer.\n *\n * Note: we can't just do this.deferredInputStream.stream.pipeTo(this.input.writable)\n * because the inputWriter locks the this.input.writable stream. All writes must go through\n * the inputWriter.\n */\n private async pumpDeferredStream() {\n const reader = this.deferredInputStream.stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n await this.inputWriter.write(value);\n }\n } catch (e) {\n this.logger.error(`Error pumping deferred stream: ${e}`);\n throw e;\n } finally {\n reader.releaseLock();\n }\n }\n\n protected async monitorMetrics() {\n let inferenceDurationTotalMs = 0;\n let inferenceCount = 0;\n const metricsReader = this.metricsStream.getReader();\n while (true) {\n const { done, value } = await metricsReader.read();\n if (done) {\n break;\n }\n switch (value.type) {\n case VADEventType.START_OF_SPEECH:\n inferenceCount++;\n if (inferenceCount >= 1000 / this.vad.capabilities.updateInterval) {\n this.vad.emit('metrics_collected', {\n type: 'vad_metrics',\n timestamp: Date.now(),\n idleTimeMs: Math.trunc(\n Number((process.hrtime.bigint() - this.lastActivityTime) / BigInt(1000000)),\n ),\n inferenceDurationTotalMs,\n inferenceCount,\n label: this.vad.label,\n });\n\n inferenceCount = 0;\n inferenceDurationTotalMs = 0;\n }\n break;\n case VADEventType.INFERENCE_DONE:\n inferenceDurationTotalMs += Math.round(value.inferenceDuration);\n this.lastActivityTime = process.hrtime.bigint();\n break;\n case VADEventType.END_OF_SPEECH:\n this.lastActivityTime = process.hrtime.bigint();\n break;\n }\n }\n }\n\n /**\n * Safely send a VAD event to the output stream, handling writer release errors during shutdown.\n * @returns true if the event was sent, false if the stream is closing\n * @throws Error if an unexpected error occurs\n */\n protected sendVADEvent(event: VADEvent): boolean {\n if (this.closed) {\n return false;\n }\n\n try {\n this.outputWriter.write(event);\n return true;\n } catch (e) {\n throw e;\n }\n }\n\n updateInputStream(audioStream: ReadableStream<AudioFrame>) {\n this.deferredInputStream.setSource(audioStream);\n }\n\n detachInputStream() {\n this.deferredInputStream.detachSource();\n }\n\n /** @deprecated Use `updateInputStream` instead */\n pushFrame(frame: AudioFrame) {\n // TODO(AJS-395): remove this method\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputWriter.write(frame);\n }\n\n flush() {\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputWriter.write(VADStream.FLUSH_SENTINEL);\n }\n\n endInput() {\n if (this.inputClosed) {\n throw new Error('Input is closed');\n }\n if (this.closed) {\n throw new Error('Stream is closed');\n }\n this.inputClosed = true;\n this.input.writable.close();\n }\n\n async next(): Promise<IteratorResult<VADEvent>> {\n return this.outputReader.read().then(({ done, value }) => {\n if (done) {\n return { done: true, value: undefined };\n }\n return { done: false, value };\n });\n }\n\n close() {\n this.outputWriter.releaseLock();\n this.outputReader.cancel();\n this.output.writable.close();\n this.closed = true;\n }\n\n [Symbol.asyncIterator](): VADStream {\n return this;\n }\n}\n"],"mappings":"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","names":["VADEventType"]}
package/dist/version.cjs CHANGED
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  version: () => version
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const version = "0.1.0";
24
+ const version = "1.2.0";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  version
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport const version = '0.1.0';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,MAAM,UAAU;","names":[]}
1
+ {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nexport const version = __PACKAGE_VERSION__;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,MAAM,UAAU;","names":[]}