Spaces:
Sleeping
Sleeping
| import { useState, useRef } from 'react'; | |
| import { Volume2, Play } from 'lucide-react'; | |
| export default function PocketTTS() { | |
| const [text, setText] = useState('Hello, this is a test of PocketTTS integration.'); | |
| const [audioUrl, setAudioUrl] = useState(''); | |
| const [loading, setLoading] = useState(false); | |
| const audioRef = useRef(null); | |
| const handleSynthesize = async () => { | |
| if (!text.trim()) return; | |
| setLoading(true); | |
| setAudioUrl(''); | |
| try { | |
| const response = await fetch('/api/tts', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ text }), | |
| }); | |
| if (!response.ok) throw new Error('TTS Generation failed'); | |
| const blob = await response.blob(); | |
| const url = URL.createObjectURL(blob); | |
| setAudioUrl(url); | |
| } catch (err) { | |
| console.error(err); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const playAudio = () => { | |
| if (audioRef.current) { | |
| audioRef.current.play(); | |
| } | |
| }; | |
| return ( | |
| <div className="bg-slate-800 rounded-xl p-6 shadow-xl border border-slate-700"> | |
| <div className="flex items-center gap-2 mb-4"> | |
| <Volume2 className="w-5 h-5 text-blue-500" /> | |
| <h2 className="text-lg font-semibold text-white">Pocket TTS</h2> | |
| </div> | |
| <div className="space-y-4"> | |
| <div> | |
| <label className="block text-sm font-medium text-slate-400 mb-1"> | |
| Text to Speech | |
| </label> | |
| <textarea | |
| value={text} | |
| onChange={(e) => setText(e.target.value)} | |
| className="w-full bg-slate-900 border border-slate-600 rounded-lg p-3 text-white placeholder-slate-500 focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-all resize-none h-24" | |
| /> | |
| </div> | |
| <div className="flex gap-2"> | |
| <button | |
| onClick={handleSynthesize} | |
| disabled={loading} | |
| className="flex-1 bg-blue-600 hover:bg-blue-500 text-white font-medium py-2 rounded-lg transition-colors disabled:opacity-50" | |
| > | |
| {loading ? 'Synthesizing...' : 'Generate Audio'} | |
| </button> | |
| {audioUrl && ( | |
| <button | |
| onClick={playAudio} | |
| className="bg-slate-700 hover:bg-slate-600 text-white p-2 rounded-lg transition-colors" | |
| title="Play Audio" | |
| > | |
| <Play className="w-5 h-5 fill-current" /> | |
| </button> | |
| )} | |
| </div> | |
| {audioUrl && ( | |
| <audio | |
| ref={audioRef} | |
| src={audioUrl} | |
| controls | |
| className="w-full mt-2 h-8" | |
| /> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } |