Skip to content

feat(tts): add Doubao TTS 2.0 (Volcengine Seed-TTS 2.0) provider#283

Merged
cosarah merged 4 commits intomainfrom
feat/doubao-tts
Mar 27, 2026
Merged

feat(tts): add Doubao TTS 2.0 (Volcengine Seed-TTS 2.0) provider#283
cosarah merged 4 commits intomainfrom
feat/doubao-tts

Conversation

@wyuc
Copy link
Copy Markdown
Contributor

@wyuc wyuc commented Mar 26, 2026

Summary

  • Add Doubao TTS 2.0 (Volcengine Seed-TTS 2.0) as a new TTS provider with 17 voices, streaming response parsing, and rate-limit error handling
  • Full integration across types, constants, provider implementation, server config, settings store, i18n (zh-CN + en-US), and UI components
  • Follows the existing TTS provider pattern - no architectural changes

Closes #282

Changed files

File Change
lib/audio/types.ts Add doubao-tts to TTSProviderId union
lib/audio/constants.ts Provider config (17 voices) + default voice
lib/audio/tts-providers.ts TTSRateLimitError + generateDoubaoTTS()
lib/server/provider-config.ts TTS_DOUBAO env var mapping
lib/store/settings.ts doubao-tts default config entry
lib/i18n/settings.ts zh-CN and en-US translations
3 UI components doubao-tts in provider name maps

Test plan

  • pnpm check / pnpm lint / npx tsc --noEmit pass
  • Configure Doubao TTS in Settings > Audio with appId:accessKey and verify voice preview works
  • Verify existing TTS providers are unaffected

🤖 Generated with Claude Code

wyuc and others added 2 commits March 25, 2026 18:52
Add Doubao TTS as a new TTS provider with 17 voices (14 Chinese, 3 English),
streaming response parsing for Volcengine's chunked JSON format, rate-limit
error handling, and full integration across types, constants, provider
implementation, server config, settings store, i18n, and UI components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show two input fields (App ID + Access Key) for Doubao TTS in settings,
instead of requiring the compound "appId:accessKey" format. The values
are combined internally so no changes are needed to the API layer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@cosarah cosarah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issues

Important

  • lib/audio/tts-providers.ts:109TTSRateLimitError is exported and thrown but never caught distinctly from Error anywhere. If retry/backoff logic is planned, add a note or TODO; otherwise this is dead code.

  • lib/audio/tts-providers.ts:484atob() + manual byte copy is less robust and less efficient than Buffer.from(chunk.data, 'base64') for server-side code. Consider:

    const bytes = Buffer.from(chunk.data, 'base64');
    audioChunks.push(new Uint8Array(bytes));
  • tts-settings.tsx:121,149 — "App ID" and "Access Key" labels are hard-coded English strings. Per project convention, UI text needs i18n — use t('settings.doubaoAppId') / t('settings.doubaoAccessKey') with entries in lib/i18n/settings.ts.

  • lib/audio/tts-providers.ts:452 + constants.tssupportedFormats declares ['mp3', 'ogg_opus', 'pcm'] but the request always hard-codes format: 'mp3'. Either use the format from config or trim supportedFormats to ['mp3'] to avoid misleading callers.

Suggestions

  • getTTSProviderName is duplicated across 3 files (pre-existing, but this PR deepens it). Worth extracting to a shared utility.
  • Access Key input field lacks the show/hide toggle that App ID has — minor inconsistency.

Summary

Well-structured PR that follows existing TTS provider patterns. The i18n gap and atobBuffer.from fix should be addressed before merge; the rest are minor.

wyuc and others added 2 commits March 27, 2026 15:22
- Add TODO note explaining TTSRateLimitError's future use for retry/backoff
- Replace atob() + manual byte loop with Buffer.from() for server-side code
- Trim supportedFormats to ['mp3'] since only mp3 is used in requests
- Add i18n keys for Doubao App ID / Access Key labels (zh-CN + en-US)
- Add show/hide toggle to Access Key input field

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@cosarah cosarah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous review items are all properly addressed in aa6b28b

  • TTSRateLimitError: TODO comment added — acceptable
  • atob()Buffer.from(): fixed
  • i18n labels: fixed, both locales updated
  • supportedFormats: trimmed to ['mp3']
  • Bonus: Access Key show/hide toggle added

No new blocking issues. The duplicated getTTSProviderName across 3 files is pre-existing debt worth a follow-up issue.

LGTM — ready to merge.

@cosarah cosarah merged commit 6945707 into main Mar 27, 2026
3 checks passed
@wyuc wyuc deleted the feat/doubao-tts branch March 27, 2026 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(tts): add Doubao TTS 2.0 (Volcengine Seed-TTS 2.0) provider

2 participants