tjbot-ce 3.0.1

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 (224) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +382 -0
  3. package/dist/camera/camera.d.ts +62 -0
  4. package/dist/camera/camera.d.ts.map +1 -0
  5. package/dist/camera/camera.js +155 -0
  6. package/dist/camera/camera.js.map +1 -0
  7. package/dist/camera/index.d.ts +18 -0
  8. package/dist/camera/index.d.ts.map +1 -0
  9. package/dist/camera/index.js +18 -0
  10. package/dist/camera/index.js.map +1 -0
  11. package/dist/config/config-types.d.ts +75 -0
  12. package/dist/config/config-types.d.ts.map +1 -0
  13. package/dist/config/config-types.generated.d.ts +495 -0
  14. package/dist/config/config-types.generated.d.ts.map +1 -0
  15. package/dist/config/config-types.generated.js +2 -0
  16. package/dist/config/config-types.generated.js.map +1 -0
  17. package/dist/config/config-types.js +175 -0
  18. package/dist/config/config-types.js.map +1 -0
  19. package/dist/config/index.d.ts +20 -0
  20. package/dist/config/index.d.ts.map +1 -0
  21. package/dist/config/index.js +19 -0
  22. package/dist/config/index.js.map +1 -0
  23. package/dist/config/tjbot-config.d.ts +98 -0
  24. package/dist/config/tjbot-config.d.ts.map +1 -0
  25. package/dist/config/tjbot-config.js +309 -0
  26. package/dist/config/tjbot-config.js.map +1 -0
  27. package/dist/config/vendor/colors.yaml +61 -0
  28. package/dist/config/vendor/model-registry.yaml +275 -0
  29. package/dist/config/vendor/tjbot-config.schema.yaml +792 -0
  30. package/dist/config/vendor/tjbot.default.toml +452 -0
  31. package/dist/led/index.d.ts +20 -0
  32. package/dist/led/index.d.ts.map +1 -0
  33. package/dist/led/index.js +20 -0
  34. package/dist/led/index.js.map +1 -0
  35. package/dist/led/led-common-anode.d.ts +38 -0
  36. package/dist/led/led-common-anode.d.ts.map +1 -0
  37. package/dist/led/led-common-anode.js +79 -0
  38. package/dist/led/led-common-anode.js.map +1 -0
  39. package/dist/led/led-neopixel-spi.d.ts +60 -0
  40. package/dist/led/led-neopixel-spi.d.ts.map +1 -0
  41. package/dist/led/led-neopixel-spi.js +216 -0
  42. package/dist/led/led-neopixel-spi.js.map +1 -0
  43. package/dist/led/led-neopixel-ws281x.js +186 -0
  44. package/dist/led/led-neopixel.d.ts +57 -0
  45. package/dist/led/led-neopixel.d.ts.map +1 -0
  46. package/dist/led/led-neopixel.js +235 -0
  47. package/dist/led/led-neopixel.js.map +1 -0
  48. package/dist/microphone/index.d.ts +18 -0
  49. package/dist/microphone/index.d.ts.map +1 -0
  50. package/dist/microphone/index.js +18 -0
  51. package/dist/microphone/index.js.map +1 -0
  52. package/dist/microphone/microphone.d.ts +65 -0
  53. package/dist/microphone/microphone.d.ts.map +1 -0
  54. package/dist/microphone/microphone.js +179 -0
  55. package/dist/microphone/microphone.js.map +1 -0
  56. package/dist/rpi-drivers/index.d.ts +22 -0
  57. package/dist/rpi-drivers/index.d.ts.map +1 -0
  58. package/dist/rpi-drivers/index.js +22 -0
  59. package/dist/rpi-drivers/index.js.map +1 -0
  60. package/dist/rpi-drivers/rpi-detect.d.ts +24 -0
  61. package/dist/rpi-drivers/rpi-detect.d.ts.map +1 -0
  62. package/dist/rpi-drivers/rpi-detect.js +49 -0
  63. package/dist/rpi-drivers/rpi-detect.js.map +1 -0
  64. package/dist/rpi-drivers/rpi-driver.d.ts +116 -0
  65. package/dist/rpi-drivers/rpi-driver.d.ts.map +1 -0
  66. package/dist/rpi-drivers/rpi-driver.js +261 -0
  67. package/dist/rpi-drivers/rpi-driver.js.map +1 -0
  68. package/dist/rpi-drivers/rpi3-driver.d.ts +47 -0
  69. package/dist/rpi-drivers/rpi3-driver.d.ts.map +1 -0
  70. package/dist/rpi-drivers/rpi3-driver.js +145 -0
  71. package/dist/rpi-drivers/rpi3-driver.js.map +1 -0
  72. package/dist/rpi-drivers/rpi4-driver.d.ts +35 -0
  73. package/dist/rpi-drivers/rpi4-driver.d.ts.map +1 -0
  74. package/dist/rpi-drivers/rpi4-driver.js +101 -0
  75. package/dist/rpi-drivers/rpi4-driver.js.map +1 -0
  76. package/dist/rpi-drivers/rpi5-driver.d.ts +33 -0
  77. package/dist/rpi-drivers/rpi5-driver.d.ts.map +1 -0
  78. package/dist/rpi-drivers/rpi5-driver.js +78 -0
  79. package/dist/rpi-drivers/rpi5-driver.js.map +1 -0
  80. package/dist/servo/index.d.ts +19 -0
  81. package/dist/servo/index.d.ts.map +1 -0
  82. package/dist/servo/index.js +19 -0
  83. package/dist/servo/index.js.map +1 -0
  84. package/dist/servo/servo-constants.d.ts +33 -0
  85. package/dist/servo/servo-constants.d.ts.map +1 -0
  86. package/dist/servo/servo-constants.js +34 -0
  87. package/dist/servo/servo-constants.js.map +1 -0
  88. package/dist/servo/servo-lgpio.d.ts +82 -0
  89. package/dist/servo/servo-lgpio.d.ts.map +1 -0
  90. package/dist/servo/servo-lgpio.js +178 -0
  91. package/dist/servo/servo-lgpio.js.map +1 -0
  92. package/dist/speaker/audio-player.d.ts +30 -0
  93. package/dist/speaker/audio-player.d.ts.map +1 -0
  94. package/dist/speaker/audio-player.js +68 -0
  95. package/dist/speaker/audio-player.js.map +1 -0
  96. package/dist/speaker/index.d.ts +18 -0
  97. package/dist/speaker/index.d.ts.map +1 -0
  98. package/dist/speaker/index.js +18 -0
  99. package/dist/speaker/index.js.map +1 -0
  100. package/dist/speaker/speaker.d.ts +53 -0
  101. package/dist/speaker/speaker.d.ts.map +1 -0
  102. package/dist/speaker/speaker.js +125 -0
  103. package/dist/speaker/speaker.js.map +1 -0
  104. package/dist/stt/backends/azure-stt.d.ts +32 -0
  105. package/dist/stt/backends/azure-stt.d.ts.map +1 -0
  106. package/dist/stt/backends/azure-stt.js +227 -0
  107. package/dist/stt/backends/azure-stt.js.map +1 -0
  108. package/dist/stt/backends/google-cloud-stt.d.ts +31 -0
  109. package/dist/stt/backends/google-cloud-stt.d.ts.map +1 -0
  110. package/dist/stt/backends/google-cloud-stt.js +371 -0
  111. package/dist/stt/backends/google-cloud-stt.js.map +1 -0
  112. package/dist/stt/backends/ibm-watson-stt.d.ts +32 -0
  113. package/dist/stt/backends/ibm-watson-stt.d.ts.map +1 -0
  114. package/dist/stt/backends/ibm-watson-stt.js +190 -0
  115. package/dist/stt/backends/ibm-watson-stt.js.map +1 -0
  116. package/dist/stt/backends/sherpa-onnx-stt.d.ts +117 -0
  117. package/dist/stt/backends/sherpa-onnx-stt.d.ts.map +1 -0
  118. package/dist/stt/backends/sherpa-onnx-stt.js +694 -0
  119. package/dist/stt/backends/sherpa-onnx-stt.js.map +1 -0
  120. package/dist/stt/index.d.ts +20 -0
  121. package/dist/stt/index.d.ts.map +1 -0
  122. package/dist/stt/index.js +21 -0
  123. package/dist/stt/index.js.map +1 -0
  124. package/dist/stt/stt-engine.d.ts +68 -0
  125. package/dist/stt/stt-engine.d.ts.map +1 -0
  126. package/dist/stt/stt-engine.js +99 -0
  127. package/dist/stt/stt-engine.js.map +1 -0
  128. package/dist/stt/stt-utils.d.ts +36 -0
  129. package/dist/stt/stt-utils.d.ts.map +1 -0
  130. package/dist/stt/stt-utils.js +112 -0
  131. package/dist/stt/stt-utils.js.map +1 -0
  132. package/dist/stt/stt.d.ts +52 -0
  133. package/dist/stt/stt.d.ts.map +1 -0
  134. package/dist/stt/stt.js +100 -0
  135. package/dist/stt/stt.js.map +1 -0
  136. package/dist/tjbot.d.ts +317 -0
  137. package/dist/tjbot.d.ts.map +1 -0
  138. package/dist/tjbot.js +736 -0
  139. package/dist/tjbot.js.map +1 -0
  140. package/dist/tts/backends/azure-tts.d.ts +30 -0
  141. package/dist/tts/backends/azure-tts.d.ts.map +1 -0
  142. package/dist/tts/backends/azure-tts.js +92 -0
  143. package/dist/tts/backends/azure-tts.js.map +1 -0
  144. package/dist/tts/backends/google-cloud-tts.d.ts +38 -0
  145. package/dist/tts/backends/google-cloud-tts.d.ts.map +1 -0
  146. package/dist/tts/backends/google-cloud-tts.js +116 -0
  147. package/dist/tts/backends/google-cloud-tts.js.map +1 -0
  148. package/dist/tts/backends/ibm-watson-tts.d.ts +42 -0
  149. package/dist/tts/backends/ibm-watson-tts.d.ts.map +1 -0
  150. package/dist/tts/backends/ibm-watson-tts.js +99 -0
  151. package/dist/tts/backends/ibm-watson-tts.js.map +1 -0
  152. package/dist/tts/backends/sherpa-onnx-tts.d.ts +80 -0
  153. package/dist/tts/backends/sherpa-onnx-tts.d.ts.map +1 -0
  154. package/dist/tts/backends/sherpa-onnx-tts.js +237 -0
  155. package/dist/tts/backends/sherpa-onnx-tts.js.map +1 -0
  156. package/dist/tts/index.d.ts +19 -0
  157. package/dist/tts/index.d.ts.map +1 -0
  158. package/dist/tts/index.js +20 -0
  159. package/dist/tts/index.js.map +1 -0
  160. package/dist/tts/tts-engine.d.ts +67 -0
  161. package/dist/tts/tts-engine.d.ts.map +1 -0
  162. package/dist/tts/tts-engine.js +109 -0
  163. package/dist/tts/tts-engine.js.map +1 -0
  164. package/dist/tts/tts.d.ts +47 -0
  165. package/dist/tts/tts.d.ts.map +1 -0
  166. package/dist/tts/tts.js +101 -0
  167. package/dist/tts/tts.js.map +1 -0
  168. package/dist/utils/colors.d.ts +39 -0
  169. package/dist/utils/colors.d.ts.map +1 -0
  170. package/dist/utils/colors.js +155 -0
  171. package/dist/utils/colors.js.map +1 -0
  172. package/dist/utils/constants.d.ts +41 -0
  173. package/dist/utils/constants.d.ts.map +1 -0
  174. package/dist/utils/constants.js +43 -0
  175. package/dist/utils/constants.js.map +1 -0
  176. package/dist/utils/credentials.d.ts +43 -0
  177. package/dist/utils/credentials.d.ts.map +1 -0
  178. package/dist/utils/credentials.js +121 -0
  179. package/dist/utils/credentials.js.map +1 -0
  180. package/dist/utils/errors.d.ts +26 -0
  181. package/dist/utils/errors.d.ts.map +1 -0
  182. package/dist/utils/errors.js +32 -0
  183. package/dist/utils/errors.js.map +1 -0
  184. package/dist/utils/index.d.ts +25 -0
  185. package/dist/utils/index.d.ts.map +1 -0
  186. package/dist/utils/index.js +23 -0
  187. package/dist/utils/index.js.map +1 -0
  188. package/dist/utils/logging.d.ts +44 -0
  189. package/dist/utils/logging.d.ts.map +1 -0
  190. package/dist/utils/logging.js +113 -0
  191. package/dist/utils/logging.js.map +1 -0
  192. package/dist/utils/model-registry.d.ts +142 -0
  193. package/dist/utils/model-registry.d.ts.map +1 -0
  194. package/dist/utils/model-registry.js +391 -0
  195. package/dist/utils/model-registry.js.map +1 -0
  196. package/dist/utils/utils.d.ts +33 -0
  197. package/dist/utils/utils.d.ts.map +1 -0
  198. package/dist/utils/utils.js +50 -0
  199. package/dist/utils/utils.js.map +1 -0
  200. package/dist/vision/backends/azure-vision.d.ts +33 -0
  201. package/dist/vision/backends/azure-vision.d.ts.map +1 -0
  202. package/dist/vision/backends/azure-vision.js +151 -0
  203. package/dist/vision/backends/azure-vision.js.map +1 -0
  204. package/dist/vision/backends/google-cloud-vision.d.ts +32 -0
  205. package/dist/vision/backends/google-cloud-vision.d.ts.map +1 -0
  206. package/dist/vision/backends/google-cloud-vision.js +193 -0
  207. package/dist/vision/backends/google-cloud-vision.js.map +1 -0
  208. package/dist/vision/backends/onnx.d.ts +116 -0
  209. package/dist/vision/backends/onnx.d.ts.map +1 -0
  210. package/dist/vision/backends/onnx.js +781 -0
  211. package/dist/vision/backends/onnx.js.map +1 -0
  212. package/dist/vision/index.d.ts +19 -0
  213. package/dist/vision/index.d.ts.map +1 -0
  214. package/dist/vision/index.js +20 -0
  215. package/dist/vision/index.js.map +1 -0
  216. package/dist/vision/vision-engine.d.ts +131 -0
  217. package/dist/vision/vision-engine.d.ts.map +1 -0
  218. package/dist/vision/vision-engine.js +97 -0
  219. package/dist/vision/vision-engine.js.map +1 -0
  220. package/dist/vision/vision.d.ts +48 -0
  221. package/dist/vision/vision.d.ts.map +1 -0
  222. package/dist/vision/vision.js +83 -0
  223. package/dist/vision/vision.js.map +1 -0
  224. package/package.json +124 -0
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Copyright 2025 IBM Corp. All Rights Reserved.
3
+ * Copyright 2026-present TJBot Contributors. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { createRequire } from 'module';
18
+ import { getLogger } from '../utils/logging.js';
19
+ import { TJBotError } from '../utils/errors.js';
20
+ import { MAX_PULSE_MS, MID_PULSE_MS, MIN_PULSE_MS } from './servo-constants.js';
21
+ const logger = getLogger(import.meta.url);
22
+ const require = createRequire(import.meta.url);
23
+ // lgpio is published as CommonJS; createRequire avoids ESM namespace interop issues.
24
+ const lgpio = require('lgpio');
25
+ /**
26
+ * Servo controller using lgpio on Raspberry Pi GPIO character devices
27
+ */
28
+ export class LGPIOServoController {
29
+ chipNumber;
30
+ pin;
31
+ freq;
32
+ chipHandle;
33
+ claimed = false;
34
+ currentPulseMs;
35
+ running;
36
+ autoStopTimer;
37
+ autoStopDelayMs;
38
+ /**
39
+ * Create a LGPIOServoController instance
40
+ * @param chipNumber GPIO chip number (usually 0)
41
+ * @param pin GPIO pin number (BCM)
42
+ * @param freq PWM frequency in Hz (default 50 for standard servos)
43
+ */
44
+ constructor(chipNumber, pin, freq = 50, autoStopDelayMs = 2000) {
45
+ this.chipNumber = chipNumber;
46
+ this.pin = pin;
47
+ this.freq = freq;
48
+ this.currentPulseMs = MID_PULSE_MS;
49
+ this.running = false;
50
+ this.autoStopDelayMs = autoStopDelayMs;
51
+ logger.debug(`LGPIOServoController initialized with config:
52
+ chip: ${chipNumber}
53
+ pin: ${pin}
54
+ frequency: ${freq} Hz`);
55
+ }
56
+ /**
57
+ * Set the servo to a specific position.
58
+ * @param position Servo position in microseconds (500-2500 for standard servos)
59
+ */
60
+ setPosition(position) {
61
+ const pulseMs = position / 1000;
62
+ logger.verbose(`setting servo position to ${position} μs (${pulseMs} ms)`);
63
+ this.setPulseWidth(pulseMs);
64
+ }
65
+ ensureStarted() {
66
+ if (this.running)
67
+ return;
68
+ logger.debug('starting LGPIOServoController');
69
+ const handle = lgpio.gpiochipOpen(this.chipNumber);
70
+ lgpio.gpioClaimOutput(handle, this.pin);
71
+ this.chipHandle = handle;
72
+ this.claimed = true;
73
+ this.running = true;
74
+ }
75
+ setServoPulse(pulseMs) {
76
+ if (this.chipHandle === undefined) {
77
+ throw new TJBotError('Servo GPIO is not initialized');
78
+ }
79
+ logger.debug(`setting servo pulse: ${pulseMs.toFixed(2)} ms`);
80
+ const periodMs = 1000 / this.freq;
81
+ const dutyCycle = Math.max(0, Math.min(100, (pulseMs / periodMs) * 100));
82
+ // 0 cycles means continuous output until changed.
83
+ lgpio.txPwm(this.chipHandle, this.pin, this.freq, dutyCycle, 0, 0);
84
+ }
85
+ /**
86
+ * Start the servo controller worker
87
+ */
88
+ start() {
89
+ try {
90
+ this.ensureStarted();
91
+ this.setServoPulse(this.currentPulseMs);
92
+ }
93
+ catch (err) {
94
+ logger.error('ServoController failed to start:', err);
95
+ throw err;
96
+ }
97
+ }
98
+ /**
99
+ * Stop the servo controller and clean up resources
100
+ */
101
+ async stop() {
102
+ logger.debug('stopping LGPIOServoController');
103
+ this.running = false;
104
+ if (this.autoStopTimer) {
105
+ clearTimeout(this.autoStopTimer);
106
+ this.autoStopTimer = undefined;
107
+ }
108
+ if (this.claimed && this.chipHandle !== undefined) {
109
+ try {
110
+ lgpio.txPwm(this.chipHandle, this.pin, this.freq, 0, 0, 0);
111
+ lgpio.gpioWrite(this.chipHandle, this.pin, false);
112
+ lgpio.gpioFree(this.chipHandle, this.pin);
113
+ lgpio.gpiochipClose(this.chipHandle);
114
+ }
115
+ catch (err) {
116
+ logger.warn('ServoController cleanup warning:', err);
117
+ }
118
+ finally {
119
+ this.claimed = false;
120
+ this.chipHandle = undefined;
121
+ }
122
+ }
123
+ }
124
+ /**
125
+ * Set pulse width in milliseconds
126
+ * Valid range is 0.5-2.5ms for standard servos
127
+ * @param pulseMs Pulse width in milliseconds
128
+ */
129
+ setPulseWidth(pulseMs) {
130
+ this.currentPulseMs = Math.max(MIN_PULSE_MS, Math.min(MAX_PULSE_MS, pulseMs));
131
+ this.ensureStarted();
132
+ this.setServoPulse(this.currentPulseMs);
133
+ // Reset auto-stop timer
134
+ if (this.autoStopTimer) {
135
+ clearTimeout(this.autoStopTimer);
136
+ }
137
+ this.autoStopTimer = setTimeout(() => {
138
+ logger.debug('ServoController auto-stopping after inactivity');
139
+ this.stop();
140
+ }, this.autoStopDelayMs);
141
+ }
142
+ /**
143
+ * Set servo angle (0-180 degrees)
144
+ * 0° = 0.5ms pulse, 90° = 1.5ms pulse, 180° = 2.5ms pulse
145
+ * @param angle Angle in degrees (0-180)
146
+ */
147
+ setAngle(angle) {
148
+ angle = Math.max(0, Math.min(180, angle));
149
+ const pulse = MIN_PULSE_MS + (angle / 180.0) * (MAX_PULSE_MS - MIN_PULSE_MS);
150
+ this.setPulseWidth(pulse);
151
+ }
152
+ /**
153
+ * Get the current pulse width
154
+ */
155
+ getPulseWidth() {
156
+ return this.currentPulseMs;
157
+ }
158
+ /**
159
+ * Get the current angle (approximately)
160
+ */
161
+ getAngle() {
162
+ return Math.round(((this.currentPulseMs - MIN_PULSE_MS) / (MAX_PULSE_MS - MIN_PULSE_MS)) * 180);
163
+ }
164
+ /**
165
+ * Check if the controller is running
166
+ */
167
+ isRunning() {
168
+ return this.running;
169
+ }
170
+ /**
171
+ * Cleanup and stop the controller
172
+ */
173
+ async cleanup() {
174
+ logger.debug('LGPIOServoController cleanup');
175
+ await this.stop();
176
+ }
177
+ }
178
+ //# sourceMappingURL=servo-lgpio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"servo-lgpio.js","sourceRoot":"","sources":["../../src/servo/servo-lgpio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAiB,MAAM,sBAAsB,CAAC;AAE/F,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE1C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,qFAAqF;AACrF,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAc5B,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,oBAAoB;IACrB,UAAU,CAAS;IACnB,GAAG,CAAS;IACZ,IAAI,CAAS;IACb,UAAU,CAAU;IACpB,OAAO,GAAG,KAAK,CAAC;IAChB,cAAc,CAAS;IACvB,OAAO,CAAU;IACjB,aAAa,CAAkB;IAC/B,eAAe,CAAS;IAEhC;;;;;OAKG;IACH,YAAY,UAAkB,EAAE,GAAW,EAAE,IAAI,GAAG,EAAE,EAAE,eAAe,GAAG,IAAI;QAC1E,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,cAAc,GAAG,YAAY,CAAC;QACnC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QAEvC,MAAM,CAAC,KAAK,CAAC;oBACD,UAAU;mBACX,GAAG;yBACG,IAAI,KAAK,CAAC,CAAC;IAChC,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,QAAuB;QAC/B,MAAM,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,6BAA6B,QAAQ,QAAQ,OAAO,MAAM,CAAC,CAAC;QAC3E,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAEO,aAAa;QACjB,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QAEzB,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnD,KAAK,CAAC,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACxB,CAAC;IAEO,aAAa,CAAC,OAAe;QACjC,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,UAAU,CAAC,+BAA+B,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,wBAAwB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,GAAG,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAEzE,kDAAkD;QAClD,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACvE,CAAC;IAED;;OAEG;IACH,KAAK;QACD,IAAI,CAAC;YACD,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;YACtD,MAAM,GAAG,CAAC;QACd,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACN,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAE9C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QACnC,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAChD,IAAI,CAAC;gBACD,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC3D,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBAClD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC1C,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,MAAM,CAAC,IAAI,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;YACzD,CAAC;oBAAS,CAAC;gBACP,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;gBACrB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;YAChC,CAAC;QACL,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,aAAa,CAAC,OAAe;QACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9E,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAExC,wBAAwB;QACxB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YACjC,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;YAC/D,IAAI,CAAC,IAAI,EAAE,CAAC;QAChB,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,KAAa;QAClB,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,YAAY,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,GAAG,YAAY,CAAC,CAAC;QAC7E,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,aAAa;QACT,OAAO,IAAI,CAAC,cAAc,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,QAAQ;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,GAAG,YAAY,CAAC,GAAG,CAAC,YAAY,GAAG,YAAY,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IACpG,CAAC;IAED;;OAEG;IACH,SAAS;QACL,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACT,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC7C,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;CACJ"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright 2026-present TJBot Contributors. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { EventEmitter } from 'events';
17
+ /**
18
+ * Native audio player that uses aplay for audio playback on Raspbian/ALSA systems
19
+ * Provides the same API surface as sound-player package
20
+ */
21
+ export declare class AudioPlayer extends EventEmitter {
22
+ private process;
23
+ /**
24
+ * Play an audio file using aplay
25
+ * @param audioPath Path to the audio file to play
26
+ * @param device Optional audio device to use (e.g., 'hw:0,0')
27
+ */
28
+ play(audioPath: string, device?: string): void;
29
+ }
30
+ //# sourceMappingURL=audio-player.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-player.d.ts","sourceRoot":"","sources":["../../src/speaker/audio-player.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAMtC;;;GAGG;AACH,qBAAa,WAAY,SAAQ,YAAY;IACzC,OAAO,CAAC,OAAO,CAA6B;IAE5C;;;;OAIG;IACH,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;CA2CjD"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Copyright 2026-present TJBot Contributors. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { EventEmitter } from 'events';
17
+ import { spawn } from 'child_process';
18
+ import { getLogger } from '../utils/logging.js';
19
+ const logger = getLogger(import.meta.url);
20
+ /**
21
+ * Native audio player that uses aplay for audio playback on Raspbian/ALSA systems
22
+ * Provides the same API surface as sound-player package
23
+ */
24
+ export class AudioPlayer extends EventEmitter {
25
+ process = null;
26
+ /**
27
+ * Play an audio file using aplay
28
+ * @param audioPath Path to the audio file to play
29
+ * @param device Optional audio device to use (e.g., 'hw:0,0')
30
+ */
31
+ play(audioPath, device) {
32
+ const args = [audioPath];
33
+ // Add device parameter if specified
34
+ if (device && device !== '') {
35
+ args.unshift('-D', device);
36
+ }
37
+ // Log the command being executed
38
+ logger.verbose(`Playing audio with command: aplay ${args.join(' ')}`);
39
+ // Spawn aplay process
40
+ this.process = spawn('aplay', args, {
41
+ stdio: ['ignore', 'ignore', 'pipe'], // Only capture stderr for errors
42
+ });
43
+ let stderrOutput = '';
44
+ // Capture stderr for error reporting
45
+ if (this.process.stderr) {
46
+ this.process.stderr.on('data', (data) => {
47
+ stderrOutput += data.toString();
48
+ });
49
+ }
50
+ // Handle process completion
51
+ this.process.on('close', (code) => {
52
+ this.process = null;
53
+ if (code === 0) {
54
+ this.emit('complete');
55
+ }
56
+ else {
57
+ const error = new Error(`aplay exited with code ${code}: ${stderrOutput}`);
58
+ this.emit('error', error);
59
+ }
60
+ });
61
+ // Handle process errors (e.g., aplay not found)
62
+ this.process.on('error', (err) => {
63
+ this.process = null;
64
+ this.emit('error', err);
65
+ });
66
+ }
67
+ }
68
+ //# sourceMappingURL=audio-player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-player.js","sourceRoot":"","sources":["../../src/speaker/audio-player.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE1C;;;GAGG;AACH,MAAM,OAAO,WAAY,SAAQ,YAAY;IACjC,OAAO,GAAwB,IAAI,CAAC;IAE5C;;;;OAIG;IACH,IAAI,CAAC,SAAiB,EAAE,MAAe;QACnC,MAAM,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAEzB,oCAAoC;QACpC,IAAI,MAAM,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC;QAED,iCAAiC;QACjC,MAAM,CAAC,OAAO,CAAC,qCAAqC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEtE,sBAAsB;QACtB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YAChC,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,iCAAiC;SACzE,CAAC,CAAC;QAEH,IAAI,YAAY,GAAG,EAAE,CAAC;QAEtB,qCAAqC;QACrC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACtB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBACpC,YAAY,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,CAAC,CAAC,CAAC;QACP,CAAC;QAED,4BAA4B;QAC5B,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YAEpB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACb,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACJ,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,0BAA0B,IAAI,KAAK,YAAY,EAAE,CAAC,CAAC;gBAC3E,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9B,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,gDAAgD;QAChD,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACP,CAAC;CACJ"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright 2025 IBM Corp. All Rights Reserved.
3
+ * Copyright 2026-present TJBot Contributors. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ export { SpeakerController } from './speaker.js';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/speaker/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright 2025 IBM Corp. All Rights Reserved.
3
+ * Copyright 2026-present TJBot Contributors. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ export { SpeakerController } from './speaker.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/speaker/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Copyright 2025 IBM Corp. All Rights Reserved.
3
+ * Copyright 2026-present TJBot Contributors. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * Speaker controller for TJBot
19
+ * Handles audio playback and text-to-speech synthesis
20
+ */
21
+ export declare class SpeakerController {
22
+ private device;
23
+ private onPauseCallback?;
24
+ private onResumeCallback?;
25
+ constructor();
26
+ /**
27
+ * Auto-detect the first available audio playback device
28
+ * Prefers USB audio devices over HDMI devices
29
+ * @returns The device string (e.g., 'plughw:0,0') or empty string if none found
30
+ */
31
+ private detectSpeakerDevice;
32
+ /**
33
+ * Initialize the speaker with configuration
34
+ * @param device Optional specific audio device to use (auto-detected if not specified)
35
+ */
36
+ initialize(device?: string): void;
37
+ /**
38
+ * Set callbacks for pause/resume (typically to pause/resume microphone)
39
+ * @param onPause Callback when audio playback starts
40
+ * @param onResume Callback when audio playback ends
41
+ */
42
+ setAudioLifecycleCallbacks(onPause?: () => void, onResume?: () => void): void;
43
+ /**
44
+ * Play audio from a file
45
+ * @param audioPath Path to the audio file to play
46
+ */
47
+ playAudio(audioPath: string): Promise<void>;
48
+ /**
49
+ * Clean up resources
50
+ */
51
+ cleanup(): void;
52
+ }
53
+ //# sourceMappingURL=speaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speaker.d.ts","sourceRoot":"","sources":["../../src/speaker/speaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AASH;;;GAGG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAC,CAAa;IACrC,OAAO,CAAC,gBAAgB,CAAC,CAAa;;IAMtC;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA6B3B;;;OAGG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAYjC;;;;OAIG;IACH,0BAA0B,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;IAK7E;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCjD;;OAEG;IACH,OAAO,IAAI,IAAI;CAGlB"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Copyright 2025 IBM Corp. All Rights Reserved.
3
+ * Copyright 2026-present TJBot Contributors. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { AudioPlayer } from './audio-player.js';
18
+ import { once } from 'events';
19
+ import { execSync } from 'child_process';
20
+ import { getLogger } from '../utils/logging.js';
21
+ const logger = getLogger(import.meta.url);
22
+ /**
23
+ * Speaker controller for TJBot
24
+ * Handles audio playback and text-to-speech synthesis
25
+ */
26
+ export class SpeakerController {
27
+ device;
28
+ onPauseCallback;
29
+ onResumeCallback;
30
+ constructor() {
31
+ this.device = '';
32
+ }
33
+ /**
34
+ * Auto-detect the first available audio playback device
35
+ * Prefers USB audio devices over HDMI devices
36
+ * @returns The device string (e.g., 'plughw:0,0') or empty string if none found
37
+ */
38
+ detectSpeakerDevice() {
39
+ try {
40
+ // Run aplay -l to list playback devices
41
+ const output = execSync('aplay -l', { encoding: 'utf8' });
42
+ const lines = output.split('\n');
43
+ // Prefer USB audio devices over HDMI (which may not work without connected display)
44
+ const usbLine = lines.find((line) => line.includes('USB') && line.match(/card (\d+):.*device (\d+):/));
45
+ const targetLine = usbLine || lines.find((line) => line.match(/card (\d+):.*device (\d+):/));
46
+ if (targetLine) {
47
+ const match = targetLine.match(/card (\d+):.*device (\d+):/);
48
+ if (match) {
49
+ const card = match[1];
50
+ const device = match[2];
51
+ const deviceString = `plughw:${card},${device}`;
52
+ logger.verbose(`🔈 auto-detected speaker device: ${deviceString}`);
53
+ return deviceString;
54
+ }
55
+ }
56
+ logger.warn('No audio playback devices found');
57
+ return '';
58
+ }
59
+ catch (error) {
60
+ logger.error('Error detecting speaker device:', error);
61
+ return '';
62
+ }
63
+ }
64
+ /**
65
+ * Initialize the speaker with configuration
66
+ * @param device Optional specific audio device to use (auto-detected if not specified)
67
+ */
68
+ initialize(device) {
69
+ // Auto-detect device if not specified
70
+ let selectedDevice = device || '';
71
+ if (!selectedDevice || selectedDevice === '') {
72
+ selectedDevice = this.detectSpeakerDevice();
73
+ }
74
+ this.device = selectedDevice;
75
+ logger.verbose(`Initialized speaker on device ${this.device}`);
76
+ }
77
+ /**
78
+ * Set callbacks for pause/resume (typically to pause/resume microphone)
79
+ * @param onPause Callback when audio playback starts
80
+ * @param onResume Callback when audio playback ends
81
+ */
82
+ setAudioLifecycleCallbacks(onPause, onResume) {
83
+ this.onPauseCallback = onPause;
84
+ this.onResumeCallback = onResume;
85
+ }
86
+ /**
87
+ * Play audio from a file
88
+ * @param audioPath Path to the audio file to play
89
+ */
90
+ async playAudio(audioPath) {
91
+ // pause listening while we play a sound
92
+ if (this.onPauseCallback) {
93
+ this.onPauseCallback();
94
+ }
95
+ const player = new AudioPlayer();
96
+ if (this.device !== undefined && this.device !== '') {
97
+ logger.verbose(`Playing audio file ${audioPath} through user-defined audio device (${this.device})`);
98
+ }
99
+ else {
100
+ logger.verbose(`Playing audio file ${audioPath} through default audio device`);
101
+ }
102
+ // Set up event handlers
103
+ player.on('complete', () => {
104
+ logger.debug('Audio playback finished');
105
+ // resume listening
106
+ if (this.onResumeCallback) {
107
+ this.onResumeCallback();
108
+ }
109
+ });
110
+ player.on('error', (err) => {
111
+ logger.error('Error occurred while playing audio', err);
112
+ });
113
+ // play the audio
114
+ player.play(audioPath, this.device);
115
+ // wait for the audio to finish playing, either by completing playback or by throwing an error
116
+ await Promise.race([once(player, 'complete'), once(player, 'error')]);
117
+ }
118
+ /**
119
+ * Clean up resources
120
+ */
121
+ cleanup() {
122
+ logger.debug('SpeakerController cleanup (no-op)');
123
+ }
124
+ }
125
+ //# sourceMappingURL=speaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speaker.js","sourceRoot":"","sources":["../../src/speaker/speaker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Copyright 2026-present TJBot Contributors. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { STTEngine, STTRequestOptions } from '../stt-engine.js';
17
+ /**
18
+ * Azure Cognitive Services Speech-to-Text Engine
19
+ *
20
+ * Cloud-based speech recognition using Microsoft Azure Speech Services.
21
+ * Requires Azure subscription key and region to be configured.
22
+ * @public
23
+ */
24
+ export declare class AzureSTTEngine extends STTEngine {
25
+ private microphoneRate;
26
+ private microphoneChannels;
27
+ private subscriptionKey?;
28
+ private region?;
29
+ initialize(microphoneRate: number, microphoneChannels: number): Promise<void>;
30
+ transcribe(micStream: NodeJS.ReadableStream, options: STTRequestOptions): Promise<string>;
31
+ }
32
+ //# sourceMappingURL=azure-stt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-stt.d.ts","sourceRoot":"","sources":["../../../src/stt/backends/azure-stt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAKhE;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,SAAS;IACzC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,eAAe,CAAC,CAAS;IACjC,OAAO,CAAC,MAAM,CAAC,CAAS;IAElB,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4B7E,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,cAAc,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;CAwNlG"}