pi-voice-input 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -7,7 +7,8 @@ Development workflow for this repo.
7
7
  - Package: `pi-voice-input`
8
8
  - GitHub: `git@github.com:tr-nc/pi-voice-input.git`
9
9
  - npm: `pi-voice-input`
10
- - Main extension: `extensions/voice-input.ts`
10
+ - Package entrypoint: `extensions/index.ts`
11
+ - Main extension implementation: `extensions/voice-input.ts`
11
12
  - Current provider: VolcEngine WebSocket ASR only
12
13
  - Provider architecture should remain extensible so more ASR providers can be added later.
13
14
 
@@ -25,8 +26,8 @@ Run from the repo root:
25
26
 
26
27
  ```bash
27
28
  npm install --package-lock=false
28
- npx tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2022 --skipLibCheck --types node extensions/voice-input.ts
29
- PI_OFFLINE=1 pi -e ./extensions/voice-input.ts --list-models
29
+ npx tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2022 --skipLibCheck --types node extensions/index.ts
30
+ PI_OFFLINE=1 pi -e . --list-models
30
31
  npm pack --dry-run
31
32
  ```
32
33
 
@@ -37,6 +38,7 @@ AGENTS.md
37
38
  CONTRIBUTING.md
38
39
  README.md
39
40
  ROADMAP.md
41
+ extensions/index.ts
40
42
  extensions/voice-input.ts
41
43
  package.json
42
44
  ```
@@ -90,7 +92,7 @@ PI_OFFLINE=1 pi --list-models
90
92
  If testing a local checkout instead of the npm package, use:
91
93
 
92
94
  ```bash
93
- pi -e ./extensions/voice-input.ts
95
+ pi -e .
94
96
  ```
95
97
 
96
98
  Do not leave local development wrappers in `~/.pi/agent/extensions/voice-input.ts` when validating the npm installation path.
package/CONTRIBUTING.md CHANGED
@@ -41,10 +41,10 @@ cd pi-voice-input
41
41
  npm install
42
42
  ```
43
43
 
44
- Run the extension directly from the checkout:
44
+ Run the package directly from the checkout:
45
45
 
46
46
  ```bash
47
- pi -e ./extensions/voice-input.ts
47
+ pi -e .
48
48
  ```
49
49
 
50
50
  Or install the local checkout into pi while developing:
@@ -82,8 +82,8 @@ Do not commit this config file or any secrets.
82
82
  Before opening a pull request, run:
83
83
 
84
84
  ```bash
85
- npx tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2022 --skipLibCheck --types node extensions/voice-input.ts
86
- PI_OFFLINE=1 pi -e ./extensions/voice-input.ts --list-models
85
+ npx tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2022 --skipLibCheck --types node extensions/index.ts
86
+ PI_OFFLINE=1 pi -e . --list-models
87
87
  npm pack --dry-run
88
88
  git diff --check
89
89
  ```
package/README.md CHANGED
@@ -10,23 +10,23 @@ A publishable, pure TypeScript [pi](https://pi.dev/) extension for Linux and mac
10
10
  Current scope:
11
11
 
12
12
  - Linux uses `pw-record` from PipeWire tools or `arecord` from alsa-utils.
13
- - macOS uses the system `afrecord` command. This path is implemented but not yet validated by the maintainer on macOS hardware.
13
+ - macOS uses `afrecord` when present, otherwise `ffmpeg` with AVFoundation.
14
14
  - A VolcEngine Speech API key is required.
15
15
  - This is not a local/offline ASR engine.
16
16
 
17
17
  The provider layer is intended to be extensible. **Current version supports only VolcEngine WebSocket ASR.**
18
18
 
19
- No Python, `uv`, upload service, or `ffmpeg` is required for normal shortcut usage.
19
+ No Python, `uv`, or upload service is required for normal shortcut usage. On macOS systems without `afrecord`, install `ffmpeg` for recording.
20
20
 
21
21
  ## Architecture
22
22
 
23
23
  ```text
24
- pi extension: extensions/voice-input.ts
24
+ pi extension: extensions/index.ts → extensions/voice-input.ts
25
25
  ├─ registers Ctrl+Shift+R and /voice commands
26
26
  ├─ starts/stops a local recorder process
27
27
  │ ├─ Linux preferred: pw-record
28
28
  │ ├─ Linux fallback: arecord
29
- │ └─ macOS: afrecord
29
+ │ └─ macOS: afrecord, or ffmpeg/AVFoundation fallback
30
30
  ├─ records a temporary 16 kHz mono 16-bit WAV
31
31
  ├─ parses the WAV container in TypeScript and extracts raw PCM
32
32
  ├─ sends PCM frames to the configured ASR provider via ws
@@ -44,9 +44,9 @@ System dependency, one of:
44
44
 
45
45
  - Linux: `pw-record` from PipeWire tools, preferred
46
46
  - Linux: `arecord` from alsa-utils, fallback
47
- - macOS: `afrecord`, included with macOS
47
+ - macOS: `afrecord` when present, or `ffmpeg` from Homebrew (`brew install ffmpeg`) as the AVFoundation fallback
48
48
 
49
- On macOS, grant Terminal or your pi host app microphone permission when prompted. If macOS has previously denied microphone access, enable it in System Settings → Privacy & Security → Microphone.
49
+ On macOS, grant Terminal, ffmpeg, or your pi host app microphone permission when prompted. If macOS has previously denied microphone access, enable it in System Settings → Privacy & Security → Microphone.
50
50
 
51
51
  ## Install / Update
52
52
 
@@ -164,10 +164,10 @@ cd pi-voice-input
164
164
  npm install
165
165
  ```
166
166
 
167
- Run directly without installing the package:
167
+ Run directly from the package checkout:
168
168
 
169
169
  ```bash
170
- pi -e ./extensions/voice-input.ts
170
+ pi -e .
171
171
  ```
172
172
 
173
173
  Or install the local checkout while developing:
@@ -0,0 +1 @@
1
+ export { default } from "./voice-input.js";
@@ -217,7 +217,10 @@ function commandOutput(command: string, args: string[], timeoutMs = 1500): strin
217
217
  }
218
218
 
219
219
  function selectRecorderExecutable(): string {
220
- if (platform() === "darwin" && commandExists("afrecord")) return "afrecord";
220
+ if (platform() === "darwin") {
221
+ if (commandExists("afrecord")) return "afrecord";
222
+ if (commandExists("ffmpeg")) return "ffmpeg";
223
+ }
221
224
  if (commandExists("pw-record")) return "pw-record";
222
225
  if (commandExists("arecord")) return "arecord";
223
226
  return "";
@@ -237,7 +240,31 @@ function recorderCommand(config: VoiceConfig, outputPath: string): string[] {
237
240
  if (executable === "afrecord") {
238
241
  return ["afrecord", "-f", "WAVE", "-d", "LEI16@16000", "-c", "1", outputPath];
239
242
  }
240
- throw new Error("No recorder found. On Linux, install PipeWire tools (pw-record) or alsa-utils (arecord). On macOS, afrecord should be available with the system.");
243
+ if (executable === "ffmpeg" && platform() === "darwin") {
244
+ return [
245
+ "ffmpeg",
246
+ "-hide_banner",
247
+ "-loglevel",
248
+ "error",
249
+ "-nostdin",
250
+ "-y",
251
+ "-f",
252
+ "avfoundation",
253
+ "-i",
254
+ config.recorderTarget || "none:default",
255
+ "-vn",
256
+ "-acodec",
257
+ "pcm_s16le",
258
+ "-ar",
259
+ "16000",
260
+ "-ac",
261
+ "1",
262
+ "-f",
263
+ "wav",
264
+ outputPath,
265
+ ];
266
+ }
267
+ throw new Error("No recorder found. On Linux, install PipeWire tools (pw-record) or alsa-utils (arecord). On macOS, install ffmpeg (brew install ffmpeg) if afrecord is not available.");
241
268
  }
242
269
 
243
270
  type PipeWireSource = {
@@ -326,6 +353,7 @@ function recordingDeviceName(config: VoiceConfig, recorderExecutable: string): s
326
353
  if (recorderExecutable === "pw-record") return pipeWireSourceName(config.recorderTarget);
327
354
  if (recorderExecutable === "arecord") return "ALSA default microphone";
328
355
  if (recorderExecutable === "afrecord") return "macOS default microphone";
356
+ if (recorderExecutable === "ffmpeg" && platform() === "darwin") return "macOS default microphone (ffmpeg/AVFoundation)";
329
357
  return config.recorderTarget || "default microphone";
330
358
  }
331
359
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-voice-input",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Press Ctrl+Shift+R to dictate prompts into Pi using VolcEngine ASR",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -34,7 +34,7 @@
34
34
  ],
35
35
  "pi": {
36
36
  "extensions": [
37
- "extensions"
37
+ "extensions/index.ts"
38
38
  ]
39
39
  },
40
40
  "dependencies": {