feat: Add Whisper GPU speech-to-text with progressive transcription

- Add faster-whisper Python server for GPU-accelerated transcription
- Support dual mode: Web Speech API or Whisper GPU (toggleable)
- Progressive transcription every 3 seconds while recording
- Separate terminal server process (stable during hot-reload)
- Add Ctrl+V paste and Ctrl+C copy support in FloatingTerminal
- Add MCP tools: whisper_start, whisper_stop, whisper_toggle, whisper_status
- Update package.json with separate api/terminal/frontend processes
This commit is contained in:
2026-02-13 23:47:52 -06:00
parent e867b7873e
commit 638e6ac8e0
10 changed files with 1009 additions and 31 deletions

66
server/routes/whisper.ts Normal file
View File

@@ -0,0 +1,66 @@
/**
* Whisper API routes
* Control the local GPU-accelerated speech-to-text server
*/
import {
startWhisperServer,
stopWhisperServer,
toggleWhisperServer,
getWhisperState,
getWhisperPort
} from '../services/whisper'
export async function handleWhisperRoutes(req: Request): Promise<Response | null> {
const url = new URL(req.url)
const path = url.pathname
// GET /api/whisper/status - Get current state
if (path === '/api/whisper/status' && req.method === 'GET') {
const state = await getWhisperState()
return Response.json(state)
}
// POST /api/whisper/start - Start Whisper server
if (path === '/api/whisper/start' && req.method === 'POST') {
const success = await startWhisperServer()
const state = await getWhisperState()
return Response.json({
success,
...state,
message: success ? 'Whisper server started' : 'Failed to start Whisper server'
})
}
// POST /api/whisper/stop - Stop Whisper server
if (path === '/api/whisper/stop' && req.method === 'POST') {
const success = stopWhisperServer()
const state = await getWhisperState()
return Response.json({
success,
...state,
message: success ? 'Whisper server stopped' : 'Failed to stop Whisper server'
})
}
// POST /api/whisper/toggle - Toggle Whisper on/off
if (path === '/api/whisper/toggle' && req.method === 'POST') {
const result = await toggleWhisperServer()
const state = await getWhisperState()
return Response.json({
...result,
...state,
message: state.enabled ? 'Whisper enabled (GPU)' : 'Whisper disabled (using Web Speech API)'
})
}
// GET /api/whisper/port - Get Whisper WebSocket port
if (path === '/api/whisper/port' && req.method === 'GET') {
return Response.json({
port: getWhisperPort(),
url: `ws://localhost:${getWhisperPort()}`
})
}
return null
}