mirror of
https://github.com/arc53/DocsGPT.git
synced 2025-11-29 08:33:20 +00:00
use /api/tts endpoint for TTS feature
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState, useRef } from 'react';
|
||||||
import Speaker from '../assets/speaker.svg?react';
|
import Speaker from '../assets/speaker.svg?react';
|
||||||
import Stopspeech from '../assets/stopspeech.svg?react';
|
import Stopspeech from '../assets/stopspeech.svg?react';
|
||||||
import EasySpeech from 'easy-speech';
|
const apiHost = import.meta.env.VITE_API_HOST || 'https://docsapi.arc53.com';
|
||||||
|
|
||||||
export default function SpeakButton({
|
export default function SpeakButton({
|
||||||
text,
|
text,
|
||||||
@@ -14,28 +14,46 @@ export default function SpeakButton({
|
|||||||
}) {
|
}) {
|
||||||
const [isSpeaking, setIsSpeaking] = useState(false);
|
const [isSpeaking, setIsSpeaking] = useState(false);
|
||||||
const [isSpeakHovered, setIsSpeakHovered] = useState(false);
|
const [isSpeakHovered, setIsSpeakHovered] = useState(false);
|
||||||
|
const audioRef = useRef<HTMLAudioElement | null>(null); // Reference to the audio object
|
||||||
|
|
||||||
const handleSpeakClick = async (text: string) => {
|
const handleSpeakClick = async () => {
|
||||||
if (isSpeaking) {
|
if (isSpeaking) {
|
||||||
EasySpeech.cancel();
|
// Stop audio if currently playing and reset the state
|
||||||
|
audioRef.current?.pause();
|
||||||
|
audioRef.current = null;
|
||||||
setIsSpeaking(false);
|
setIsSpeaking(false);
|
||||||
return;
|
return;
|
||||||
} // Stop ongoing speech if already speaking
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await EasySpeech.init(); // Initialize EasySpeech
|
|
||||||
setIsSpeaking(true);
|
setIsSpeaking(true);
|
||||||
|
|
||||||
EasySpeech.speak({
|
// Make a POST request to the /api/tts endpoint
|
||||||
text,
|
const response = await fetch(apiHost + '/api/tts', {
|
||||||
onend: () => setIsSpeaking(false), // Reset when speech ends
|
method: 'POST',
|
||||||
onerror: () => {
|
headers: { 'Content-Type': 'application/json' },
|
||||||
console.error('Speech synthesis failed.');
|
body: JSON.stringify({ text }),
|
||||||
setIsSpeaking(false);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.success && data.audio_base64) {
|
||||||
|
const audio = new Audio(`data:audio/mp3;base64,${data.audio_base64}`);
|
||||||
|
audioRef.current = audio; // Store the audio object in ref for later control
|
||||||
|
audio.play();
|
||||||
|
|
||||||
|
// Reset state when audio ends
|
||||||
|
audio.onended = () => {
|
||||||
|
setIsSpeaking(false);
|
||||||
|
audioRef.current = null;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
console.error('Failed to retrieve audio.');
|
||||||
|
setIsSpeaking(false);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to initialize speech synthesis', error);
|
console.error('Error fetching audio from TTS endpoint', error);
|
||||||
|
setIsSpeaking(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,14 +68,14 @@ export default function SpeakButton({
|
|||||||
{isSpeaking ? (
|
{isSpeaking ? (
|
||||||
<Stopspeech
|
<Stopspeech
|
||||||
className="cursor-pointer fill-none"
|
className="cursor-pointer fill-none"
|
||||||
onClick={() => handleSpeakClick(text)}
|
onClick={handleSpeakClick}
|
||||||
onMouseEnter={() => setIsSpeakHovered(true)}
|
onMouseEnter={() => setIsSpeakHovered(true)}
|
||||||
onMouseLeave={() => setIsSpeakHovered(false)}
|
onMouseLeave={() => setIsSpeakHovered(false)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Speaker
|
<Speaker
|
||||||
className="cursor-pointer fill-none"
|
className="cursor-pointer fill-none"
|
||||||
onClick={() => handleSpeakClick(text)}
|
onClick={handleSpeakClick}
|
||||||
onMouseEnter={() => setIsSpeakHovered(true)}
|
onMouseEnter={() => setIsSpeakHovered(true)}
|
||||||
onMouseLeave={() => setIsSpeakHovered(false)}
|
onMouseLeave={() => setIsSpeakHovered(false)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user