Setup detalhado
1. Criar Server-to-Server OAuth app
- https://marketplace.zoom.us > Develop > Build App
- App Type: Server-to-Server OAuth
- App credentials: copie Account ID, Client ID, Client Secret
2. Scopes necessarios
meeting:read:admin— listar meetingsmeeting:write:admin— criar/atualizar/deletar meetingsrecording:read:admin— acessar gravacoesuser:read:admin— info dos hosts
3. Event Subscriptions (webhook)
- App > Feature > Event Subscriptions
- Subscription URL:
https://[tenant].studeia.com/api/webhooks/video/zoom - Authentication: Webhook secret token (copie pra Studeia)
- Events a subscribir:
- Meeting > Meeting Started
- Meeting > Meeting Ended
- Meeting > Participant Joined / Left
- Recording > Recording Completed
- Recording > Recording Transcript Completed
4. Configurar em Studeia
Settings > Video Provider > Zoom > Add:
- Account ID
- Client ID
- Client Secret
- Webhook Secret Token (do passo 3)
- Set as default (opcional — usa Zoom para todas LiveClasses sem override)
Studeia armazena tudo criptografado AES-256-GCM.
Como funciona
Admin/Professor cria LiveClass no Studeia (videoProvider=zoom)
↓
Studeia ZoomAdapter.createMeeting()
→ Server-to-Server OAuth token (cached Redis 55min)
→ POST https://api.zoom.us/v2/users/{userId}/meetings
→ Retorna meetingId + joinUrl + startUrl + password
↓
Studeia salva em LiveClass.providerMeetingId / providerJoinUrl / providerData
↓
Aluno entra via /live-classes/[id] > clique "Entrar"
→ joinMethod=external (nova aba) — Zoom NAO suporta iframe (X-Frame-Options)
→ Abre Zoom app/web
↓
Durante meeting: webhooks notificam Studeia
→ meeting.started → LiveClass.actualStartTime
→ participant.joined → LiveClassAttendance
→ meeting.ended → LiveClass.actualEndTime
↓
Apos meeting termina (~5-30min processamento Zoom):
→ recording.completed webhook
→ Studeia atualiza LiveClass.recordingUrl
→ recording.transcript_completed webhook
→ Studeia cria LiveClassTranscription com VTT parseado
Cron fallback
Webhooks Zoom sao unreliable (delays, subscription expiry, falhas de rede). Studeia roda /api/cron/recording-sync a cada 15min:
- Busca LiveClasses completed > 15min sem recordingUrl
- Para cada, chama
adapter.getRecordings(meetingId)via Zoom API - Se encontrar, atualiza recordingUrl + cria LiveClassTranscription
RAG ingestion da transcripcao
Apos transcription approved pelo professor:
/institution/courses/[id]/transcriptions/[tid]/approve- Texto da transcripcao virua chunks + embeddings + ContentBlock
- Metadata:
{ source: "live_class_transcript", liveClassId, courseId } - Tutor IA cita: "Na aula ao vivo do dia X, a professora explicou que..."
Troubleshooting
"401 Unauthorized" ao criar meeting
Token expirado. Verificar logs:
- Server-to-Server OAuth token cached Redis 55min (renew automatico)
- Se persistir: rotacionar Client Secret no Zoom Marketplace + atualizar em Studeia
Webhook nao chegando
- Verificar webhook URL acessivel publicamente (curl externo)
- Validar HMAC SHA-256 signature (Studeia loga warning se mismatch)
- Zoom retry 3x com backoff — se falhar 3x, webhook event perdido (cron recupera)
Recording sem VTT
VTT so e gerado se Zoom Cloud Recording esta habilitado (nao Local Recording). Verificar User > Settings > Recording > Cloud recording on.
Custos
- Studeia: zero custo adicional (incluido em qualquer plano)
- Zoom: cobranca direto do Zoom (licenca por host). Studeia nao revende Zoom.