XiaoMusic: Arquitetura Open-Source para Controle Avançado de Alto-Falantes Inteligentes

XiaoMusic é uma solução open-source projetada para desbloquear o potencial completo de alto-falantes inteligentes da linha XiaoAI, permitindo reprodução de áudio local e remota sem dependência de serviços proprietários. Construído com Python e FastAPI, o projeto atua como um intermediário entre o usuário e o dispositivo, substituindo restrições de licenciamento por um ecossistema flexível, extensível e controlado localmente.

Arquiteutra Técnica e Mecanismos-Chave

O sistema opera em três camadas interconectadas:

  • Camada de Comunicação: Utiliza uma implementação personalizada do protocolo MiOT (Mi IoT) para autenticação segura e troca de mensagens com dispositivos Xiaomi. Em vez de depender de bibliotecas oficiais, o projeto emprega requisições HTTP assinadas e gerenciamento de sessão baseado em tokens.
  • Camada de Processamento de Áudio: Integra yt-dlp como motor de extração de mídia, com suporte nativo para conversão automática para formatos compatíveis (ex: MP3 via ffmpeg). A fila de downloads é gerenciada por um executor assíncrono com controle de concorrência.
  • Camada de Interface: Oferece uma API RESTful em JSON (porta 8090 por padrão) e um endpoint WebSocket para atualizações em tempo real de estado de reprodução, além de uma interface web estática construída com Vue.js.

O reconhecimento de comandos de voz não ocorre no dispositivo, mas sim no servidor — onde frases são normalizadas, tokenizadas e mapeadas a ações via dicionário configurável:

{
  "tocar": "play_track",
  "pular": "skip_track",
  "repetir": "toggle_repeat_mode",
  "favoritar": "mark_as_favorite"
}

Implantação Prática com Docker

A forma mais robusta de implantação usa containers isolados. O arquivo docker-compose.yml abaixo define um ambiente seguro e persistente:

version: '3.9'
services:
  audio-hub:
    image: hanxi/xiaomusic:v2.4.1
    restart: always
    ports:
      - "58090:8090"
    volumes:
      - ./data/audio:/srv/music:ro
      - ./data/config:/srv/conf:rw
      - ./data/logs:/srv/logs:rw
    environment:
      - TZ=Asia/Shanghai
      - XIAOMUSIC_LOG_LEVEL=INFO
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8090/api/health"]
      interval: 30s
      timeout: 10s
      retries: 3

Observações importantes:

  • O volume /srv/music deve conter apenas arquivos de áudio válidos (MP3, FLAC, OGG, WAV); subdiretórios são varridos recursivamente até profundidade 8.
  • O diretório /srv/conf deve incluir config.json, com credenciais de conta Xiaomi ou cookies de sessão exportados manualmente.
  • A verificação de saúde garante que o serviço esteja respondendo antes de ser considerado operacional.

Configuração Avançada de Biblioteca e Reprodução

O comportamento de indexação de músicas é ajustável via configuração JSON:

{
  "scan_depth": 8,
  "ignore_patterns": ["*.tmp", ".DS_Store", "__pycache__"],
  "auto_tag_read": true,
  "playlist_max_size": 200,
  "watch_enabled": true,
  "watch_debounce_ms": 3000
}

Para integração com fontes externas, o sistema aceita listas de reprodução em múltiplos formatos:

  • playlist.json: estrutura hierárquica com metadados ricos (artista, álbum, ano, duração)
  • radios.m3u: estações de rádio via streaming HTTP
  • feeds.rss: feeds RSS com links para arquivos de áudio

Sistema de Extensões Modular

O núcleo suporta plugins escritos em Python que se registram dinamicamente ao iniciar. Um plugin de exemplo para consulta climática:

from xiaomusic.plugin import PluginBase

class WeatherPlugin(PluginBase):
    def __init__(self):
        super().__init__(name="weather_v2", priority=10)
    
    def on_command(self, cmd: str, payload: dict) -> dict | None:
        if cmd == "clima":
            location = payload.get("cidade", "São Paulo")
            return {"status": "ok", "data": self._fetch_weather(location)}
        return None
    
    def _fetch_weather(self, city: str) -> dict:
        # Implementação real usaria OpenWeatherMap ou similar
        return {"temp": 22.5, "condition": "parcialmente nublado"}

Plugins podem interceptar comandos, modificar metadados de faixas ou disparar ações externas — tudo sem modificar o código principal.

Otimizações de Desempenho para Grandes Coleções

Em ambientes com mais de 10 mil faixas, recomenda-se:

  • Ativar cache em disco para resultados de busca ("cache_dir": "/srv/cache")
  • Limitar threads de download simultâneos a 3–5 com "max_download_workers": 4
  • Habilitar compactação de logs rotativos com "log_rotation": "1 week"
  • Usar SQLite com WAL mode ativado para acesso concorrente eficiente

Segurança Operacional

Proteção mínima recomendada inclui:

  • Autenticação HTTP básica com credenciais fortes (desativada por padrão em redes locais confiáveis)
  • Restrição de acesso à API via firewall de rede — expor apenas a porta 58090 internamente
  • Uso de conta Xiaomi dedicada com permissões restritas (não vinculada a pagamentos ou dados sensíveis)
  • Atualizações regulares da imagem Docker para incorporar correções de segurança

Integração com Ecosistemas Externos

A API REST permite orquestração com sistemas terceiros. Exemplo de automação com curl:

# Buscar e tocar música por nome
curl -X POST http://localhost:58090/api/v1/play \
  -H "Content-Type: application/json" \
  -d '{"device_id":"1234567890abcdef","query":"Bohemian Rhapsody"}'

# Obter status de todos os dispositivos conectados
curl http://localhost:58090/api/v1/devices/status

Essas chamadas podem ser integradas a fluxos de automação (ex: Node-RED, Home Asisstant) ou scripts agendados via cron.

Tags: Python FastAPI IoT xiaomi yt-dlp

Publicado em 10-14 05:55