1

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:

  1. Card Zap Executivo: Resumo compacto de 5 linhas pronto para colar no WhatsApp/Slack da diretoria com decisões e donos.
  2. Minuta Formal em PDF: Documento auditável para arquivo corporativo.
  3. 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!

Carregando publicação patrocinada...