Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when working with Quetrex's voice interface, OpenAI Realtime API, WebRTC, or echo cancellation. Knows Quetrex's specific voice architecture decisions and patterns. CRITICAL - prevents breaking working voice system.
.claude/skills/aiskillstore-voice-system-expert/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-12 | ✗→✓ | ▲ Improved | 35% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 100% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 7% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 6% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 26% | 0% |
Quetrex's voice system architecture is extensively documented and battle-tested. Before making ANY changes to voice-related code, you MUST read:
Location: src/lib/openai-realtime.ts
This is Decision 4 from VOICE-SYSTEM.md and the definitive approach documented in ADR-001.
typescript// ✅ CORRECT: Always-on microphone const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, // CRITICAL - browser handles echo cancellation noiseSuppression: true, autoGainControl: true, }, }) // Microphone track stays ENABLED throughout conversation // Browser's native AEC prevents feedback loops // Server-side VAD (Voice Activity Detection) handles turn detection
User speaks
↓
Microphone (always enabled, echoCancellation: true)
↓
WebRTC → OpenAI Realtime API
↓
Server-side VAD detects speech
↓
OpenAI processes and responds
↓
Audio response via WebRTC
↓
HTMLAudioElement playback (stays in browser pipeline)
↓
Browser AEC compares mic input + speaker output
↓
Echo automatically canceled (no feedback loop)Browser Echo Cancellation Requirements:
This is the industry standard:
They ALL use always-on microphone + browser AEC.
typescript// ❌ WRONG - This breaks echo cancellation async function pauseRecording() { microphone.enabled = false // DON'T DO THIS } async function resumeRecording() { microphone.enabled = true // DON'T DO THIS }
Why this fails:
typescript// ❌ WRONG - AudioWorklet bypass to native audio const workletNode = new AudioWorkletNode(audioContext, 'bypass-processor') workletNode.port.postMessage({ cmd: 'route-to-native' })
Why this fails:
typescript// ❌ WRONG - Custom AEC implementation class CustomEchoCanceller { cancelEcho(input: AudioBuffer, output: AudioBuffer) { // Complex DSP code... } }
Why this fails:
typescript// ❌ WRONG - Delays for echo prevention await new Promise(resolve => setTimeout(resolve, 500)) await playAudio() await new Promise(resolve => setTimeout(resolve, 500)) resumeRecording()
Why this fails:
typescript// ✅ Can tweak these settings const constraints = { audio: { echoCancellation: true, // MUST be true noiseSuppression: true, // Can adjust autoGainControl: true, // Can adjust sampleRate: 24000, // Can change for quality channelCount: 1, // Mono is fine for voice }, }
typescript// ✅ Can manage connection lifecycle async function connectVoice() { // Setup WebRTC connection // Start streaming // Handle connection events } async function disconnectVoice() { // Clean up WebRTC connection // Stop streaming // Release microphone }
typescript// ✅ Can add visual indicators function onVoiceActivity(active: boolean) { if (active) { // Show "listening" indicator // Animate microphone icon } else { // Show "idle" indicator } }
typescript// ✅ Can improve error handling try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }) } catch (error) { if (error.name === 'NotAllowedError') { // Show permission request UI } else if (error.name === 'NotFoundError') { // Show "no microphone found" error } }
Primary file: src/lib/openai-realtime.ts
Key functions:
setupMediaStream() - Initializes microphone with correct constraintsconnectToOpenAI() - Establishes WebRTC connectionhandleAudioResponse() - Plays AI responses via HTMLAudioElementDO NOT modify:
CAN modify:
From ADR-001:
Option A: Trust Industry Pattern (CHOSEN)
Options Rejected:
IMPORTANT: Quetrex is now a pure web application, not a Tauri desktop app.
Why this matters for voice:
The WKWebView Problem (Historical): Quetrex was originally a Tauri desktop app. On macOS, Tauri uses WKWebView, which has a bug: WebRTC audio playback doesn't work. This forced us to try workarounds (AudioWorklet bypass, native audio routing), which all broke echo cancellation.
Solution: Convert to web application. Now echo cancellation works perfectly everywhere.
If you must modify voice code:
Before any voice changes, read:
docs/decisions/ADR-001-VOICE-ECHO-CANCELLATION.mddocs/architecture/VOICE-SYSTEM.mddocs/development/abandoned-approaches/If you see mentions of:
The Golden Rule: Trust browser echo cancellation. Always-on microphone + echoCancellation: true + audio in browser pipeline = Perfect echo cancellation.
DO:
echoCancellation: trueDON'T:
If in doubt: Read ADR-001 and VOICE-SYSTEM.md. The architecture is thoroughly documented for a reason.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-12 | fail→pass | 20,020 | 18,155 | -9% | 1 | 1 | 0% | 3,539 | 4,760 | +35% | 0 | 0 | — |
case-01 | pass→pass | 27,662 | 26,425 | -4% | 1 | 1 | 0% | 4,857 | 6,540 | +35% | 0 | 0 | — |
case-02 | fail→pass | 17,856 | 18,552 | +4% | 1 | 1 | 0% | 2,255 | 4,507 | +100% | 0 | 0 | — |
case-03 | fail→pass | 25,379 | 14,231 | -44% | 1 | 1 | 0% | 3,509 | 3,744 | +7% | 0 | 0 | — |
case-04 | fail→pass | 26,390 | 15,056 | -43% | 1 | 1 | 0% | 4,183 | 4,454 | +6% | 0 | 0 | — |
case-05 | fail→fail | 10,594 | 10,609 | +0% | 1 | 1 | 0% | 1,937 | 3,245 | +68% | 0 | 0 | — |
case-06 | pass→pass | 9,149 | 12,466 | +36% | 1 | 1 | 0% | 1,780 | 3,537 | +99% | 0 | 0 | — |
case-13 | pass→fail | 22,977 | 9,605 | -58% | 1 | 1 | 0% | 3,085 | 2,513 | -19% | 0 | 0 | — |
case-07 | pass→pass | 23,658 | 15,964 | -33% | 1 | 1 | 0% | 4,119 | 5,598 | +36% | 0 | 0 | — |
case-08 | fail→pass | 14,595 | 14,467 | -1% | 1 | 1 | 0% | 2,869 | 3,625 | +26% | 0 | 0 | — |
case-09 | fail→pass | 29,968 | 13,100 | -56% | 1 | 1 | 0% | 5,058 | 4,466 | -12% | 0 | 0 | — |
case-10 | pass→pass | 13,479 | 16,238 | +20% | 1 | 1 | 0% | 2,803 | 4,166 | +49% | 0 | 0 | — |
case-11 | pass→pass | 10,882 | 16,029 | +47% | 1 | 1 | 0% | 1,826 | 3,838 | +110% | 0 | 0 | — |
case-14 | fail→pass | 32,770 | 25,520 | -22% | 1 | 1 | 0% | 4,626 | 5,996 | +30% | 0 | 0 | — |
case-15 | fail→pass | 14,511 | 7,494 | -48% | 1 | 1 | 0% | 1,736 | 3,611 | +108% | 0 | 0 | — |
case-16 | pass→pass | 19,299 | 13,982 | -28% | 1 | 1 | 0% | 2,599 | 3,795 | +46% | 0 | 0 | — |
case-17 | pass→pass | 19,304 | 20,919 | +8% | 1 | 1 | 0% | 3,806 | 4,978 | +31% | 0 | 0 | — |
case-18 | pass→pass | 19,089 | 18,647 | -2% | 1 | 1 | 0% | 2,677 | 4,651 | +74% | 0 | 0 | — |
case-19 | pass→pass | 16,559 | 27,267 | +65% | 1 | 1 | 0% | 2,017 | 3,465 | +72% | 0 | 0 | — |
case-20 | pass→pass | 16,665 | 16,832 | +1% | 1 | 1 | 0% | 2,386 | 4,556 | +91% | 0 | 0 | — |
case-21 | pass→pass | 34,652 | 20,109 | -42% | 1 | 1 | 0% | 2,496 | 4,550 | +82% | 0 | 0 | — |
case-22 | pass→pass | 17,973 | 16,447 | -8% | 1 | 1 | 0% | 2,300 | 4,357 | +89% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.