import { serve } from 'https://deno.land/std@0.168.0/http/server.ts' import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' import { processAudioWithWhisper } from './whisper.ts' import { analyzeReading } from './analyzer.ts' const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', } interface AudioRecord { id: string story_id: string student_id: string audio_url: string status: 'pending_analysis' | 'processing' | 'completed' | 'error' analysis: any created_at: string transcription: string | null processed_at: string | null error_message: string | null fluency_score: number | null pronunciation_score: number | null accuracy_score: number | null comprehension_score: number | null words_per_minute: number | null pause_count: number | null error_count: number | null self_corrections: number | null strengths: string[] improvements: string[] suggestions: string | null } serve(async (req) => { if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }) } let data: any = null try { // Log dos headers para debug console.log('Headers:', Object.fromEntries(req.headers.entries())) // Validação inicial do body const body = await req.text() console.log('Raw body:', body) console.log('Body length:', body.length) console.log('Body type:', typeof body) data = JSON.parse(body) // Validação do record if (!data.record || !data.record.id || !data.record.audio_url) { return new Response( JSON.stringify({ error: 'Payload inválido', details: 'record, id e audio_url são obrigatórios', receivedData: data }), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ) } const supabase = createClient( Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '' ) const audioRecord = data.record as AudioRecord console.log('AudioRecord', audioRecord) // 1. Atualiza status para processing await supabase .from('story_recordings') .update({ status: 'processing' }) .eq('id', audioRecord.id) // 2. Processa o áudio com Whisper const transcription = await processAudioWithWhisper(audioRecord.audio_url) // 3. Analisa a leitura const analysis = await analyzeReading(transcription, audioRecord.story_id) console.log('Análise concluída', analysis) // 4. Atualiza o registro com os resultados const updateData = { status: 'completed', transcription, processed_at: new Date().toISOString(), fluency_score: analysis.fluency_score || 0, pronunciation_score: analysis.pronunciation_score || 0, accuracy_score: analysis.accuracy_score || 0, comprehension_score: analysis.comprehension_score || 0, words_per_minute: analysis.words_per_minute || 0, pause_count: analysis.pause_count || 0, error_count: analysis.error_count || 0, self_corrections: analysis.self_corrections || 0, strengths: Array.isArray(analysis.strengths) ? analysis.strengths : [], improvements: Array.isArray(analysis.improvements) ? analysis.improvements : [], suggestions: analysis.suggestions || '', analysis: JSON.stringify(analysis.raw_data) } console.log('Dados para atualização:', updateData) const { error: updateError } = await supabase .from('story_recordings') .update(updateData) .eq('id', audioRecord.id) if (updateError) { console.error('Erro na atualização:', updateError) throw updateError } return new Response( JSON.stringify({ message: 'Áudio processado com sucesso', data: analysis }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 200, } ) } catch (error) { console.error('Erro ao processar áudio:', error) // Só tenta atualizar o registro se tiver o ID if (data?.record?.id) { const supabase = createClient( Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '' ) await supabase .from('story_recordings') .update({ status: 'error', error_message: error.message }) .eq('id', audioRecord.id) } return new Response( JSON.stringify({ error: 'Falha ao processar áudio', details: error.message }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 500, } ) } })