import { useState, useEffect } from "react"; import { ChatHeader } from "@/components/ChatHeader"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Upload, Mic, Play, Download, Trash2, FileAudio, Copy } from "lucide-react"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { useToast } from "@/hooks/use-toast"; const SUPPORTED_FORMATS = ['flac', 'm4a', 'mp3', 'mp4', 'mpeg', 'mpga', 'oga', 'ogg', 'wav', 'webm']; const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25 MB interface TranscriptionResult { id: string; fileName: string; text: string; timestamp: Date; } interface GeneratedAudio { id: string; text: string; voice: string; voiceLabel: string; audioUrl: string; timestamp: Date; } const VOICE_OPTIONS = { alloy: { label: "Alloy", gender: "Masculina", style: "Neutra, equilibrada, tom corporativo", description: "Boa para tutoriais e comunicações institucionais." }, echo: { label: "Echo", gender: "Masculina", style: "Forte e profissional, mais grave", description: "Ideal para voz de autoridade ou locução firme." }, fable: { label: "Fable", gender: "Feminina", style: "Narrativa, calorosa e envolvente", description: "Ótima para storytelling e áudios empáticos." }, onyx: { label: "Onyx", gender: "Masculina", style: "Grave, autoritária, impactante", description: "Excelente para trailers, mensagens sérias ou institucionais." }, nova: { label: "Nova", gender: "Feminina", style: "Brilhante, animada, energética", description: "Boa para vídeos curtos, marketing ou conteúdos leves." }, shimmer: { label: "Shimmer", gender: "Feminina", style: "Suave, otimista, clara", description: "Boa para mensagens acolhedoras, explicações e IA conversacional." } }; export const AudioView = () => { const [textToSpeech, setTextToSpeech] = useState(""); const [isProcessing, setIsProcessing] = useState(false); const [isTranscribing, setIsTranscribing] = useState(false); const [transcriptionResult, setTranscriptionResult] = useState(null); const [selectedFile, setSelectedFile] = useState(null); const [selectedVoice, setSelectedVoice] = useState("alloy"); const [generatedAudio, setGeneratedAudio] = useState(null); const [transcriptionHistory, setTranscriptionHistory] = useState([]); const [audioHistory, setAudioHistory] = useState([]); const { toast } = useToast(); // Load history from localStorage useEffect(() => { const savedTranscriptions = localStorage.getItem('transcriptionHistory'); const savedAudios = localStorage.getItem('audioHistory'); if (savedTranscriptions) { setTranscriptionHistory(JSON.parse(savedTranscriptions)); } if (savedAudios) { setAudioHistory(JSON.parse(savedAudios)); } }, []); const handleGenerateAudio = () => { setIsProcessing(true); // Simulate audio generation - replace with actual API call setTimeout(() => { const audio: GeneratedAudio = { id: Date.now().toString(), text: textToSpeech, voice: selectedVoice, voiceLabel: VOICE_OPTIONS[selectedVoice].label, audioUrl: "data:audio/mp3;base64,//sample", // Placeholder timestamp: new Date(), }; setGeneratedAudio(audio); // Add to history const newHistory = [audio, ...audioHistory].slice(0, 10); setAudioHistory(newHistory); localStorage.setItem('audioHistory', JSON.stringify(newHistory)); setIsProcessing(false); toast({ title: "Áudio gerado com sucesso", description: `Voz: ${VOICE_OPTIONS[selectedVoice].label}`, }); }, 2000); }; const handleFileSelect = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; // Validate file size if (file.size > MAX_FILE_SIZE) { toast({ title: "Arquivo muito grande", description: "O arquivo deve ter no máximo 25 MB", variant: "destructive", }); return; } // Validate file format const fileExtension = file.name.split('.').pop()?.toLowerCase(); if (!fileExtension || !SUPPORTED_FORMATS.includes(fileExtension)) { toast({ title: "Formato não suportado", description: `Formatos suportados: ${SUPPORTED_FORMATS.join(', ')}`, variant: "destructive", }); return; } setSelectedFile(file); handleTranscription(file); }; const handleTranscription = async (file: File) => { setIsTranscribing(true); // Simulate transcription - replace with actual API call setTimeout(() => { const result: TranscriptionResult = { id: Date.now().toString(), fileName: file.name, text: "Esta é uma transcrição de exemplo do áudio enviado. O sistema utilizará modelos de IA avançados para converter sua fala em texto com alta precisão. O áudio foi processado com sucesso e convertido para texto.", timestamp: new Date(), }; setTranscriptionResult(result); // Add to history const newHistory = [result, ...transcriptionHistory].slice(0, 10); setTranscriptionHistory(newHistory); localStorage.setItem('transcriptionHistory', JSON.stringify(newHistory)); setIsTranscribing(false); toast({ title: "Transcrição concluída", description: "Seu áudio foi transcrito com sucesso!", }); }, 2000); }; const handleDownloadAudio = (audio: GeneratedAudio) => { // In real implementation, download the actual audio file const a = document.createElement('a'); a.href = audio.audioUrl; a.download = `audio_${audio.voiceLabel}_${new Date(audio.timestamp).getTime()}.mp3`; document.body.appendChild(a); a.click(); document.body.removeChild(a); toast({ title: "Download iniciado", description: "O arquivo de áudio está sendo baixado.", }); }; const handleDeleteAudio = (audioId: string) => { if (generatedAudio?.id === audioId) { setGeneratedAudio(null); } const newHistory = audioHistory.filter(a => a.id !== audioId); setAudioHistory(newHistory); localStorage.setItem('audioHistory', JSON.stringify(newHistory)); toast({ title: "Áudio removido", description: "O áudio foi removido do histórico.", }); }; const handleDeleteTranscription = () => { setTranscriptionResult(null); setSelectedFile(null); }; const handleDeleteTranscriptionFromHistory = (transcriptionId: string) => { if (transcriptionResult?.id === transcriptionId) { setTranscriptionResult(null); } const newHistory = transcriptionHistory.filter(t => t.id !== transcriptionId); setTranscriptionHistory(newHistory); localStorage.setItem('transcriptionHistory', JSON.stringify(newHistory)); toast({ title: "Transcrição removida", description: "A transcrição foi removida do histórico.", }); }; const handleCopyTranscription = () => { if (transcriptionResult) { navigator.clipboard.writeText(transcriptionResult.text); toast({ title: "Texto copiado", description: "A transcrição foi copiada para a área de transferência", }); } }; const handleDownloadTranscription = () => { if (transcriptionResult) { const blob = new Blob([transcriptionResult.text], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `transcricao_${transcriptionResult.fileName}.txt`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } }; return (
Transcrição de Áudio Geração de Voz {/* Transcription Tab */}

Converter Áudio em Texto

Envie um arquivo de áudio para transcrição (máx. 25MB)

Formatos: {SUPPORTED_FORMATS.join(', ')}

`.${f}`).join(',')} onChange={handleFileSelect} /> {isTranscribing && (

Transcrevendo áudio...

)}
{/* Transcription Result */} {transcriptionResult && (

{transcriptionResult.fileName}

Transcrito {new Date(transcriptionResult.timestamp).toLocaleTimeString('pt-BR')}

{transcriptionResult.text}

)} {/* Generation Tab */}

Converter Texto em Voz