diff --git a/extension/entrypoints/background/notifications.ts b/extension/entrypoints/background/notifications.ts
index 8064ca22e..9bf141f85 100644
--- a/extension/entrypoints/background/notifications.ts
+++ b/extension/entrypoints/background/notifications.ts
@@ -189,6 +189,7 @@ export async function notifyUser(title: string, message: string, url?: string) {
if (matchedVoice) ttsMessage.voice = matchedVoice;
}
+ ttsMessage.rate = settings.notifications.ttsRate;
window.speechSynthesis.speak(ttsMessage);
} else {
// Offscreen documents
@@ -199,6 +200,7 @@ export async function notifyUser(title: string, message: string, url?: string) {
text: text,
volume: settings.notifications.volume / 100,
voice: settings.notifications.ttsVoice,
+ rate: settings.notifications.ttsRate,
} satisfies OffscreenMessage);
}
}
diff --git a/extension/entrypoints/offscreen/offscreen.ts b/extension/entrypoints/offscreen/offscreen.ts
index 41b464bba..831bf4b65 100644
--- a/extension/entrypoints/offscreen/offscreen.ts
+++ b/extension/entrypoints/offscreen/offscreen.ts
@@ -16,9 +16,10 @@ interface PlayTTSOptions {
text: string;
volume: number;
voice: string;
+ rate: number;
}
-function playTTS({ text, volume, voice }: PlayTTSOptions) {
+function playTTS({ text, volume, voice, rate }: PlayTTSOptions) {
const ttsMessage = new SpeechSynthesisUtterance(text);
ttsMessage.volume = volume;
if (voice !== "default") {
@@ -26,6 +27,8 @@ function playTTS({ text, volume, voice }: PlayTTSOptions) {
if (matchedVoice) ttsMessage.voice = matchedVoice;
}
+ ttsMessage.rate = rate;
+
window.speechSynthesis.speak(ttsMessage);
}
diff --git a/extension/entrypoints/options/index.html b/extension/entrypoints/options/index.html
index e5c81fae3..32ace6415 100644
--- a/extension/entrypoints/options/index.html
+++ b/extension/entrypoints/options/index.html
@@ -737,6 +737,10 @@
+
+
+
+
diff --git a/extension/entrypoints/options/settings.ts b/extension/entrypoints/options/settings.ts
index 3580ccfc1..ce47127e8 100644
--- a/extension/entrypoints/options/settings.ts
+++ b/extension/entrypoints/options/settings.ts
@@ -744,6 +744,7 @@ async function setupPreferences(requireCleanup: boolean = false) {
_preferences.querySelector("#notification-sound").value = settings.notifications.sound;
_preferences.querySelector("#notification-tts").checked = settings.notifications.tts;
+ _preferences.querySelector("#notification-ttsRate").value = settings.notifications.ttsRate.toString();
_preferences.querySelector("#notification-link").checked = settings.notifications.link;
_preferences.querySelector("#notification-requireInteraction").checked = settings.notifications.requireInteraction;
_preferences.querySelector("#notification-volume").value = settings.notifications.volume.toString();
@@ -1202,6 +1203,7 @@ async function setupPreferences(requireCleanup: boolean = false) {
settings.notifications.tts = _preferences.querySelector("#notification-tts").checked;
settings.notifications.ttsVoice = _preferences.querySelector("#tts-voice").value;
+ settings.notifications.ttsRate = parseFloat(_preferences.querySelector("#notification-ttsRate").value);
settings.notifications.link = _preferences.querySelector("#notification-link").checked;
settings.notifications.requireInteraction = _preferences.querySelector("#notification-requireInteraction").checked;
settings.notifications.volume = parseInt(_preferences.querySelector("#notification-volume").value);
diff --git a/extension/utils/common/data/default-database.ts b/extension/utils/common/data/default-database.ts
index 35796414b..08c5931a3 100644
--- a/extension/utils/common/data/default-database.ts
+++ b/extension/utils/common/data/default-database.ts
@@ -71,6 +71,7 @@ export const DEFAULT_STORAGE = {
soundCustom: new DefaultSetting("string", ""),
tts: new DefaultSetting("boolean", false),
ttsVoice: new DefaultSetting("string", "default"),
+ ttsRate: new DefaultSetting("number", 1),
link: new DefaultSetting("boolean", true),
volume: new DefaultSetting("number", 100),
requireInteraction: new DefaultSetting("boolean", false),
diff --git a/public/changelog.json b/public/changelog.json
index 97d9a63c0..3b637428a 100644
--- a/public/changelog.json
+++ b/public/changelog.json
@@ -8,7 +8,8 @@
{ "message": "'FF Scouter' score filter for ranked wars.", "contributor": "DeKleineKobini" },
{ "message": "Labels for stakeouts.", "contributor": "DeKleineKobini" },
{ "message": "Added bazaarOpen filter on abroad people page", "contributor": "mystify-321" },
- { "message": "More special filters to the 'Userlist Filter': has bounties and bazaar open", "contributor": "DeKleineKobini" }
+ { "message": "More special filters to the 'Userlist Filter': has bounties and bazaar open", "contributor": "DeKleineKobini" },
+ { "message": "Modify TTS speaking rate for notifications.", "contributor": "DeKleineKobini" }
],
"fixes": [
{ "message": "Filtering on profit in the 'Stocks Filter' gave errors for stocks you don't own.", "contributor": "DeKleineKobini" },