pi-voice-input 0.3.1 → 0.3.2

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/README.md CHANGED
@@ -18,6 +18,7 @@ Typing long prompts can slow you down. `pi-voice-input` lets you:
18
18
  - **One-key dictation**: `Ctrl+Shift+R` starts recording; press it again to stop and insert text.
19
19
  - **Editor-safe workflow**: transcription is pasted into the current editor only. It does not auto-submit.
20
20
  - **Chinese/English mixed input**: handles prompts that switch between Chinese, English, product names, and technical terms.
21
+ - **Hotword table support**: can pass a VolcEngine boosting table ID to improve recognition of project terms.
21
22
  - **Works on Linux and macOS**: uses common system recording tools.
22
23
  - **Lowers sound while you speak**: automatically turns down system audio during recording, then restores it afterwards.
23
24
  - **No hidden rewriting**: inserts the raw ASR transcript, prefixed with a short note that it may contain voice-recognition errors. If the editor already contains that note, later dictation inserts only the transcript.
@@ -105,12 +106,15 @@ User config keys are:
105
106
  ```json
106
107
  {
107
108
  "volcApiKey": "",
109
+ "boostingTableId": "",
108
110
  "duckSystemVolume": true,
109
111
  "duckSystemVolumeFactor": 0.5,
110
112
  "duckSystemVolumeFadeMs": 300
111
113
  }
112
114
  ```
113
115
 
116
+ Set `boostingTableId` to a VolcEngine hotword/boosting table ID to send it as `boosting_table_id` on ASR requests. Leave it empty to disable hotword-table boosting. Boosting table name is not configured yet.
117
+
114
118
  ## System requirements
115
119
 
116
120
  Linux needs one recording tool:
@@ -135,7 +139,7 @@ On macOS, allow microphone access for your terminal or pi host app when prompted
135
139
  ## Troubleshooting
136
140
 
137
141
  - Run `/voice status` to see whether recording is active.
138
- - Run `/voice config` to confirm the API key is detected.
142
+ - Run `/voice config` to confirm the API key and optional boosting table ID are detected.
139
143
  - Run `/voice key` again if the key was changed or expired.
140
144
  - On macOS, check microphone permission if recording immediately fails.
141
145
  - On Linux, make sure `pw-record` or `arecord` is installed and your microphone works in other apps.
package/ROADMAP.md CHANGED
@@ -7,6 +7,7 @@ This roadmap lists user-visible work planned for pi Voice Input. It is intention
7
7
  - Linux voice input through `pw-record` or `arecord`
8
8
  - macOS voice input through the system `afrecord` command
9
9
  - VolcEngine WebSocket ASR
10
+ - Optional VolcEngine hotword boosting table ID
10
11
  - Raw ASR transcript insertion with a voice-input caveat wrapper
11
12
 
12
13
  ## Planned
@@ -42,6 +42,7 @@ type JsonObject = Record<string, unknown>;
42
42
 
43
43
  type VoiceInputConfigFile = {
44
44
  volcApiKey: string;
45
+ boostingTableId: string;
45
46
  duckSystemVolume: boolean;
46
47
  duckSystemVolumeFactor: number;
47
48
  duckSystemVolumeFadeMs: number;
@@ -55,6 +56,7 @@ type VoiceConfig = {
55
56
  language: string;
56
57
  uid: string;
57
58
  prompt: string;
59
+ boostingTableId: string;
58
60
  segmentMs: number;
59
61
  requestTimeoutMs: number;
60
62
  finalizeDelayMs: number;
@@ -114,6 +116,7 @@ function ensureDir(dir: string) {
114
116
  function defaultConfigFile(): VoiceInputConfigFile {
115
117
  return {
116
118
  volcApiKey: "",
119
+ boostingTableId: "",
117
120
  duckSystemVolume: true,
118
121
  duckSystemVolumeFactor: 0.5,
119
122
  duckSystemVolumeFadeMs: 300,
@@ -148,6 +151,11 @@ function normalizeConfigFile(input: unknown): VoiceInputConfigFile {
148
151
  const root = isObject(input) ? input : {};
149
152
  return {
150
153
  volcApiKey: stringField(root, "volcApiKey", defaults.volcApiKey).trim(),
154
+ boostingTableId: stringField(
155
+ root,
156
+ "boostingTableId",
157
+ stringField(root, "boosting_table_id", defaults.boostingTableId),
158
+ ).trim(),
151
159
  duckSystemVolume: booleanField(root, "duckSystemVolume", defaults.duckSystemVolume),
152
160
  duckSystemVolumeFactor: clamp(numberField(root, "duckSystemVolumeFactor", defaults.duckSystemVolumeFactor), 0, 1),
153
161
  duckSystemVolumeFadeMs: Math.round(clamp(numberField(root, "duckSystemVolumeFadeMs", defaults.duckSystemVolumeFadeMs), 0, 3000)),
@@ -181,6 +189,7 @@ function getConfig(): VoiceConfig {
181
189
  language: "",
182
190
  uid: "pi-voice-input",
183
191
  prompt: "",
192
+ boostingTableId: fileConfig.boostingTableId,
184
193
  segmentMs: 5000,
185
194
  requestTimeoutMs: 90000,
186
195
  finalizeDelayMs: 100,
@@ -790,6 +799,7 @@ async function transcribePcm(pcm: Buffer, durationMs: number, config: VoiceConfi
790
799
  "X-Api-Resource-Id": config.resourceId,
791
800
  "X-Api-Connect-Id": connectId,
792
801
  "X-Api-Request-Id": connectId,
802
+ "X-Api-Sequence": "-1",
793
803
  },
794
804
  handshakeTimeout: 15_000,
795
805
  });
@@ -867,6 +877,10 @@ async function transcribePcm(pcm: Buffer, durationMs: number, config: VoiceConfi
867
877
  audioPayload.language = config.language;
868
878
  }
869
879
 
880
+ const corpusPayload: Record<string, unknown> = {};
881
+ if (config.boostingTableId) corpusPayload.boosting_table_id = config.boostingTableId;
882
+ if (config.prompt) corpusPayload.context = config.prompt;
883
+
870
884
  const requestPayload: Record<string, unknown> = {
871
885
  user: { uid: config.uid || "pi-voice-input" },
872
886
  audio: audioPayload,
@@ -877,7 +891,7 @@ async function transcribePcm(pcm: Buffer, durationMs: number, config: VoiceConfi
877
891
  enable_ddc: config.enableDdc,
878
892
  show_utterances: config.showUtterances,
879
893
  result_type: "full",
880
- ...(config.prompt ? { corpus: { context: config.prompt } } : {}),
894
+ ...(Object.keys(corpusPayload).length ? { corpus: corpusPayload } : {}),
881
895
  },
882
896
  };
883
897
 
@@ -1108,6 +1122,7 @@ function setupHelp(config = getConfig()): string {
1108
1122
  "- Current provider: VolcEngine WebSocket ASR",
1109
1123
  `- Config file: ${config.configPath}`,
1110
1124
  `- API key: ${config.apiKey ? "set" : "missing"}`,
1125
+ `- Hotword boosting table ID: ${config.boostingTableId ? "set" : "not set"}`,
1111
1126
  "- To create/update the JSON config file, run: /voice init",
1112
1127
  "- To save/update the key, run: /voice key",
1113
1128
  "- Output: raw ASR transcript wrapped with a short voice-input caveat",
@@ -1147,12 +1162,13 @@ function configSummary(config: VoiceConfig): string {
1147
1162
  "Voice input config:",
1148
1163
  `- config file: ${config.configPath}${existsSync(config.configPath) ? "" : " (missing; run /voice init to create it)"}`,
1149
1164
  `- volcApiKey: ${config.apiKey ? "set" : "missing"} (update with /voice key)`,
1165
+ `- boostingTableId: ${config.boostingTableId ? "set" : "not set"}`,
1150
1166
  "- outputMode: raw transcript with voice-input caveat wrapper",
1151
1167
  `- duckSystemVolume: ${config.duckSystemVolume ? "enabled" : "disabled"}`,
1152
1168
  `- duckSystemVolumeFactor: ${config.duckSystemVolumeFactor}`,
1153
1169
  `- duckSystemVolumeFadeMs: ${config.duckSystemVolumeFadeMs}`,
1154
1170
  `- current recording device: ${currentDevice}`,
1155
- "Config keys: volcApiKey, duckSystemVolume, duckSystemVolumeFactor, duckSystemVolumeFadeMs.",
1171
+ "Config keys: volcApiKey, boostingTableId, duckSystemVolume, duckSystemVolumeFactor, duckSystemVolumeFadeMs.",
1156
1172
  `VolcEngine API key URL: ${VOLC_API_KEY_URL}`,
1157
1173
  ].join("\n");
1158
1174
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-voice-input",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Press Ctrl+Shift+R to dictate prompts into Pi using VolcEngine ASR",
5
5
  "type": "module",
6
6
  "keywords": [