{"id":26820165,"url":"https://github.com/osteele/speech-provider","last_synced_at":"2026-02-17T05:33:25.050Z","repository":{"id":284843920,"uuid":"956159164","full_name":"osteele/speech-provider","owner":"osteele","description":"A unified TypeScript interface for browser speech synthesis and Eleven Labs TTS voices","archived":false,"fork":false,"pushed_at":"2025-11-08T07:22:59.000Z","size":98,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-08T08:25:26.554Z","etag":null,"topics":["browser","eleven-labs","speech-synthesis","text-to-speech","tts","typescript","voice"],"latest_commit_sha":null,"homepage":"https://osteele.github.io/speech-provider/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/osteele.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-27T19:46:10.000Z","updated_at":"2025-11-08T07:22:58.000Z","dependencies_parsed_at":"2025-03-28T01:11:14.580Z","dependency_job_id":"3ad9c511-fb20-4a67-b3b8-b9cc73e1ceb1","html_url":"https://github.com/osteele/speech-provider","commit_stats":null,"previous_names":["osteele/speech-provider"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/osteele/speech-provider","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/osteele%2Fspeech-provider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/osteele%2Fspeech-provider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/osteele%2Fspeech-provider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/osteele%2Fspeech-provider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/osteele","download_url":"https://codeload.github.com/osteele/speech-provider/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/osteele%2Fspeech-provider/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29534969,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T05:00:25.817Z","status":"ssl_error","status_checked_at":"2026-02-17T04:57:16.126Z","response_time":100,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","eleven-labs","speech-synthesis","text-to-speech","tts","typescript","voice"],"created_at":"2025-03-30T06:20:50.524Z","updated_at":"2026-02-17T05:33:25.043Z","avatar_url":"https://github.com/osteele.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# speech-provider\n\nA unified interface for browser speech synthesis and Eleven Labs voices.\n\n## Installation\n\n```bash\n# Using npm\nnpm install speech-provider\n\n# Using yarn\nyarn add speech-provider\n\n# Using bun\nbun add speech-provider\n```\n\n## Documentation\n\nFull API documentation is available at [https://osteele.github.io/speech-provider/](https://osteele.github.io/speech-provider/).\n\n## Usage\n\n```typescript\nimport { getVoiceProvider } from 'speech-provider';\n\n// Use browser voices only\nconst provider = getVoiceProvider({});\n\n// Use Eleven Labs voices if API key is available\nconst provider = getVoiceProvider({ elevenLabsApiKey: 'your-api-key' });\n\n// Use Eleven Labs with custom cache duration\nconst provider = getVoiceProvider({\n  elevenLabsApiKey: 'your-api-key',\n  cacheMaxAge: 86400 // Cache for 1 day\n});\n\n// Get voices for a specific language\nconst voices = await provider.getVoices({ lang: 'en-US', minVoices: 1 });\n\n// Get default voice for a language\nconst defaultVoice = await provider.getDefaultVoice({ lang: 'en-US' });\n\n// Create and play an utterance\nif (defaultVoice) {\n  const utterance = defaultVoice.createUtterance('Hello, world!');\n  utterance.onstart = () =\u003e console.log('Started speaking');\n  utterance.onend = () =\u003e console.log('Finished speaking');\n  utterance.start();\n}\n```\n\n## Features\n\n- Unified interface for both browser speech synthesis and Eleven Labs voices\n- Automatic fallback to browser voices when Eleven Labs API key is not provided\n- Typesafe API with TypeScript support\n- Simple voice selection by language\n- Event listeners for speech start and end events\n- Automatic caching of Eleven Labs API responses to reduce API calls\n- Configurable cache duration for Eleven Labs responses\n\n## Used In\n\nThis package is used in [Mandarin Sentence\nPractice](https://mandarin-sentence-practice.osteele.com), a web application for\npracticing Mandarin Chinese with listening and translation exercises. The app\nuses this package to provide high-quality text-to-speech for Mandarin sentences,\nwith automatic fallback to browser voices when Eleven Labs is not available.\n\n## API\n\n### `getVoiceProvider(options)`\n\nCreates a voice provider based on the available API keys. Falls back to browser speech synthesis if no API keys are provided.\n\n```typescript\nfunction getVoiceProvider(options: {\n  elevenLabsApiKey?: string | null;\n  cacheMaxAge?: number; // Cache duration in seconds (default: 1 hour)\n}): VoiceProvider;\n```\n\n### `createElevenLabsVoiceProvider(apiKey, options?)`\n\nCreates an Eleven Labs voice provider with optional configuration.\n\n```typescript\nfunction createElevenLabsVoiceProvider(\n  apiKey: string,\n  options?: {\n    validateResponses?: boolean;\n    printVoiceProperties?: boolean;\n    cacheMaxAge?: number; // Cache duration in seconds (default: 1 hour)\n  }\n): VoiceProvider;\n```\n\n### Caching\n\nThe library implements automatic caching for Eleven Labs API responses:\n\n- Browser voices are cached automatically by the browser's speech synthesis engine\n- Eleven Labs responses are cached using IndexedDB with a default duration of 1 hour\n- Cache duration can be configured when creating the provider\n- Cached responses are automatically invalidated after the specified duration\n- Cache can be disabled by setting `cacheMaxAge: null` in the provider options\n\nExamples of cache configuration:\n```typescript\n// Use default 1-hour cache\nconst provider = getVoiceProvider({ elevenLabsApiKey: 'your-api-key' });\n\n// Cache for 1 day\nconst provider = getVoiceProvider({\n  elevenLabsApiKey: 'your-api-key',\n  cacheMaxAge: 86400 // 24 hours in seconds\n});\n\n// Cache for 1 week\nconst provider = getVoiceProvider({\n  elevenLabsApiKey: 'your-api-key',\n  cacheMaxAge: 604800 // 7 days in seconds\n});\n\n// Disable caching (preferred approach)\nconst provider = getVoiceProvider({\n  elevenLabsApiKey: 'your-api-key',\n  cacheMaxAge: null\n});\n\n// Alternative way to disable caching\nconst provider = getVoiceProvider({\n  elevenLabsApiKey: 'your-api-key',\n  cacheMaxAge: 0\n});\n```\n\n### `VoiceProvider` Interface\n\n```typescript\ninterface VoiceProvider {\n  name: string;\n  getVoices({ lang, minVoices }: { lang: string; minVoices: number }): Promise\u003cVoice[]\u003e;\n  getDefaultVoice({ lang }: { lang: string }): Promise\u003cVoice | null\u003e;\n}\n```\n\n### `Voice` Interface\n\n```typescript\ninterface Voice {\n  name: string;\n  id: string;\n  lang: string;\n  provider: VoiceProvider;\n  description: string | null;\n  createUtterance(text: string): Utterance;\n}\n```\n\n### `Utterance` Interface\n\n```typescript\ninterface Utterance {\n  start(): void;\n  stop(): void;\n  set onstart(callback: () =\u003e void);\n  set onend(callback: () =\u003e void);\n}\n```\n\n## Browser Compatibility\n\n### Browser Speech Synthesis\n\nThe browser speech synthesis provider (`BrowserVoiceProvider`) is supported in all modern browsers:\n\n- **Chrome/Edge**: Full support (voices load asynchronously)\n- **Firefox**: Full support\n- **Safari**: Full support (iOS and macOS)\n- **Opera**: Full support\n\n**Note**: Voice availability and quality vary by browser and operating system. Chrome and Edge typically offer the best selection of voices.\n\n### ElevenLabs Provider\n\nThe ElevenLabs provider (`ElevenLabsVoiceProvider`) requires:\n\n- **IndexedDB**: For caching API responses (supported in all modern browsers)\n- **Fetch API**: For making API requests (supported in all modern browsers)\n- **Audio API**: For playing synthesized speech (supported in all modern browsers)\n\n### Minimum Requirements\n\n- Modern browser with ES2022 support\n- IndexedDB support (for ElevenLabs caching)\n- No Internet Explorer support\n\n### Server-Side Rendering (SSR)\n\nThe library is designed for client-side use. When used in SSR environments:\n\n- Browser voice provider gracefully handles the absence of `window.speechSynthesis`\n- Returns empty arrays when browser APIs are unavailable\n- Safe to import in SSR frameworks (Next.js, Nuxt, etc.) but should only be used client-side\n\n## Contributing\n\nContributions are welcome! Please read the [CONTRIBUTING.md](CONTRIBUTING.md) guide for details on our code of conduct and the process for submitting pull requests.\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for a list of changes and version history.\n\n## License\n\nCopyright 2025 by Oliver Steele\n\nAvailable under the MIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fosteele%2Fspeech-provider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fosteele%2Fspeech-provider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fosteele%2Fspeech-provider/lists"}