← Voltar

Assistente de Voz Offline com ESP32 e Reconhecimento de Comandos

Status: Em andamento | Categoria: Embedded & IoT

O Problema

Necessidade de dispositivo que:

Soluções cloud (Alexa, Google) exigem:

A Solução

Implementei assistente de voz offline com:

Reconhecimento em tempo real

~200ms latency

10 comandos customizados

"ligar luz", "desligar ventilador", etc.

Wake word detection

Ativa escuta somente após "Alexa" (ou palavra customizada)

Modelos de ML comprimidos

Rodam em RAM limitada do ESP32

Feedback visual/sonoro

LED + buzzer confirmam comando reconhecido

100% standalone

Funciona sem internet

Stack Tecnológico

Hardware

ESP32 + Microfone digital (I2S)

Audio ADC

16-bit, 16kHz, Mono

Machine Learning

Espressif ESP-SR (Speech Recognition library)

Modelos

MultiNet (10 comandos) + WakeNet (wake word)

Quantização

Q8 (8-bit) para compactação

Framework

ESP-IDF com Audio Front-End (AFE)

Storage

Modelos armazenados em SPIFFS (~2MB)

Processamento

Noise cancellation, MFCC, Neural network (~100KB)

Arquitetura de Reconhecimento

Microfone (I2S, 16kHz) ↓ Audio Buffer (512 samples) ↓ AFE Preprocessing - Noise suppression - Echo cancellation - Normalization ↓ Feature Extraction (MFCC) ↓ WakeNet Detection └─→ Se detectou wake word: Ativa listening mode Acende LED Inicia timeout (5 seg) ↓ MultiNet Command Recognition - 10 redes neurais especializadas - Cada uma prediz probabilidade para 1 comando - Confidence threshold: 0.7 ↓ Command Processing - "ligar luz" → GPIO22 = HIGH - "ventilador" → UART envio controle - Feedback (buzzer + LED pattern) ↓ Logging + Telemetria

Principais Funcionalidades

✓ Wake word detection: Reconhece "Alexa" antes de processar comandos
✓ 10 comandos customizáveis: Adaptáveis conforme contexto (casa, fábrica, etc)
✓ Feedback multi-modal: LED RGB + buzzer + UART output
✓ Noise suppression: Reduz ruído ambiente para melhor acurácia
✓ Continuous audio streaming: Monitoramento constante sem gaps
✓ Energy efficient: Processamento otimizado, <100mW avg
✓ Listening mode: LED aceso durante janela de 5 segundos
✓ Confidence scoring: Exibe confidence (0-100%) para debugging
✓ Offline 100%: Zero cloud calls, Zero API costs
✓ Privacidade: Audio nunca deixa dispositivo

Desafios Técnicos Resolvidos

1. Acurácia de Reconhecimento em Ambiente Ruidoso

Desafio: Modelo treinado em ambiente silencioso falhava em ambientes reais (ventilador ligado, barulho de rua). Acurácia caía de 95% para 40%.

Solução Implementada:

  • Implementei Audio Front-End (AFE) do Espressif:
    • Noise suppression (remove ruído de fundo até -20dB)
    • Echo cancellation (se houver speaker)
    • Automatic gain control (normaliza volume)
  • Retreinei modelo com dados ruidosos (data augmentation)
  • Aumentei confidence threshold de 0.5 para 0.7

Resultado: Acurácia em ambiente ruidoso: 88% (aceitável). Trade-off: alguns falsos negativos, mas zero falsos positivos prejudiciais.

2. Latência de Reconhecimento

Desafio: Tempo de "Alexa... [espera processamento]... comando executado" era 800ms. Esperado: <200ms.

Solução Implementada:

  • Profiling revelou bottleneck: Feature extraction levava 600ms
  • Otimizações aplicadas:
    • Usar MFCC pré-computado vs computar on-the-fly
    • Reduzir número de frames de 512 para 256
    • Usar operações SIMD (Single Instruction Multiple Data) do ESP32
  • Passou a processar em paralelo: capturar audio novo enquanto calcula features antigas

Resultado: Latência reduzida para 150ms (quase imperceptível). E2E: "Alexa" → comando executado em 200ms.

3. Gerenciamento de Memória com Modelos de ML

Desafio: Modelo neural completo (não quantizado) ocuparia 5MB. ESP32 tem apenas 520KB SRAM. Modelo não cabe.

Solução Implementada:

  • Quantização Q8: Reduz modelo de 1.2MB para 300KB (sem perder acurácia significativamente)
  • Armazenamento em SPIFFS (SPI Flash), carregado sob demanda em chunks
  • Caching inteligente: Apenas camadas ativas em RAM
  • Compilação com -Os (optimize for size)

Resultado: Modelo completo ocupa 300KB RAM. Deixa 200KB livre para buffers de audio e stack.

4. Wake Word vs Comando: Discriminação

Desafio: Se usuário diz "Alexa, liga a TV", o modelo confundia "Alexa" com "TV" às vezes. Acurácia: 78%.

Solução Implementada:

  • Two-stage pipeline:
    • Stage 1: Apenas WakeNet ativo (escuta por "Alexa")
    • Se detecta: Acende LED, inicia timeout de 5 segundos
    • Stage 2: Ativa MultiNet para reconhecer comandos (10 redes em paralelo)
    • Depois de 5s sem comando: volta para Stage 1
  • Treinei separadamente WakeNet com exemplos de "Alexa" apenas

Resultado: Acurácia 96% agora. Wake word detection praticamente perfeito. Redução de false activations de 8% para <1%.

Impacto e Resultados

100% Offline

Zero latência de rede, zero custos de API

88-96%

Acurácia (depende do comando e ambiente)

<100mW

Consumo médio (poderia rodar em bateria)

200ms

Latência end-to-end

📊 Assistente de voz funcional 100% offline: Zero latência de rede, zero custos de API
📊 Privacidade total: Audio nunca deixa o dispositivo (apenas comando binário)
📊 Acurácia 88-96%: Depende do comando e ambiente
📊 Energy efficient: <100mW médio (poderia rodar em bateria)
📊 10 comandos customizáveis: Rápido adaptar para novos contextos
📊 Expertise consolidada: Machine Learning no edge, Espressif ESP-SR, quantização de modelos, otimização de latência