v1.2.0
v1.2
New Feature: Random Voice
Configure a pool of language groups and the integration picks a different voice on every tts.speak call.
Setup: Press the 🎲 button next to Speak in the dashboard card, tick the language groups you want, press "Save and close". Then select 🎲 Random Voice from the language dropdown.
Automations: Pass voice: random in options:
options:
voice: randomA fresh voice is picked on every call from both the dashboard card and automation callers. The pool persists across restarts and is independent of config entries.
Bug Fixes
Switching connection modes (proxy/direct) now works correctly. Disabling or deleting one connection mode while the other is active no longer destroys the shared dashboard entities (language, voice, device, message, speak button). Those entities now survive and transfer cleanly to the remaining connection entry.
Speak button no longer targets a stale TTS entity. After removing one connection mode, the button was staying locked to the old entity. It now checks loaded config entry states rather than potentially stale hass.states.
Message length. HA's text entity enforces a 255 character limit with a colour-coded live counter.
Language dropdown icon was rendering incorrectly. Replaced with a clean MDI translate glyph.
Random Voice state restore on restart was partially broken - the language dropdown restored correctly but the voice dropdown showed a real voice name instead of "Random Voice". Both now restore correctly.
Dashboard Card Changes
- 🎲 dice button added alongside Speak button to open the Random Voice settings panel.
- Speak button no longer full width.
- Status feedback line removed as it was unnecessary.
- Message textarea capped at 255 characters with a live counter.
Internal
- Random voice pool stored via HA's
Storeclass (.storage/tiktoktts_random_voices.json) - the correct HA-idiomatic approach for user preference data independent of config entries. _RandomVoiceAwareCachedict subclass replaces HA's TTSSpeechManager.mem_cacheto force cache misses forvoice=randomcalls, ensuring a fresh voice is picked every time from any call source.services.yamladded to suppress HA startup log warning about undescribed services.- Shared platforms (select, text, button) now tracked per config entry to prevent the
"already been setup"error when switching between connection modes.
v1.1
New Features
- New Voices: Now has over 100 unique voices, in multiple languages
- Additional endpoints: For Direct API usage
- Custom Dashboard Card: Use this card to easily preview voices or to send impromptu messages around your home.
v1.0
This is a modernized fork of the original philipp-luettecke/tiktoktts integration, updated for current Home Assistant versions with significant new features and bug fixes.
Important
If you are upgrading from the original integration, please read the Upgrading from the Original Integration section in the README before installing. A clean removal of the old integration is required.
Bug Fixes
- Fixed
PLATFORMSdeclaration: was a single value instead of a list, causing the integration to fail silently on modern HA versions - Fixed missing commas in
SUPPORTED_VOICES: several singing/expressive voice entries were being silently concatenated into invalid strings by Python - Fixed default language and voice: changed from German (
de/de_001) to English US (en_us/en_us_001) - Fixed broken GitHub URL in original
en.json(pointed to wrong repository)
New Features
- UI config flow: integration is now configured via Settings -> Devices & Services, no
configuration.yamlediting required - Live connection test: endpoint and session ID are validated before saving, so failures are caught at setup time
- Options flow: change endpoint, voice, or session ID at any time via the gear icon, changes take effect immediately without a restart
- Direct TikTok API mode: optional alternative to the proxy that calls TikTok's internal API directly using a browser session cookie, with automatic fallback across 4 known regional endpoints
- Automatic text chunking: direct mode splits long messages at sentence and word boundaries to respect TikTok's 200-character per-request limit
- Retry logic: both proxy and direct modes retry failed requests up to 2 times with backoff before giving up
- Stable entity ID: always
tts.tiktoktts_proxyortts.tiktoktts_direct, no longer a random UUID
Technical / Internal Changes
- Migrated from legacy
Providerbase class to modernTextToSpeechEntity - Replaced deprecated
async_timeoutlibrary with Python's built-inasyncio.timeout - All hardcoded strings (API paths, field names, status codes, retry config) moved to
const.py - Config stored entirely in
entry.data- single source of truth for both setup and options flows - Full developer documentation added to all files
Credits
| Role | Person / Project |
|---|---|
| Original integration | philipp-luettecke/tiktoktts |
| Community TTS proxy | Weilbyte/tiktok-tts |
| Voice list reference | oscie57/tiktok-voice |
