feat: add option to remove reasoning tag from TTS output

This commit is contained in:
n4ze3m 2025-02-09 13:00:04 +05:30
parent 023d3c2fb2
commit 084b859e3e
21 changed files with 106 additions and 10 deletions

View File

@ -119,6 +119,9 @@
},
"ssmlEnabled": {
"label": "تمكين SSML (لغة ترميز توليف الكلام)"
},
"removeReasoningTagTTS": {
"label": "إزالة علامة التفكير من تحويل النص إلى كلام"
}
}
},

View File

@ -113,6 +113,9 @@
},
"ssmlEnabled": {
"label": "Aktiver SSML (Speech Synthesis Markup Language)"
},
"removeReasoningTagTTS": {
"label": "Fjern Ræsonnement Tag fra TTS"
}
}
},

View File

@ -116,6 +116,9 @@
},
"ssmlEnabled": {
"label": "SSML (Speech Synthesis Markup Language) aktivieren"
},
"removeReasoningTagTTS": {
"label": "Reasoning-Tag aus Text-zu-Sprache entfernen"
}
}
},

View File

@ -122,6 +122,9 @@
},
"responseSplitting": {
"label": "Response Splitting"
},
"removeReasoningTagTTS": {
"label": "Remove Reasoning Tag from TTS"
}
}
},

View File

@ -116,8 +116,10 @@
},
"ssmlEnabled": {
"label": "Habilitar SSML (Speech Synthesis Markup Language)"
}
}
},
"removeReasoningTagTTS": {
"label": "Eliminar Etiqueta de Razonamiento del TTS"
} }
},
"manageModels": {
"title": "Administar de Modelos",

View File

@ -113,6 +113,9 @@
},
"ssmlEnabled": {
"label": "فعال کردن SSML (Speech Synthesis Markup Language)"
},
"removeReasoningTagTTS": {
"label": "حذف برچسب استدلال از تبدیل متن به گفتار"
}
}
},

View File

@ -116,6 +116,9 @@
},
"ssmlEnabled": {
"label": "Activer SSML (langage de balisage de synthèse vocale)"
},
"removeReasoningTagTTS": {
"label": "Supprimer la balise de raisonnement de la synthèse vocale"
}
}
},

View File

@ -116,6 +116,9 @@
},
"ssmlEnabled": {
"label": "Abilita SSML (Speech Synthesis Markup Language)"
},
"removeReasoningTagTTS": {
"label": "Rimuovi Tag di Ragionamento dal TTS"
}
}
},

View File

@ -119,6 +119,9 @@
},
"ssmlEnabled": {
"label": "SSML (Speech Synthesis Markup Language) を有効にする"
},
"removeReasoningTagTTS": {
"label": "テキスト読み上げから推論タグを削除"
}
}
},

View File

@ -119,6 +119,9 @@
},
"ssmlEnabled": {
"label": "SSML (Speech Synthesis Markup Language) 활성화"
},
"removeReasoningTagTTS": {
"label": "TTS에서 추론 태그 제거"
}
}
},

View File

@ -119,6 +119,9 @@
},
"ssmlEnabled": {
"label": "SSML (സ്പീച്ച് സിന്തസിസ് മാർക്കപ്പ് ലാംഗ്വേജ്) പ്രവർത്തനക്ഷമമാക്കുക"
},
"removeReasoningTagTTS": {
"label": "ടിടിഎസിൽ നിന്ന് റീസണിംഗ് ടാഗ് നീക്കം ചെയ്യുക"
}
}
},

View File

@ -116,6 +116,9 @@
},
"ssmlEnabled": {
"label": "Aktiver SSML (Speech Synthesis Markup Language)"
},
"removeReasoningTagTTS": {
"label": "Fjern Resonneringsmerke fra TTS"
}
}
},

View File

@ -116,6 +116,9 @@
},
"ssmlEnabled": {
"label": "Ativar SSML (Linguagem de Marcação de Síntese de Fala)"
},
"removeReasoningTagTTS": {
"label": "Remover Tag de Raciocínio do TTS"
}
}
},

View File

@ -117,6 +117,9 @@
},
"ssmlEnabled": {
"label": "Включить SSML (язык разметки синтеза речи)"
},
"removeReasoningTagTTS": {
"label": "Удалить тег рассуждения из TTS"
}
}
},

View File

@ -116,6 +116,9 @@
},
"ssmlEnabled": {
"label": "Aktivera SSML (Speech Synthesis Markup Language)"
},
"removeReasoningTagTTS": {
"label": "Ta bort resonemangstagg från Text till Tal"
}
}
},

View File

@ -116,6 +116,9 @@
},
"ssmlEnabled": {
"label": "Ввімкнути SSML (Мова Розмітки для Синтезу Голосу)"
},
"removeReasoningTagTTS": {
"label": "Видалити тег міркування з TTS"
}
}
},

View File

@ -119,6 +119,9 @@
},
"ssmlEnabled": {
"label": "启用SSML(语音合成标记语言)"
},
"removeReasoningTagTTS": {
"label": "从语音合成中移除推理标签"
}
}
},

View File

@ -18,7 +18,7 @@ import { useTTS } from "@/hooks/useTTS"
import { tagColors } from "@/utils/color"
import { removeModelSuffix } from "@/db/models"
import { GenerationInfo } from "./GenerationInfo"
import { parseReasoning, removeReasoning } from "@/libs/reasoning"
import { parseReasoning, } from "@/libs/reasoning"
import { humanizeMilliseconds } from "@/utils/humanize-milliseconds"
type Props = {
message: string
@ -213,7 +213,7 @@ export const PlaygroundMessage = (props: Props) => {
cancel()
} else {
speak({
utterance: removeReasoning(props.message)
utterance: props.message
})
}
}}

View File

@ -17,6 +17,7 @@ export const TTSModeSettings = ({ hideBorder }: { hideBorder?: boolean }) => {
ttsProvider: "",
voice: "",
ssmlEnabled: false,
removeReasoningTagTTS: true,
elevenLabsApiKey: "",
elevenLabsVoiceId: "",
elevenLabsModel: "",
@ -209,6 +210,20 @@ export const TTSModeSettings = ({ hideBorder }: { hideBorder?: boolean }) => {
</div>
</div>
<div className="flex sm:flex-row flex-col space-y-4 sm:space-y-0 sm:justify-between">
<span className="text-gray-700 dark:text-neutral-50 ">
{t("generalSettings.tts.removeReasoningTagTTS.label")}
</span>
<div>
<Switch
className="mt-4 sm:mt-0"
{...form.getInputProps("removeReasoningTagTTS", {
type: "checkbox"
})}
/>
</div>
</div>
<div className="flex justify-end">
<SaveButton btnType="submit" />
</div>

View File

@ -4,6 +4,7 @@ import {
getElevenLabsApiKey,
getElevenLabsModel,
getElevenLabsVoiceId,
getRemoveReasoningTagTTS,
getTTSProvider,
getVoice,
isSSMLEnabled
@ -11,6 +12,7 @@ import {
import { markdownToSSML } from "@/utils/markdown-to-ssml"
import { generateSpeech } from "@/services/elevenlabs"
import { splitMessageContent } from "@/utils/tts"
import { removeReasoning } from "@/libs/reasoning"
export interface VoiceOptions {
utterance: string
@ -26,6 +28,11 @@ export const useTTS = () => {
try {
const voice = await getVoice()
const provider = await getTTSProvider()
const isRemoveReasoning = await getRemoveReasoningTagTTS()
if (isRemoveReasoning) {
utterance = removeReasoning(utterance)
}
if (provider === "browser") {
const isSSML = await isSSMLEnabled()
@ -115,7 +122,10 @@ export const useTTS = () => {
return
}
if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
if (
import.meta.env.BROWSER === "chrome" ||
import.meta.env.BROWSER === "edge"
) {
chrome.tts.stop()
} else {
window.speechSynthesis.cancel()

View File

@ -1,6 +1,9 @@
import { Storage } from "@plasmohq/storage"
const storage = new Storage()
const storage2 = new Storage({
area: "local"
})
const DEFAULT_TTS_PROVIDER = "browser"
@ -98,10 +101,22 @@ export const getResponseSplitting = async () => {
return data
}
export const getRemoveReasoningTagTTS = async () => {
const data = await storage2.get("removeReasoningTagTTS")
if (!data || data.length === 0 || data === "") {
return true
}
return data === "true"
}
export const setResponseSplitting = async (responseSplitting: string) => {
await storage.set("ttsResponseSplitting", responseSplitting)
}
export const setRemoveReasoningTagTTS = async (removeReasoningTagTTS: boolean) => {
await storage2.set("removeReasoningTagTTS", removeReasoningTagTTS.toString())
}
export const getTTSSettings = async () => {
const [
ttsEnabled,
@ -112,7 +127,8 @@ export const getTTSSettings = async () => {
elevenLabsApiKey,
elevenLabsVoiceId,
elevenLabsModel,
responseSplitting
responseSplitting,
removeReasoningTagTTS
] = await Promise.all([
isTTSEnabled(),
getTTSProvider(),
@ -122,7 +138,8 @@ export const getTTSSettings = async () => {
getElevenLabsApiKey(),
getElevenLabsVoiceId(),
getElevenLabsModel(),
getResponseSplitting()
getResponseSplitting(),
getRemoveReasoningTagTTS()
])
return {
@ -134,7 +151,8 @@ export const getTTSSettings = async () => {
elevenLabsApiKey,
elevenLabsVoiceId,
elevenLabsModel,
responseSplitting
responseSplitting,
removeReasoningTagTTS
}
}
@ -146,7 +164,8 @@ export const setTTSSettings = async ({
elevenLabsApiKey,
elevenLabsVoiceId,
elevenLabsModel,
responseSplitting
responseSplitting,
removeReasoningTagTTS
}: {
ttsEnabled: boolean
ttsProvider: string
@ -156,6 +175,7 @@ export const setTTSSettings = async ({
elevenLabsVoiceId: string
elevenLabsModel: string
responseSplitting: string
removeReasoningTagTTS: boolean
}) => {
await Promise.all([
setTTSEnabled(ttsEnabled),
@ -165,6 +185,7 @@ export const setTTSSettings = async ({
setElevenLabsApiKey(elevenLabsApiKey),
setElevenLabsVoiceId(elevenLabsVoiceId),
setElevenLabsModel(elevenLabsModel),
setResponseSplitting(responseSplitting)
setResponseSplitting(responseSplitting),
setRemoveReasoningTagTTS(removeReasoningTagTTS)
])
}