claude-voice 1.0.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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +395 -0
  3. package/bin/claude-voice +29 -0
  4. package/config/default.json +109 -0
  5. package/config/voice-prompt.md +27 -0
  6. package/dist/cli.d.ts +8 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +1103 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/config.d.ts +140 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +179 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/env.d.ts +40 -0
  15. package/dist/env.d.ts.map +1 -0
  16. package/dist/env.js +175 -0
  17. package/dist/env.js.map +1 -0
  18. package/dist/index.d.ts +10 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +140 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/platform/index.d.ts +35 -0
  23. package/dist/platform/index.d.ts.map +1 -0
  24. package/dist/platform/index.js +170 -0
  25. package/dist/platform/index.js.map +1 -0
  26. package/dist/server.d.ts +5 -0
  27. package/dist/server.d.ts.map +1 -0
  28. package/dist/server.js +185 -0
  29. package/dist/server.js.map +1 -0
  30. package/dist/stt/index.d.ts +15 -0
  31. package/dist/stt/index.d.ts.map +1 -0
  32. package/dist/stt/index.js +54 -0
  33. package/dist/stt/index.js.map +1 -0
  34. package/dist/stt/providers/openai.d.ts +15 -0
  35. package/dist/stt/providers/openai.d.ts.map +1 -0
  36. package/dist/stt/providers/openai.js +74 -0
  37. package/dist/stt/providers/openai.js.map +1 -0
  38. package/dist/stt/providers/sherpa-onnx.d.ts +50 -0
  39. package/dist/stt/providers/sherpa-onnx.d.ts.map +1 -0
  40. package/dist/stt/providers/sherpa-onnx.js +237 -0
  41. package/dist/stt/providers/sherpa-onnx.js.map +1 -0
  42. package/dist/stt/providers/whisper-local.d.ts +19 -0
  43. package/dist/stt/providers/whisper-local.d.ts.map +1 -0
  44. package/dist/stt/providers/whisper-local.js +141 -0
  45. package/dist/stt/providers/whisper-local.js.map +1 -0
  46. package/dist/terminal/input-injector.d.ts +55 -0
  47. package/dist/terminal/input-injector.d.ts.map +1 -0
  48. package/dist/terminal/input-injector.js +189 -0
  49. package/dist/terminal/input-injector.js.map +1 -0
  50. package/dist/tts/index.d.ts +20 -0
  51. package/dist/tts/index.d.ts.map +1 -0
  52. package/dist/tts/index.js +72 -0
  53. package/dist/tts/index.js.map +1 -0
  54. package/dist/tts/providers/elevenlabs.d.ts +23 -0
  55. package/dist/tts/providers/elevenlabs.d.ts.map +1 -0
  56. package/dist/tts/providers/elevenlabs.js +142 -0
  57. package/dist/tts/providers/elevenlabs.js.map +1 -0
  58. package/dist/tts/providers/macos-say.d.ts +17 -0
  59. package/dist/tts/providers/macos-say.d.ts.map +1 -0
  60. package/dist/tts/providers/macos-say.js +72 -0
  61. package/dist/tts/providers/macos-say.js.map +1 -0
  62. package/dist/tts/providers/openai.d.ts +19 -0
  63. package/dist/tts/providers/openai.d.ts.map +1 -0
  64. package/dist/tts/providers/openai.js +118 -0
  65. package/dist/tts/providers/openai.js.map +1 -0
  66. package/dist/tts/providers/piper.d.ts +48 -0
  67. package/dist/tts/providers/piper.d.ts.map +1 -0
  68. package/dist/tts/providers/piper.js +417 -0
  69. package/dist/tts/providers/piper.js.map +1 -0
  70. package/dist/voice-input.d.ts +9 -0
  71. package/dist/voice-input.d.ts.map +1 -0
  72. package/dist/voice-input.js +137 -0
  73. package/dist/voice-input.js.map +1 -0
  74. package/dist/wake-word/index.d.ts +19 -0
  75. package/dist/wake-word/index.d.ts.map +1 -0
  76. package/dist/wake-word/index.js +200 -0
  77. package/dist/wake-word/index.js.map +1 -0
  78. package/dist/wake-word/recorder.d.ts +19 -0
  79. package/dist/wake-word/recorder.d.ts.map +1 -0
  80. package/dist/wake-word/recorder.js +145 -0
  81. package/dist/wake-word/recorder.js.map +1 -0
  82. package/hooks/notification.js +125 -0
  83. package/hooks/post-tool-use.js +374 -0
  84. package/hooks/session-start.js +212 -0
  85. package/hooks/stop.js +254 -0
  86. package/models/.gitkeep +0 -0
  87. package/package.json +80 -0
  88. package/python/stt_service.py +59 -0
  89. package/python/voice_input.py +154 -0
  90. package/scripts/install.sh +147 -0
  91. package/scripts/listen.py +161 -0
  92. package/scripts/postinstall.js +57 -0
  93. package/scripts/record.sh +79 -0
  94. package/scripts/setup-hooks.sh +22 -0
  95. package/scripts/voice-input.sh +66 -0
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Voice Input - Record and transcribe speech with a keypress
5
+ *
6
+ * Usage: node voice-input.js
7
+ * Press SPACE to start recording, SPACE again to stop and transcribe.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ const readline = __importStar(require("readline"));
44
+ const child_process_1 = require("child_process");
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const os = __importStar(require("os"));
48
+ const config_1 = require("./config");
49
+ const stt_1 = require("./stt");
50
+ const input_injector_1 = require("./terminal/input-injector");
51
+ const config = (0, config_1.loadConfig)();
52
+ const sttManager = new stt_1.STTManager(config.stt);
53
+ let isRecording = false;
54
+ let recordProcess = null;
55
+ let tempFile = '';
56
+ async function startRecording() {
57
+ tempFile = path.join(os.tmpdir(), `voice-input-${Date.now()}.wav`);
58
+ console.log('\n🎤 Recording... (press SPACE to stop)');
59
+ // Use sox (rec) on macOS for recording
60
+ recordProcess = (0, child_process_1.spawn)('rec', [
61
+ '-r', '16000', // Sample rate
62
+ '-c', '1', // Mono
63
+ '-b', '16', // 16-bit
64
+ tempFile
65
+ ], {
66
+ stdio: ['ignore', 'ignore', 'ignore']
67
+ });
68
+ isRecording = true;
69
+ }
70
+ async function stopRecording() {
71
+ if (!recordProcess)
72
+ return '';
73
+ recordProcess.kill('SIGTERM');
74
+ recordProcess = null;
75
+ isRecording = false;
76
+ console.log('⏳ Transcribing...');
77
+ // Wait a moment for file to be written
78
+ await new Promise(r => setTimeout(r, 500));
79
+ try {
80
+ const transcript = await sttManager.transcribe(tempFile);
81
+ // Cleanup
82
+ if (fs.existsSync(tempFile)) {
83
+ fs.unlinkSync(tempFile);
84
+ }
85
+ return transcript;
86
+ }
87
+ catch (error) {
88
+ console.error('Transcription error:', error);
89
+ return '';
90
+ }
91
+ }
92
+ async function main() {
93
+ console.log('╔════════════════════════════════════════╗');
94
+ console.log('║ Claude Voice Input ║');
95
+ console.log('╠════════════════════════════════════════╣');
96
+ console.log('║ SPACE = Start/Stop recording ║');
97
+ console.log('║ ENTER = Send to Claude ║');
98
+ console.log('║ Q = Quit ║');
99
+ console.log('╚════════════════════════════════════════╝');
100
+ console.log('\nPress SPACE to start recording...\n');
101
+ // Set up raw mode for keypress detection
102
+ readline.emitKeypressEvents(process.stdin);
103
+ if (process.stdin.isTTY) {
104
+ process.stdin.setRawMode(true);
105
+ }
106
+ let lastTranscript = '';
107
+ process.stdin.on('keypress', async (str, key) => {
108
+ if (key.name === 'q' || (key.ctrl && key.name === 'c')) {
109
+ console.log('\nGoodbye!');
110
+ process.exit(0);
111
+ }
112
+ if (key.name === 'space') {
113
+ if (!isRecording) {
114
+ await startRecording();
115
+ }
116
+ else {
117
+ lastTranscript = await stopRecording();
118
+ if (lastTranscript) {
119
+ console.log(`\n📝 Transcript: "${lastTranscript}"`);
120
+ console.log('\nPress ENTER to send to Claude, SPACE to re-record, or Q to quit');
121
+ }
122
+ else {
123
+ console.log('\n❌ No speech detected. Press SPACE to try again.');
124
+ }
125
+ }
126
+ }
127
+ if (key.name === 'return' && lastTranscript) {
128
+ console.log('\n📤 Sending to Claude...');
129
+ await (0, input_injector_1.sendToClaudeCode)(lastTranscript);
130
+ console.log('✅ Sent! Switch to your Claude terminal.');
131
+ lastTranscript = '';
132
+ console.log('\nPress SPACE to record again...');
133
+ }
134
+ });
135
+ }
136
+ main().catch(console.error);
137
+ //# sourceMappingURL=voice-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-input.js","sourceRoot":"","sources":["../src/voice-input.ts"],"names":[],"mappings":";;AACA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,mDAAqC;AACrC,iDAAsC;AACtC,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AACzB,qCAAsC;AACtC,+BAAmC;AACnC,8DAA6D;AAE7D,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAE,CAAC;AAC5B,MAAM,UAAU,GAAG,IAAI,gBAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAE9C,IAAI,WAAW,GAAG,KAAK,CAAC;AACxB,IAAI,aAAa,GAAoC,IAAI,CAAC;AAC1D,IAAI,QAAQ,GAAW,EAAE,CAAC;AAE1B,KAAK,UAAU,cAAc;IAC3B,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAEnE,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IAEvD,uCAAuC;IACvC,aAAa,GAAG,IAAA,qBAAK,EAAC,KAAK,EAAE;QAC3B,IAAI,EAAE,OAAO,EAAO,cAAc;QAClC,IAAI,EAAE,GAAG,EAAW,OAAO;QAC3B,IAAI,EAAE,IAAI,EAAU,SAAS;QAC7B,QAAQ;KACT,EAAE;QACD,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;KACtC,CAAC,CAAC;IAEH,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED,KAAK,UAAU,aAAa;IAC1B,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAE9B,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9B,aAAa,GAAG,IAAI,CAAC;IACrB,WAAW,GAAG,KAAK,CAAC;IAEpB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAEjC,uCAAuC;IACvC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAE3C,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAEzD,UAAU;QACV,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAC7C,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IAErD,yCAAyC;IACzC,QAAQ,CAAC,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,IAAI,cAAc,GAAG,EAAE,CAAC;IAExB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9C,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,cAAc,EAAE,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,cAAc,GAAG,MAAM,aAAa,EAAE,CAAC;gBACvC,IAAI,cAAc,EAAE,CAAC;oBACnB,OAAO,CAAC,GAAG,CAAC,qBAAqB,cAAc,GAAG,CAAC,CAAC;oBACpD,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;gBACnF,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;gBACnE,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,cAAc,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACzC,MAAM,IAAA,iCAAgB,EAAC,cAAc,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;YACvD,cAAc,GAAG,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { EventEmitter } from 'events';
2
+ import { WakeWordConfig, RecordingConfig } from '../config';
3
+ export declare class WakeWordDetector extends EventEmitter {
4
+ private config;
5
+ private recordingConfig;
6
+ private porcupine;
7
+ private recorder;
8
+ private isListening;
9
+ private isRecordingCommand;
10
+ constructor(wakeWordConfig: WakeWordConfig, recordingConfig: RecordingConfig);
11
+ initialize(): Promise<void>;
12
+ start(): Promise<void>;
13
+ private startCommandRecording;
14
+ private calculateAmplitude;
15
+ private finishRecording;
16
+ stop(): void;
17
+ cleanup(): void;
18
+ }
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wake-word/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAuB5D,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,kBAAkB,CAAS;gBAEvB,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe;IAMtE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmD3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YA+Bd,qBAAqB;IA8CnC,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,eAAe;IAUvB,IAAI,IAAI,IAAI;IAWZ,OAAO,IAAI,IAAI;CAehB"}
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.WakeWordDetector = void 0;
37
+ const events_1 = require("events");
38
+ const child_process_1 = require("child_process");
39
+ const recorder_1 = require("./recorder");
40
+ // Play macOS system sounds
41
+ function playSound(soundName) {
42
+ const soundPath = `/System/Library/Sounds/${soundName}.aiff`;
43
+ (0, child_process_1.spawn)('afplay', [soundPath], { stdio: 'ignore' });
44
+ }
45
+ class WakeWordDetector extends events_1.EventEmitter {
46
+ config;
47
+ recordingConfig;
48
+ porcupine = null;
49
+ recorder = null;
50
+ isListening = false;
51
+ isRecordingCommand = false;
52
+ constructor(wakeWordConfig, recordingConfig) {
53
+ super();
54
+ this.config = wakeWordConfig;
55
+ this.recordingConfig = recordingConfig;
56
+ }
57
+ async initialize() {
58
+ const accessKey = process.env.PICOVOICE_ACCESS_KEY;
59
+ if (!accessKey) {
60
+ console.warn('PICOVOICE_ACCESS_KEY not set. Wake word detection will be disabled.', 'Get a free key at https://picovoice.ai/');
61
+ return;
62
+ }
63
+ try {
64
+ // Dynamic import for Porcupine
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ const porcupineModule = await Promise.resolve().then(() => __importStar(require('@picovoice/porcupine-node')));
67
+ const Porcupine = porcupineModule.Porcupine;
68
+ const BuiltinKeyword = porcupineModule.BuiltinKeyword;
69
+ // Use custom Jarvis wake word model
70
+ const path = await Promise.resolve().then(() => __importStar(require('path')));
71
+ const fs = await Promise.resolve().then(() => __importStar(require('fs')));
72
+ const customModelPath = path.join(__dirname, '..', '..', 'models', 'jarvis.ppn');
73
+ let keywords;
74
+ if (fs.existsSync(customModelPath)) {
75
+ // Use custom Jarvis model
76
+ keywords = [customModelPath];
77
+ console.log('Using custom Jarvis wake word model');
78
+ }
79
+ else {
80
+ // Fallback to built-in JARVIS
81
+ keywords = [BuiltinKeyword.JARVIS];
82
+ console.log('Using built-in Jarvis keyword');
83
+ }
84
+ // Porcupine uses constructor, not .create()
85
+ this.porcupine = new Porcupine(accessKey, keywords, [this.config.sensitivity]);
86
+ this.recorder = new recorder_1.AudioRecorder({
87
+ sampleRate: this.porcupine.sampleRate,
88
+ frameLength: this.porcupine.frameLength,
89
+ channels: this.recordingConfig.channels,
90
+ });
91
+ console.log('Wake word detector initialized');
92
+ }
93
+ catch (error) {
94
+ console.error('Failed to initialize Porcupine:', error);
95
+ throw error;
96
+ }
97
+ }
98
+ async start() {
99
+ if (!this.porcupine || !this.recorder) {
100
+ console.warn('Wake word detector not initialized');
101
+ return;
102
+ }
103
+ if (this.isListening) {
104
+ return;
105
+ }
106
+ this.isListening = true;
107
+ this.recorder.on('frame', (frame) => {
108
+ if (!this.isListening || !this.porcupine || this.isRecordingCommand) {
109
+ return;
110
+ }
111
+ const keywordIndex = this.porcupine.process(frame);
112
+ if (keywordIndex >= 0) {
113
+ // Play "listening" sound
114
+ playSound('Ping');
115
+ this.emit('wakeword', keywordIndex);
116
+ this.startCommandRecording();
117
+ }
118
+ });
119
+ await this.recorder.start();
120
+ this.emit('started');
121
+ }
122
+ async startCommandRecording() {
123
+ if (!this.recorder || this.isRecordingCommand) {
124
+ return;
125
+ }
126
+ this.isRecordingCommand = true;
127
+ this.emit('listening');
128
+ const audioChunks = [];
129
+ let silenceStart = null;
130
+ const silenceThreshold = this.recordingConfig.silenceThreshold;
131
+ const maxDuration = this.recordingConfig.maxDuration;
132
+ const startTime = Date.now();
133
+ const recordingHandler = (frame) => {
134
+ // Convert Int16Array to Buffer
135
+ const buffer = Buffer.from(frame.buffer);
136
+ audioChunks.push(buffer);
137
+ // Simple silence detection based on amplitude
138
+ const amplitude = this.calculateAmplitude(frame);
139
+ if (amplitude < 500) {
140
+ // Low amplitude threshold
141
+ if (!silenceStart) {
142
+ silenceStart = Date.now();
143
+ }
144
+ else if (Date.now() - silenceStart > silenceThreshold) {
145
+ // End of speech detected
146
+ this.finishRecording(audioChunks);
147
+ this.recorder?.off('frame', recordingHandler);
148
+ return;
149
+ }
150
+ }
151
+ else {
152
+ silenceStart = null;
153
+ }
154
+ // Max duration check
155
+ if (Date.now() - startTime > maxDuration) {
156
+ this.finishRecording(audioChunks);
157
+ this.recorder?.off('frame', recordingHandler);
158
+ }
159
+ };
160
+ this.recorder.on('frame', recordingHandler);
161
+ }
162
+ calculateAmplitude(frame) {
163
+ let sum = 0;
164
+ for (let i = 0; i < frame.length; i++) {
165
+ sum += Math.abs(frame[i]);
166
+ }
167
+ return sum / frame.length;
168
+ }
169
+ finishRecording(chunks) {
170
+ this.isRecordingCommand = false;
171
+ // Play "done" sound
172
+ playSound('Pop');
173
+ const audioBuffer = Buffer.concat(chunks);
174
+ this.emit('command', audioBuffer);
175
+ }
176
+ stop() {
177
+ this.isListening = false;
178
+ this.isRecordingCommand = false;
179
+ if (this.recorder) {
180
+ this.recorder.stop();
181
+ }
182
+ this.emit('stopped');
183
+ }
184
+ cleanup() {
185
+ this.stop();
186
+ if (this.porcupine) {
187
+ // Porcupine v4.x uses release(), older versions use delete()
188
+ if (typeof this.porcupine.release === 'function') {
189
+ this.porcupine.release();
190
+ }
191
+ else if (typeof this.porcupine.delete === 'function') {
192
+ this.porcupine.delete();
193
+ }
194
+ this.porcupine = null;
195
+ }
196
+ this.recorder = null;
197
+ }
198
+ }
199
+ exports.WakeWordDetector = WakeWordDetector;
200
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wake-word/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { EventEmitter } from 'events';
2
+ interface RecorderConfig {
3
+ sampleRate: number;
4
+ frameLength: number;
5
+ channels: number;
6
+ }
7
+ export declare class AudioRecorder extends EventEmitter {
8
+ private config;
9
+ private recorder;
10
+ private isRunning;
11
+ private readInterval;
12
+ constructor(config: RecorderConfig);
13
+ start(): Promise<void>;
14
+ stop(): void;
15
+ static listDevices(): Promise<string[]>;
16
+ }
17
+ export declare function saveToWav(audioBuffer: Buffer, outputPath: string, sampleRate: number, channels: number): Promise<void>;
18
+ export {};
19
+ //# sourceMappingURL=recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/wake-word/recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAeD,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAA+B;gBAEvC,MAAM,EAAE,cAAc;IAK5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoC5B,IAAI,IAAI,IAAI;WAqBC,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAS9C;AAGD,wBAAgB,SAAS,CACvB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAmCf"}
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AudioRecorder = void 0;
37
+ exports.saveToWav = saveToWav;
38
+ const events_1 = require("events");
39
+ class AudioRecorder extends events_1.EventEmitter {
40
+ config;
41
+ recorder = null;
42
+ isRunning = false;
43
+ readInterval = null;
44
+ constructor(config) {
45
+ super();
46
+ this.config = config;
47
+ }
48
+ async start() {
49
+ if (this.isRunning) {
50
+ return;
51
+ }
52
+ try {
53
+ // Dynamic import for PvRecorder
54
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ const pvRecorderModule = await Promise.resolve().then(() => __importStar(require('@picovoice/pvrecorder-node')));
56
+ const PvRecorder = pvRecorderModule.PvRecorder;
57
+ // Use default audio device (index -1)
58
+ this.recorder = new PvRecorder(this.config.frameLength, -1);
59
+ this.recorder.start();
60
+ this.isRunning = true;
61
+ // Read frames continuously using readSync
62
+ this.readInterval = setInterval(() => {
63
+ if (this.recorder && this.isRunning) {
64
+ try {
65
+ // Use readSync() for synchronous reading in interval
66
+ const frame = this.recorder.readSync();
67
+ this.emit('frame', frame);
68
+ }
69
+ catch (error) {
70
+ this.emit('error', error);
71
+ }
72
+ }
73
+ }, (this.config.frameLength / this.config.sampleRate) * 1000);
74
+ this.emit('started');
75
+ }
76
+ catch (error) {
77
+ console.error('Failed to start audio recorder:', error);
78
+ throw error;
79
+ }
80
+ }
81
+ stop() {
82
+ this.isRunning = false;
83
+ if (this.readInterval) {
84
+ clearInterval(this.readInterval);
85
+ this.readInterval = null;
86
+ }
87
+ if (this.recorder) {
88
+ try {
89
+ this.recorder.stop();
90
+ this.recorder.delete();
91
+ }
92
+ catch {
93
+ // Ignore cleanup errors
94
+ }
95
+ this.recorder = null;
96
+ }
97
+ this.emit('stopped');
98
+ }
99
+ static async listDevices() {
100
+ try {
101
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
102
+ const pvRecorderModule = await Promise.resolve().then(() => __importStar(require('@picovoice/pvrecorder-node')));
103
+ return pvRecorderModule.PvRecorder.getAvailableDevices();
104
+ }
105
+ catch {
106
+ return [];
107
+ }
108
+ }
109
+ }
110
+ exports.AudioRecorder = AudioRecorder;
111
+ // Utility to save audio buffer to WAV file
112
+ function saveToWav(audioBuffer, outputPath, sampleRate, channels) {
113
+ return new Promise((resolve, reject) => {
114
+ Promise.resolve().then(() => __importStar(require('fs'))).then((fs) => {
115
+ // WAV header
116
+ const header = Buffer.alloc(44);
117
+ const dataSize = audioBuffer.length;
118
+ const fileSize = dataSize + 36;
119
+ // RIFF chunk descriptor
120
+ header.write('RIFF', 0);
121
+ header.writeUInt32LE(fileSize, 4);
122
+ header.write('WAVE', 8);
123
+ // fmt sub-chunk
124
+ header.write('fmt ', 12);
125
+ header.writeUInt32LE(16, 16); // Subchunk1Size
126
+ header.writeUInt16LE(1, 20); // AudioFormat (PCM)
127
+ header.writeUInt16LE(channels, 22); // NumChannels
128
+ header.writeUInt32LE(sampleRate, 24); // SampleRate
129
+ header.writeUInt32LE(sampleRate * channels * 2, 28); // ByteRate
130
+ header.writeUInt16LE(channels * 2, 32); // BlockAlign
131
+ header.writeUInt16LE(16, 34); // BitsPerSample
132
+ // data sub-chunk
133
+ header.write('data', 36);
134
+ header.writeUInt32LE(dataSize, 40);
135
+ const wavBuffer = Buffer.concat([header, audioBuffer]);
136
+ fs.writeFile(outputPath, wavBuffer, (err) => {
137
+ if (err)
138
+ reject(err);
139
+ else
140
+ resolve();
141
+ });
142
+ });
143
+ });
144
+ }
145
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../src/wake-word/recorder.ts"],"names":[],"mappings":"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"}