diff --git a/modules/tts/tts-overlay.html b/modules/tts/tts-overlay.html
index a127a2e..1dc3d19 100644
--- a/modules/tts/tts-overlay.html
+++ b/modules/tts/tts-overlay.html
@@ -2168,7 +2168,12 @@ function normalizeMySpeakers(list) {
value: String(item?.value || '').trim(),
source: item?.source || getVoiceSource(item?.value || ''),
resourceId: item?.resourceId || null,
- })).filter(item => item.value);
+ })).filter(item => {
+ if (!item.value) return false;
+ // Keep UI behavior aligned with runtime: remove unsupported legacy free voices.
+ if (item.source === 'free' && !TRIAL_VOICE_KEYS.has(item.value)) return false;
+ return true;
+ });
}
function applyCacheStats(stats = {}) {
diff --git a/modules/tts/tts.js b/modules/tts/tts.js
index 7cedc5b..ad54291 100644
--- a/modules/tts/tts.js
+++ b/modules/tts/tts.js
@@ -915,11 +915,26 @@ async function loadConfig() {
config = await TtsStorage.load();
config.volc = config.volc || {};
+ let legacyPurged = false;
if (Array.isArray(config.volc.mySpeakers)) {
- config.volc.mySpeakers = config.volc.mySpeakers.map(s => ({
+ const normalized = config.volc.mySpeakers.map(s => ({
...s,
source: s.source || getVoiceSource(s.value)
}));
+ const filtered = normalized.filter(s => {
+ // Purge legacy free voices that are no longer supported by the current free voice map.
+ if (s.source === 'free' && !FREE_VOICE_KEYS.has(s.value)) {
+ legacyPurged = true;
+ return false;
+ }
+ return true;
+ });
+ config.volc.mySpeakers = filtered;
+ }
+
+ if (config.volc.defaultSpeaker && getVoiceSource(config.volc.defaultSpeaker) === 'free' && !FREE_VOICE_KEYS.has(config.volc.defaultSpeaker)) {
+ config.volc.defaultSpeaker = FREE_DEFAULT_VOICE;
+ legacyPurged = true;
}
config.volc.disableMarkdownFilter = config.volc.disableMarkdownFilter !== false;
@@ -945,6 +960,12 @@ async function loadConfig() {
config.showFloorButton = config.showFloorButton !== false;
config.showFloatingButton = config.showFloatingButton === true;
+ if (legacyPurged) {
+ await TtsStorage.set('volc', config.volc);
+ await TtsStorage.saveNow({ silent: true });
+ console.info('[TTS] Purged legacy free voices from mySpeakers.');
+ }
+
return config;
}