From 56d2ac40da6710adfe3de94f6b09bd53d9bb6db9 Mon Sep 17 00:00:00 2001 From: Roland Date: Wed, 27 May 2026 00:13:40 +0200 Subject: [PATCH 1/2] fix(vscode): detect Windows speech input devices --- .changeset/bright-mics-tap.md | 5 ++++ .../kilo-vscode/src/speech-to-text/capture.ts | 24 ++++++++++++++++++- .../tests/unit/speech-to-text-capture.test.ts | 18 ++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 .changeset/bright-mics-tap.md diff --git a/.changeset/bright-mics-tap.md b/.changeset/bright-mics-tap.md new file mode 100644 index 0000000000..c6a1aa8606 --- /dev/null +++ b/.changeset/bright-mics-tap.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Fix Windows speech input device detection when FFmpeg lists DirectShow microphones by section. diff --git a/packages/kilo-vscode/src/speech-to-text/capture.ts b/packages/kilo-vscode/src/speech-to-text/capture.ts index 92f127dc2c..d0a9b5475a 100644 --- a/packages/kilo-vscode/src/speech-to-text/capture.ts +++ b/packages/kilo-vscode/src/speech-to-text/capture.ts @@ -313,7 +313,29 @@ async function listDshowAudioDevices(bin: string): Promise { export function parseDshowAudioDevices(raw: string): string[] { const devices = new Set() - for (const match of raw.matchAll(/"([^"]+)"\s+\(audio\)/g)) devices.add(match[1]!) + const state = { audio: false } + const legacy = /"([^"]+)"\s+\(audio\)/ + const quoted = /"([^"]+)"/ + const section = (line: string) => /DirectShow audio devices/i.test(line) + const other = (line: string) => /DirectShow (video|external) devices/i.test(line) + const alt = (line: string) => /Alternative name/i.test(line) + for (const line of raw.split(/\r?\n/)) { + const match = legacy.exec(line) + if (match) devices.add(match[1]!) + + if (section(line)) { + state.audio = true + continue + } + if (other(line)) { + if (!state.audio) continue + state.audio = false + break + } + if (!state.audio || alt(line)) continue + const found = quoted.exec(line) + if (found) devices.add(found[1]!) + } return [...devices] } diff --git a/packages/kilo-vscode/tests/unit/speech-to-text-capture.test.ts b/packages/kilo-vscode/tests/unit/speech-to-text-capture.test.ts index c840008d9b..84ebbf6942 100644 --- a/packages/kilo-vscode/tests/unit/speech-to-text-capture.test.ts +++ b/packages/kilo-vscode/tests/unit/speech-to-text-capture.test.ts @@ -14,6 +14,24 @@ describe("parseDshowAudioDevices", () => { expect(parseDshowAudioDevices(raw)).toEqual(["Microphone Array (Realtek Audio)", "Webcam Microphone"]) }) + it("extracts section-listed Windows dshow audio device names", () => { + const raw = ` +[dshow @ 000001] DirectShow video devices (some may be both video and audio devices) +[dshow @ 000001] "OBS Virtual Camera" +[dshow @ 000001] Alternative name "@device_video" +[dshow @ 000001] DirectShow audio devices +[dshow @ 000001] "Headset (2- Bose QuietComfort 35 Series II)" +[dshow @ 000001] Alternative name "@device_headset" +[dshow @ 000001] "Microphone (MSI Sound Tune)" +[dshow @ 000001] Alternative name "@device_microphone" +` + + expect(parseDshowAudioDevices(raw)).toEqual([ + "Headset (2- Bose QuietComfort 35 Series II)", + "Microphone (MSI Sound Tune)", + ]) + }) + it("deduplicates repeated dshow audio device names", () => { const raw = `"Microphone" (audio)\n"Microphone" (audio)` From 6ab07aad600b0b313f1831763176146ad557ca07 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Fri, 29 May 2026 16:45:52 +0200 Subject: [PATCH 2/2] fix(vscode): preserve DirectShow microphone display names --- packages/kilo-vscode/src/speech-to-text/capture.ts | 2 +- packages/kilo-vscode/tests/unit/speech-to-text-capture.test.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/kilo-vscode/src/speech-to-text/capture.ts b/packages/kilo-vscode/src/speech-to-text/capture.ts index d0a9b5475a..03efa67aaf 100644 --- a/packages/kilo-vscode/src/speech-to-text/capture.ts +++ b/packages/kilo-vscode/src/speech-to-text/capture.ts @@ -318,7 +318,7 @@ export function parseDshowAudioDevices(raw: string): string[] { const quoted = /"([^"]+)"/ const section = (line: string) => /DirectShow audio devices/i.test(line) const other = (line: string) => /DirectShow (video|external) devices/i.test(line) - const alt = (line: string) => /Alternative name/i.test(line) + const alt = (line: string) => /\]\s+Alternative name\s+"/i.test(line) for (const line of raw.split(/\r?\n/)) { const match = legacy.exec(line) if (match) devices.add(match[1]!) diff --git a/packages/kilo-vscode/tests/unit/speech-to-text-capture.test.ts b/packages/kilo-vscode/tests/unit/speech-to-text-capture.test.ts index 84ebbf6942..8b68ca79c7 100644 --- a/packages/kilo-vscode/tests/unit/speech-to-text-capture.test.ts +++ b/packages/kilo-vscode/tests/unit/speech-to-text-capture.test.ts @@ -24,11 +24,14 @@ describe("parseDshowAudioDevices", () => { [dshow @ 000001] Alternative name "@device_headset" [dshow @ 000001] "Microphone (MSI Sound Tune)" [dshow @ 000001] Alternative name "@device_microphone" +[dshow @ 000001] "Alternative name Microphone" +[dshow @ 000001] Alternative name "@device_alternative" ` expect(parseDshowAudioDevices(raw)).toEqual([ "Headset (2- Bose QuietComfort 35 Series II)", "Microphone (MSI Sound Tune)", + "Alternative name Microphone", ]) })