Transcricao de audio
WPP Hub tem pipeline opt-in de transcricao de audio. Voce ativa por app+chip e recebe message.transcribed separado do message.received. Util pra atendimento humano (agente le sem precisar tocar audio) ou logging searchable.
Como funciona
- Mensagem audio chega no chip → hub persiste em
messages+ disparamessage.received(commedia_id) - Se app tem
transcribe_audio_mode='all'ou'whitelist': hub enfileira job de transcricao - Worker baixa audio do MinIO, manda pra Whisper API, persiste resultado em
transcriptions - Hub dispara
message.transcribedso pra app que pediu (nao broadcast)
Setup
1. Provider OpenAI configurado no hub
apps/hub/.env:
TRANSCRIPTION_PROVIDER=openaiOPENAI_API_KEY=sk-proj-...OPENAI_WHISPER_MODEL=whisper-1TRANSCRIPTION_COST_CENTS_PER_MINUTE=0.6(Se voce nao roda o hub, peca pro operador ativar.)
2. Ativar pra sua app no chip especifico
Quando crias o vinculo, escolhe o modo:
POST /v1/app-chip-access{ "app_id": "01HZTQAPP...", "chip_id": "01HZTQCHIP...", "can_send": true, "can_receive": true, "transcribe_audio_mode": "all"}Modos:
| Modo | Comportamento |
|---|---|
'off' (default) | nao transcreve nada pra essa app |
'all' | transcreve TODOS audios recebidos no chip |
'whitelist' | transcreve so se sender/chat estiver em transcribe_audio_jids |
Modo whitelist
{ "transcribe_audio_mode": "whitelist", "transcribe_audio_jids": [ "5511988887777", // telefone puro "+55 (11) 99999-8888", // formato amigavel "5511777776666@s.whatsapp.net", // JID "5516991423401-1445094123@g.us", // grupo "12345678901234@lid" // LID (so exact match — nao bate digito) ]}Hub aceita varios formatos. Match e por digit-extraction. LIDs nao batem com telefone (digitos diferentes); pra LID precisa exact match na string.
Recebendo a transcricao
app.post('/webhook', async (req, res) => { // ... validacao HMAC ... res.sendStatus(200)
const { event, data } = JSON.parse(req.body.toString())
if (event === 'message.received' && data.type === 'audio') { // Audio entrou — UI pode mostrar "transcrevendo..." await db.message.create({ ..., transcriptionStatus: 'pending', }) }
if (event === 'message.transcribed') { if (data.status === 'success') { await db.message.update( { hubMessageId: data.message_id }, { transcriptionStatus: 'success', transcriptionText: data.transcription.text, transcriptionLang: data.transcription.language, transcriptionDuration: data.transcription.duration_seconds, transcriptionCostCents: data.transcription.cost_cents, }, ) } else { await db.message.update( { hubMessageId: data.message_id }, { transcriptionStatus: 'failed', transcriptionError: data.error }, ) } }})Latencia tipica
Audio de 30s → Whisper responde em ~3-5s. Total 5-8s entre audio chegar e message.transcribed disparar.
Custo
Whisper-1: $0.006/min ≈ R$0.03/min (cambio 5).
Audio tipico WhatsApp: 30s → R$0.015 por audio.
10k audios/mes = R$150/mes. Pra volume alto, considerar:
- Modo whitelist pra transcrever so agentes/lojas chave
- Whisper local (Hub backlog — viavel quando volume justifica deploy de GPU)
Leitura admin
Ver transcricoes existentes
GET /v1/admin/messages?type=audio&limit=50Retorna mensagens audio com link pra transcricao (se existe).
Re-transcrever manualmente (admin)
Mensagem ja foi parcialmente transcrita ou Whisper falhou? Force re-run:
POST /v1/admin/messages/:id/transcribeAuthorization: Bearer ADMIN_KEYIdempotente (so cria se nao existe ou se status=‘failed’ anterior).
Cuidados
- Custo de OpenAI — monitora
transcriptions.cost_centsmensal. WPP Hub expoe gaugewpp_transcription_cost_cents_total{provider, model}no Prometheus - Falha em audio corrompido — Whisper retorna erro. Hub salva
status='failed'+error. Sua UI deve degradar com graca (mostrar mensagem audio sem transcricao) - Timing —
message.receivedchega ANTES demessage.transcribed. Sua UI precisa lidar com isso (placeholder “transcrevendo…”) - Multiplas apps — se 2 apps tem
transcribe_audio_mode='all'no mesmo chip, hub dedupa Whisper (1 chamada API) mas grava 1 row por app emtranscriptions+ dispara webhook pra cada app. Cobranca por app