// ===== NOVA FUNÇÃO DE TRANSCRIÇÃO COM CLOUDINARY ===== // Função para enviar formulário de transcrição com upload direto ao Cloudinary async function submitTranscriptionFormCloudinary(event) { event.preventDefault(); console.log('🎯 [TRANSCRIPTION-WASABI] Iniciando processo de transcrição com Wasabi'); // Validar campos if (!JaniceApp.elements.transcriptionTitleInput.value.trim()) { alert('O título da transcrição é obrigatório'); return; } if (!JaniceApp.elements.transcriptionFileInput.files.length) { alert('Por favor, selecione um arquivo de áudio ou vídeo'); return; } // Verificar tamanho do arquivo (máximo 2GB para Cloudinary) const file = JaniceApp.elements.transcriptionFileInput.files[0]; const fileSize = file.size / (1024 * 1024); // tamanho em MB if (fileSize > 2048) { alert('O arquivo é muito grande. O tamanho máximo permitido é 2GB.'); return; } console.log('✅ [TRANSCRIPTION-CLOUDINARY] Validações passaram'); console.log('📁 [TRANSCRIPTION-CLOUDINARY] Arquivo:', file.name, `(${fileSize.toFixed(2)} MB)`); let cloudinaryResult = null; try { // Estimar duração do áudio baseada no tamanho do arquivo const estimatedAudioMinutes = Math.max(1, Math.ceil(fileSize / 1)); // ~1MB por minuto // Registrar processo no painel de processos ativos com metadados const client = JaniceApp.state.currentClients.find(c => c._id === JaniceApp.state.currentClientId); const processMetadata = { duracaoAudioMinutos: estimatedAudioMinutes, tamanhoArquivoMB: fileSize }; const processId = JaniceApp.state.activeProcessesManager.registerProcess( 'transcricao', JaniceApp.state.currentClientId, `Transcrição: ${JaniceApp.elements.transcriptionTitleInput.value.trim()}`, null, processMetadata ); console.log('📊 [TRANSCRIPTION-CLOUDINARY] Processo registrado:', processId); // Mostrar tela de carregamento JaniceApp.elements.transcriptionContainer.style.display = 'none'; JaniceApp.elements.welcomeContainer.style.display = 'none'; JaniceApp.elements.errorContainer.style.display = 'none'; JaniceApp.elements.resultContainer.style.display = 'none'; JaniceApp.elements.loadingContainer.style.display = 'block'; // Adicionar classe para modo transcrição JaniceApp.elements.loadingContainer.classList.add('transcription-mode'); // Adaptar tela de carregamento para transcrição com novo fluxo JaniceApp.elements.loadingStatus.textContent = 'Fazendo upload para o servidor...'; document.querySelector('.loading-text').textContent = 'Enviando arquivo para processamento...'; // Adaptar etapas para novo fluxo document.getElementById('step-1').querySelector('.step-text').textContent = 'Fazendo upload para o servidor'; document.getElementById('step-2').querySelector('.step-text').textContent = 'Processando áudio'; document.getElementById('step-3').querySelector('.step-text').textContent = 'Gerando transcrição'; document.getElementById('step-4').querySelector('.step-text').textContent = 'Finalizando'; // Resetar barra de progresso JaniceApp.modules.analysis.resetProgress(); // ETAPA 1: Upload para Cloudinary console.log('📤 [TRANSCRIPTION-CLOUDINARY] Iniciando upload para Cloudinary...'); JaniceApp.modules.analysis.updateStepStatus(1, 'active'); JaniceApp.elements.loadingStatus.textContent = 'Fazendo upload para o servidor...'; // Callback para progresso do upload const uploadProgressCallback = (percentage) => { console.log(`📤 [TRANSCRIPTION-CLOUDINARY] Progresso upload: ${percentage}%`); // Mapear progresso do upload para 0-30% da barra total const mappedProgress = Math.round(percentage * 0.3); JaniceApp.elements.progressFill.style.width = `${mappedProgress}%`; JaniceApp.elements.progressText.textContent = `${mappedProgress}%`; if (percentage < 100) { JaniceApp.elements.loadingStatus.textContent = `Fazendo upload para o servidor... ${percentage}%`; } else { JaniceApp.elements.loadingStatus.textContent = 'Upload concluído! Preparando para transcrição...'; } }; // Usar sempre BunnyCDN para transcrições console.log('📤 [TRANSCRIPTION-BUNNYCDN] Usando BunnyCDN para upload...'); cloudinaryResult = await uploadToBunnyCDN(file, uploadProgressCallback); console.log('✅ [TRANSCRIPTION-BUNNYCDN] Upload para BunnyCDN concluído!'); console.log('🔗 [TRANSCRIPTION-BUNNYCDN] URL:', cloudinaryResult.secure_url); console.log('🆔 [TRANSCRIPTION-BUNNYCDN] Key:', cloudinaryResult.public_id); // Atualizar progresso para 30% JaniceApp.modules.analysis.updateStepStatus(1, 'completed'); JaniceApp.modules.analysis.updateStepStatus(2, 'active'); JaniceApp.elements.progressFill.style.width = '30%'; JaniceApp.elements.progressText.textContent = '30%'; JaniceApp.elements.loadingStatus.textContent = 'Enviando para processamento...'; // ETAPA 2: Enviar URL para backend console.log('🚀 [TRANSCRIPTION-CLOUDINARY] Enviando URL para backend...'); // Ensure the URL has the https:// protocol for Replicate const fullUrl = cloudinaryResult.secure_url.startsWith('http') ? cloudinaryResult.secure_url : `https://${cloudinaryResult.secure_url}`; const requestData = { titulo: JaniceApp.elements.transcriptionTitleInput.value.trim(), idioma: JaniceApp.elements.transcriptionLanguageSelect.value, cloudinaryUrl: fullUrl, cloudinaryPublicId: cloudinaryResult.public_id, nomeArquivoOriginal: file.name, tamanhoArquivo: file.size }; console.log('🔗 [TRANSCRIPTION-CLOUDINARY] URL corrigida para Replicate:', fullUrl); console.log('📋 [TRANSCRIPTION-CLOUDINARY] Dados da requisição:', requestData); const response = await fetch(`/api/transcricoes/upload-cloudinary/${JaniceApp.state.currentClientId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestData) }); if (!response.ok) { // Tentar extrair o erro da resposta let errorMessage = 'Erro ao iniciar transcrição'; try { const errorData = await response.json(); errorMessage = errorData.erro || 'Erro ao iniciar transcrição'; } catch (jsonError) { try { const errorText = await response.text(); if (errorText.includes('Tipo de arquivo não suportado')) { errorMessage = 'Tipo de arquivo não suportado. Por favor, envie apenas arquivos de áudio ou vídeo.'; } else if (errorText.length < 200) { errorMessage = errorText; } } catch (textError) { console.error('❌ [TRANSCRIPTION-CLOUDINARY] Erro ao processar resposta:', textError); } } throw new Error(errorMessage); } // Obter ID da transcrição para acompanhar progresso const data = await response.json(); const transcriptionId = data.transcricaoId; console.log('✅ [TRANSCRIPTION-CLOUDINARY] Transcrição iniciada com ID:', transcriptionId); // Atualizar progresso para 40% JaniceApp.elements.progressFill.style.width = '40%'; JaniceApp.elements.progressText.textContent = '40%'; JaniceApp.elements.loadingStatus.textContent = 'Processamento iniciado...'; // ETAPA 3: Iniciar monitoramento de progresso via SSE de processos console.log('📡 [TRANSCRIPTION-CLOUDINARY] Iniciando monitoramento de progresso via SSE...'); // O progresso será monitorado através do sistema SSE de processos ativos // que já está conectado e funcionando. Não precisamos criar uma nova conexão. // Armazenar informações do arquivo para timeout inteligente if (window.currentProcessInfo) { window.currentProcessInfo.fileSizeMB = fileSize; window.currentProcessInfo.transcriptionId = transcriptionId; } // Salvar informações no localStorage para persistência localStorage.setItem('activeTranscription', JSON.stringify({ id: transcriptionId, startTime: new Date(), clientId: JaniceApp.state.currentClientId, bunnycdnKey: cloudinaryResult.public_id, fileSizeMB: fileSize })); // Iniciar verificação periódica como backup para garantir que a transcrição seja detectada quando concluir setTimeout(() => { JaniceApp.modules.transcriptions.startPeriodicStatusCheck(transcriptionId); }, 10000); // Iniciar após 10 segundos // Atualizar lista de transcrições em segundo plano JaniceApp.modules.transcriptions.loadClientTranscriptions(JaniceApp.state.currentClientId); console.log('🎉 [TRANSCRIPTION-CLOUDINARY] Processo iniciado com sucesso!'); } catch (error) { console.error('❌ [TRANSCRIPTION-CLOUDINARY] Erro no processo:', error); // Se houve upload, tentar limpar do BunnyCDN if (cloudinaryResult && cloudinaryResult.public_id) { console.log('🗑️ [TRANSCRIPTION-BUNNYCDN] Limpando arquivo do BunnyCDN devido ao erro...'); try { await deleteFromBunnyCDN(cloudinaryResult.public_id); } catch (cleanupError) { console.warn('⚠️ [TRANSCRIPTION-BUNNYCDN] Erro na limpeza (não crítico):', cleanupError); } } JaniceApp.modules.analysis.showError(error.message || 'Ocorreu um erro ao iniciar a transcrição.'); } } // Substituir a função original no módulo de transcrições console.log('🔍 [TRANSCRIPTION-CLOUDINARY] Verificando se JaniceApp e módulo de transcrições existem...'); // Aguardar que o JaniceApp esteja disponível function replaceTranscriptionFunction() { if (typeof window.JaniceApp !== 'undefined' && window.JaniceApp.modules && window.JaniceApp.modules.transcriptions && typeof window.JaniceApp.modules.transcriptions.submitTranscriptionForm === 'function') { console.log('✅ [TRANSCRIPTION-CLOUDINARY] Função original encontrada! Substituindo...'); // Backup da função original window.JaniceApp.modules.transcriptions.originalSubmitTranscriptionForm = window.JaniceApp.modules.transcriptions.submitTranscriptionForm; // Substituir pela nova função window.JaniceApp.modules.transcriptions.submitTranscriptionForm = submitTranscriptionFormCloudinary; // Também disponibilizar globalmente para compatibilidade window.submitTranscriptionFormCloudinary = submitTranscriptionFormCloudinary; console.log('✅ [TRANSCRIPTION-CLOUDINARY] Substituição concluída!'); console.log('🔍 [TRANSCRIPTION-CLOUDINARY] Nova função:', window.JaniceApp.modules.transcriptions.submitTranscriptionForm.name); return true; } return false; } // Tentar substituir imediatamente if (!replaceTranscriptionFunction()) { console.log('⏳ [TRANSCRIPTION-CLOUDINARY] JaniceApp ainda não disponível, aguardando...'); // Se não conseguir imediatamente, tentar novamente após um delay setTimeout(() => { if (!replaceTranscriptionFunction()) { console.warn('⚠️ [TRANSCRIPTION-CLOUDINARY] Função original não encontrada após timeout!'); console.log('🔍 [TRANSCRIPTION-CLOUDINARY] Estado do JaniceApp:', { janiceAppExists: typeof window.JaniceApp !== 'undefined', modulesExists: window.JaniceApp?.modules ? 'sim' : 'não', transcriptionsExists: window.JaniceApp?.modules?.transcriptions ? 'sim' : 'não', submitFunctionExists: typeof window.JaniceApp?.modules?.transcriptions?.submitTranscriptionForm === 'function' ? 'sim' : 'não' }); } }, 500); }