"use client"; import { useRef, useState, useEffect } from "react"; import { Button } from "./ui/button"; import { Play } from "lucide-react"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "./ui/accordion"; import { Label } from "./ui/label"; export default function KokoroReader({ pages }: { pages: any[] }) { // Create a reference to the worker object. const worker = useRef(null); const [inputText, setInputText] = useState( "Life is like a box of chocolates. You never know what you're gonna get." ); const [selectedSpeaker, setSelectedSpeaker] = useState("af_heart"); const [voices, setVoices] = useState([]); const [status, setStatus] = useState<"ready" | "running" | null>(null); const [error, setError] = useState(null); const [loadingMessage, setLoadingMessage] = useState("Loading..."); const [results, setResults] = useState<{ text: string; src: string }[]>([]); // We use the `useEffect` hook to setup the worker as soon as the `App` component is mounted. useEffect(() => { // Create the worker if it does not yet exist. console.log("Initializing worker..."); worker.current ??= new Worker("/workers/kokoro-worker.js", { type: "module", }); console.log("Worker initialized"); // Create a callback function for messages from the worker thread. const onMessageReceived = (e: any) => { switch (e.data.status) { case "device": setLoadingMessage(`Loading model (device="${e.data.device}")`); break; case "ready": setStatus("ready"); setVoices(e.data.voices); break; case "error": setError(e.data.data); break; case "complete": const { audio, text } = e.data; // Generation complete: re-enable the "Generate" button setResults((prev) => [{ text, src: audio }, ...prev]); setStatus("ready"); break; } }; console.log("onmessagereceived"); const onErrorReceived = (e: any) => { console.error("Worker error:", e); setError(e.message); }; console.log("Attaching event listeners to worker"); // Attach the callback function as an event listener. worker.current.addEventListener("message", onMessageReceived); worker.current.addEventListener("error", onErrorReceived); console.log(worker.current); // Define a cleanup function for when the component is unmounted. return () => { worker.current!.removeEventListener("message", onMessageReceived); worker.current!.removeEventListener("error", onErrorReceived); }; }, []); const handleSubmit = (e: any) => { e.preventDefault(); setStatus("running"); worker.current!.postMessage({ type: "generate", text: inputText.trim(), voice: selectedSpeaker, }); }; return (
Settings
{/*