File size: 5,614 Bytes
0b5c6fd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
"use client";
import React from "react";
import ImageUpload from "./ImageUpload";
import DescriptionDisplay from "./DescriptionDisplay";
import AudioPlayback from "./AudioPlayback";
import {Card, CardContent} from "@/components/ui/card";
import {useGenWav, useImageToText, useTextToSpeachLang, useTranslator, useUploadImage} from "@/hooks/api";
import LanguageSelector from "./LanguageSelector";
import {modal} from "@/app/constant";
import Image from "next/image";
export default function VisualSearchAssistant() {
const [imageUrl, setImageUrl] = React.useState<string | null>(null);
const [description, setDescription] = React.useState<string>("");
const [language, setLanguage] = React.useState<string>("Xenova/mms-tts-eng");
const [path, setPath] = React.useState<string | null>(null);
const code = modal.find((lang) => lang.model === language)?.code || "en";
const upload = useUploadImage();
const iToText = useImageToText();
const translator = useTranslator();
const tts = useTextToSpeachLang();
const wav = useGenWav();
const handleImageUpload = async (file: File) => {
const url = URL.createObjectURL(file);
setImageUrl(url);
const formData = new FormData();
formData.append("image", file);
try {
upload.mutate(
{form: formData},
{
onSuccess: (data) => {
iToText.mutate(
{url: data?.key},
{
onSuccess: (data) => {
translator.mutate(
{text: data[0].generated_text, code},
{
onSuccess: (data) => {
console.log("data-desc", data);
setDescription(data[0]?.translation_text);
console.log("lang", language, data);
tts.mutate({text: data[0]?.translation_text, modal: language}, {
onSuccess: (data) => {
wav.mutate({
sampling_rate: data.sampling_rate,
audio: data.audio,
name: crypto.randomUUID()
}, {
onSuccess: (data) => {
setPath(data.audio);
}
})
}
})
},
},
);
},
},
);
},
},
);
} catch (error) {
console.error("Error processing image:", error);
setDescription("Failed to process image. Please try again.");
}
};
console.log("upload data", upload?.data);
const renderStatusMessage = () => {
if (upload.isPending) {
return <p>Please wait while we process your image...</p>;
}
if (iToText.isPending) {
return <p>Processing image and extracting information, please wait...</p>;
}
if (translator.isPending) {
return <p>Wait while we translate your text...</p>;
}
if (tts.isPending) {
return <p>Wait while we process the audio...</p>;
}
if (wav.isPending) {
return <p>Generating audio file, please wait...</p>;
}
return null;
};
return (
<div className="w-full">
<Card
className="bg-white/90 backdrop-blur-sm shadow-xl rounded-xl overflow-hidden transition-all duration-300 hover:shadow-2xl">
<CardContent className="p-6 space-y-6">
<LanguageSelector onLanguageChange={setLanguage} sideEffect={setPath}/>
<ImageUpload sideEffect={setPath} onImageUpload={handleImageUpload}/>
{imageUrl && (
<div className="mt-4 flex justify-center">
<Image
src={imageUrl}
alt="Uploaded image"
width={1000}
height={1000}
className="max-w-full max-h-[50vh] object-contain rounded-lg shadow-md transition-all duration-300 hover:scale-105"
/>
</div>
)}
{renderStatusMessage()}
{description && (
<div className="space-y-4" key={crypto.randomUUID()}>
<DescriptionDisplay description={description}/>
<AudioPlayback path={path!}/>
</div>
)}
</CardContent>
</Card>
</div>
);
}
|