mirror of
https://github.com/FranP-code/ChatGPT.git
synced 2025-10-13 00:13:25 +00:00
feat: tts (##534)
This commit is contained in:
42
src-tauri/src/scripts/chat.js
vendored
42
src-tauri/src/scripts/chat.js
vendored
@@ -12,10 +12,14 @@ async function init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function chatBtns() {
|
function chatBtns() {
|
||||||
Array.from(document.querySelectorAll("main >div>div>div>div>div"))
|
const synth = window.speechSynthesis;
|
||||||
.forEach(i => {
|
let currentUtterance = null;
|
||||||
|
let currentIndex = -1;
|
||||||
|
const list = Array.from(document.querySelectorAll("main >div>div>div>div>div"));
|
||||||
|
list.forEach((i, idx) => {
|
||||||
if (i.querySelector('.chat-item-copy')) return;
|
if (i.querySelector('.chat-item-copy')) return;
|
||||||
if (!i.querySelector('button.rounded-md')) return;
|
if (!i.querySelector('button.rounded-md')) return;
|
||||||
|
if (!i.querySelector('.self-end')) return;
|
||||||
const cpbtn = i.querySelector('button.rounded-md').cloneNode(true);
|
const cpbtn = i.querySelector('button.rounded-md').cloneNode(true);
|
||||||
cpbtn.classList.add('chat-item-copy');
|
cpbtn.classList.add('chat-item-copy');
|
||||||
cpbtn.title = 'Copy to clipboard';
|
cpbtn.title = 'Copy to clipboard';
|
||||||
@@ -30,27 +34,39 @@ function chatBtns() {
|
|||||||
saybtn.title = 'Say';
|
saybtn.title = 'Say';
|
||||||
saybtn.innerHTML = setIcon('voice');
|
saybtn.innerHTML = setIcon('voice');
|
||||||
i.querySelector('.self-end').appendChild(saybtn);
|
i.querySelector('.self-end').appendChild(saybtn);
|
||||||
let amISpeaking = null;
|
|
||||||
const synth = window.speechSynthesis;
|
|
||||||
saybtn.onclick = () => {
|
saybtn.onclick = () => {
|
||||||
|
if (currentUtterance && currentIndex !== -1) {
|
||||||
|
synth.cancel();
|
||||||
|
if (idx === currentIndex) {
|
||||||
|
saybtn.innerHTML = setIcon('voice');
|
||||||
|
currentUtterance = null;
|
||||||
|
currentIndex = -1;
|
||||||
|
return;
|
||||||
|
} else if (list[currentIndex].querySelector('.chat-item-voice')) {
|
||||||
|
list[currentIndex].querySelector('.chat-item-voice').innerHTML = setIcon('voice');
|
||||||
|
list[idx].querySelector('.chat-item-voice').innerHTML = setIcon('speaking');
|
||||||
|
}
|
||||||
|
}
|
||||||
const txt = i?.innerText?.trim() || '';
|
const txt = i?.innerText?.trim() || '';
|
||||||
const lang = 'en-US';
|
const lang = 'en-US';
|
||||||
if (!txt) return;
|
if (!txt) return;
|
||||||
if (amISpeaking) {
|
|
||||||
amISpeaking = null;
|
|
||||||
synth.cancel();
|
|
||||||
saybtn.innerHTML = setIcon('voice');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const utterance = new SpeechSynthesisUtterance(txt);
|
const utterance = new SpeechSynthesisUtterance(txt);
|
||||||
utterance.lang = lang;
|
|
||||||
utterance.voice = speechSynthesis.getVoices().find(voice => voice.lang === lang);
|
utterance.voice = speechSynthesis.getVoices().find(voice => voice.lang === lang);
|
||||||
|
currentIndex = idx;
|
||||||
|
utterance.lang = lang;
|
||||||
|
utterance.rate = 0.7;
|
||||||
|
utterance.pitch = 1.1;
|
||||||
|
utterance.volume = 1;
|
||||||
synth.speak(utterance);
|
synth.speak(utterance);
|
||||||
amISpeaking = synth.speaking;
|
amISpeaking = synth.speaking;
|
||||||
saybtn.innerHTML = setIcon('speaking');
|
saybtn.innerHTML = setIcon('speaking');
|
||||||
utterance.addEventListener('end', () => {
|
currentUtterance = utterance;
|
||||||
|
currentIndex = idx;
|
||||||
|
utterance.onend = () => {
|
||||||
saybtn.innerHTML = setIcon('voice');
|
saybtn.innerHTML = setIcon('voice');
|
||||||
});
|
currentUtterance = null;
|
||||||
|
currentIndex = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user