Como construímos um pipeline de transcrição e atas de reunião (Meet, Teams e Zoom) em < 45 MB de RAM com Fastify e SQLite WAL
Rodar múltiplos micro-SaaS numa única VPS de 2 GB de RAM exige abrir mão de abstrações pesadas. No SecretárioExecutivo, nosso objetivo foi resolver um problema clássico de agências e times de engenharia: transformar áudio e reuniões em atas acionáveis, sem pagar ferramentas em dólar (Fireflies/Tactiq a US$ 20+/mês) e sem explodir o servidor.
O container em produção (secretario-service) opera atualmente em ~30,17 MiB (com limite estrito de 45 MiB no Docker Compose).
Aqui estão as decisões técnicas e lições que aprendemos construindo esse pipeline:
1. Suporte Multiplataforma: Google Meet, Microsoft Teams e Zoom
A maior fricção em ferramentas de ata corporativa é forçar o cliente a trocar de plataforma de chamada. O pipeline do SecretárioExecutivo foi desenhado de forma desacoplada:
- Google Meet: Captura e processamento diarizado (separando oradores) direto do stream de áudio.
- Microsoft Teams: Ingestão de áudios de gravação ou transcrição nativa da organização via API/Webhook.
- Zoom: Processamento das gravações na nuvem com identificação de pautas e deliberações.
Seja qual for a plataforma onde a call aconteceu, o payload que entra no motor é normalizado para um formato canônico único de diarização (speaker, timestamp, text).
2. Fastify + SQLite em modo WAL (zero ORM, zero Redis)
Em vez de subir Postgres + Redis + Prisma (que sozinhos consumiriam ~300 MB de RAM em repouso), usamos SQLite embarcado com:
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
Para o perfil de workload de atas e reuniões (leitura concorrente no painel web e escritas sequenciais de transcrição e sessões), o modo WAL elimina completamente locks de leitura e mantém o consumo de memória praticamente nulo (< 5 MB de cache do SQLite).
3. Fast-Break de LLM com Fallback Determinístico (Promise.race)
APIs de LLM sofrem com picos ocasionais de latência. Se uma reunião de 1h demorar 40 segundos para responder, a conexão HTTP pode cair e o event-loop fica segurando buffers.
Implementamos um utilitário simples de circuit-break / timeout curto na chamada de IA:
function withTimeout(promise, ms = 4500) {
let timer;
const timeoutPromise = new Promise((_, reject) => {
timer = setTimeout(() => reject(new Error('AI_TIMEOUT')), ms);
});
return Promise.race([promise, timeoutPromise]).finally(() => clearTimeout(timer));
}
Se a chamada estourar o orçamento de tempo ou falhar, o motor cai imediatamente no nosso parser determinístico, que extrai datas, horários, deliberações e donos de ação via regex e heurísticas estruturais — garantindo 100% de disponibilidade da ata mesmo em instabilidade de IA.
4. Output Orientado à Execução (Card Zap, Minuta PDF e Matriz RACI)
Ata em texto corrido ninguém lê. Estruturamos a saída em 3 entregáveis práticos em 1 clique:
- Card Zap Executivo: Resumo compacto de 5 linhas pronto para colar no WhatsApp/Slack da diretoria com decisões e donos.
- Minuta Formal em PDF: Documento auditável para arquivo corporativo.
- Matriz RACI e Backlog: Mapeamento de Responsável, Aprovador, Consultado e Informado com despacho direto para cards no Jira e Trello.
Trade-offs reais
- Prós: Deploy em 2 segundos, custo de infraestrutura quase zero (~R$ 30/mês para toda a frota de 10 micro-SaaS) e estabilidade de consumo de memória.
- Contras: Arquivos brutos de áudio exigem tratamento estrito de stream/chunks para não lotar a RAM efêmera antes da diarização.
Para quem quiser ver a arquitetura em funcionamento ou testar o fluxo com reuniões reais do Meet, Teams ou Zoom: https://secretario.stacktools.com.br?utm_source=tabnews&utm_medium=community_post&utm_campaign=secretario&utm_content=tabnews_draft_001
Feedback de quem lida com otimização de Node.js e orquestração de IA em VPS modesta é super bem-vindo!