Files
ko-grammar/docs/.vitepress/theme/components/TTS.vue
T
2026-07-19 21:56:58 +07:00

90 lines
1.8 KiB
Vue

<template>
<span>
<span ref="main" :class="class" :lang="lang">
<slot />
</span>
<audio
style="display: none"
ref="audio"
@error="playAudioTTSPlugin()"
></audio>
<span>
<button type="button" @click="playAudio()" :class="$style.speak">
🗣️
</button>
</span>
</span>
</template>
<script setup lang="ts">
import { useTemplateRef } from "vue";
import { speak, getVoices } from "tauri-plugin-tts-api";
defineExpose({
playAudio,
});
const { lang = "ko-KR" } = defineProps<{
class?: string;
lang?: string;
}>();
const mainEl = useTemplateRef("main");
const audioEl = useTemplateRef("audio");
function getMainText() {
if (!mainEl.value) return "";
return mainEl.value.innerText
.replace(/[*]/gu, " ")
.replace(/[\p{Ps}\p{Pe}]/gu, "");
}
async function playAudio() {
if (!mainEl.value) return;
if (navigator.platform === "Win32" || !(await playAudioTTSPlugin())) {
if (!audioEl.value) return;
const url = new URL("http://localhost:5500/api/tts");
url.searchParams.set("voice", "glow-speak:ko_kss");
url.searchParams.set("text", getMainText());
audioEl.value.src = url.href;
audioEl.value.currentTime = 0;
audioEl.value.play();
}
}
async function playAudioTTSPlugin(): Promise<boolean> {
if (!mainEl.value) return false;
const voices = await getVoices(lang);
if (!voices.length) return false;
document.querySelectorAll("audio").forEach((el) => {
el.pause();
});
const v = voices[Math.floor(Math.random() * voices.length)];
console.log(JSON.stringify(v));
await speak({
text: getMainText(),
language: null,
rate: null,
volume: null,
pitch: null,
queueMode: null,
voiceId: v.id,
});
return true;
}
</script>
<style module>
.speak {
margin-inline-start: 0.2em;
}
</style>