Files
stack/apps/web/src/lib/api/speech.ts
T
jason.woltjeandClaude Opus 4.6 bc86947d01 feat(#404): add speech settings page with provider config
Implements the SpeechSettings component with four sections:
- STT settings (enable/disable, language preference)
- TTS settings (enable/disable, voice selector, tier preference, auto-play, speed control)
- Voice preview with test button
- Provider status with health indicators

Also adds Slider UI component and getHealthStatus API client function.
30 unit tests covering all sections, toggles, voice loading, and PDA-friendly design.

Fixes #404

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 03:16:27 -06:00

83 lines
1.8 KiB
TypeScript

/**
* Speech API client
* Handles text-to-speech synthesis and voice listing via /api/speech
*/
import { apiGet } from "./client";
import { API_BASE_URL } from "../config";
export type SpeechTier = "default" | "premium" | "fallback";
export interface VoiceInfo {
id: string;
name: string;
language: string;
gender?: string;
preview_url?: string;
tier?: SpeechTier;
isDefault?: boolean;
}
export interface SynthesizeOptions {
text: string;
voice?: string;
speed?: number;
format?: string;
tier?: string;
}
export interface VoicesResponse {
data: VoiceInfo[];
}
export interface ProviderHealth {
available: boolean;
}
export interface HealthResponse {
data: {
stt: ProviderHealth;
tts: ProviderHealth;
};
}
/**
* Fetch available TTS voices
* Optionally filter by tier (default, premium, fallback)
*/
export async function getVoices(tier?: SpeechTier): Promise<VoicesResponse> {
const endpoint = tier ? `/api/speech/voices?tier=${tier}` : "/api/speech/voices";
return apiGet<VoicesResponse>(endpoint);
}
/**
* Fetch health status of speech providers (STT and TTS)
*/
export async function getHealthStatus(): Promise<HealthResponse> {
return apiGet<HealthResponse>("/api/speech/health");
}
/**
* Synthesize text to speech audio
* Returns the audio as a Blob since the API returns binary audio data
*/
export async function synthesizeSpeech(options: SynthesizeOptions): Promise<Blob> {
const url = `${API_BASE_URL}/api/speech/synthesize`;
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify(options),
});
if (!response.ok) {
const errorText = await response.text().catch(() => "Unknown error");
throw new Error(`Speech synthesis failed: ${errorText}`);
}
return response.blob();
}