As câmeras Blink da Amazon são baratas (você consegue 2 ou 3 câmeras por menos de 50 dólares em promoção na Amazon). A qualidade não é das melhores, mas elas dão para o gasto. Só que tem um grande problema: Se você quiser ter acesso as suas gravações, você precisa assinar o serviço da Blink (Amazon). E o que é pior, de acordo com os Termos de Serviço da Blink, ou Amazon:
You give us all permissions we need to use your Blink Recordings to do so. These permissions include, for example, the rights to copy your Blink Recordings, modify your Blink Recordings to generate clips, use information about your Blink Recordings to organize them on your behalf, and review your Blink Recordings to provide technical support.
É… não sei bem como me sinto sobre isso. Dar todas as permissões possíveis para a Amazon sobre as minhas gravações?
Por sorte existe uma alternativa: Você pode comprar um Blink Sync Module 2, armazenar tudo localmente e se livrar da nuvem/assinatura, certo? Não exatamente… 1) A assinatura ainda é necessária para reprodução instantânea de qualquer lugar, 2) você continua preso no ecossistema Amazon/Blink e dependente do app fechado deles, 3) você não tem muito controle sobre as gravações e arquivamento, 4) compartilhar acesso com outros usuários (cônjuge, filho, amigos) é uma dor de cabeça, e por aí vai.
Então se eu comprei as câmeras, por que não ser dono das minhas próprias gravações, decidir o que fazer com elas, reduzir o “blast radius” se algo der errado e ter uma assinatura a menos? Por cerca de $25 em hardware (menos de 3 meses da assinatura Blink), eu poderia ser dono do meu pipeline inteiro para sempre.
Então, com uma ideia na cabeça e o GitHub Copilot na tela, decidi escrever uma solução que atendesse às minhas necessidades e, com sorte, de outros também ;)
O resultado é o Watchman: um Raspberry Pi Zero 2 W que finge ser um drive USB para o Blink Sync Module 2, captura clipes de movimento, arquiva localmente e serve tudo através de uma interface web simples.
Repositório:
https://github.com/renanfernandes/watchman
Índice
- Pré-requisitos
- Por Que Eu Construí Isso
- Visão Geral da Arquitetura - Papo Nerd
- Como o Modo USB Funciona?
- Pipeline de Ingestão (Passo a Passo)
- Camada Web e Verificações de Segurança
- Modelo de Serviço e Operações
- Tradeoffs e Próximos Passos
Pré-requisitos
O Que Você Precisa:
| Item | Custo Aprox. |
|---|---|
| Raspberry Pi Zero 2 W | ~$15 |
| Cartão MicroSD (16 GB+) | ~$5 |
| Cabo USB OTG (Micro-USB para USB-A) | ~$5 |
| Blink Sync Module 2 | Já possui |
| Câmera(s) Blink | Já possui |
Custo único total: ~$25 vs. assinatura Blink de ~$10/mês (ou $100/ano).
O Pi se paga em menos de 3 meses. Depois disso, é de graça para sempre.
Por Que Eu Construí Isso
Comecei com um objetivo simples: parar de alugar acesso aos meus próprios dados.
Eu não queria um stack enorme de NVR ou uma solução completa tipo Unifi Protect. Meu setup roda a vários milhares de quilômetros de casa e eu queria algo barato e confiável o suficiente para simplesmente funcionar.
Isso me levou a alguns requisitos, como:
- Blink deve sempre ver um armazenamento USB válido
- Clipes devem ser movidos somente após as escritas terminarem
- Falhas devem se recuperar automaticamente
- Navegar/baixar clipes deve ser fácil pela rede. E se eu quiser, expor através de um reverse proxy no futuro.
As próximas seções vão explicar o que implementei e como foi desenvolvido. Basicamente papo nerd. Fique à vontade para pular toda a discussão de Arquitetura e implementação e ir direto ao meu repositório no github para seguir as instruções de setup e colocar para funcionar: https://github.com/renanfernandes/watchman
Visão Geral da Arquitetura - Papo Nerd
Para tudo o que eu faço, o Princípio KISS é meu guia. Com isso em mente, tudo que preciso é uma solução para 1) arquivar vídeos, 2) servir vídeos, então para este primeiro release o fluxo de arquitetura deve ser tão simples quanto:

Para alcançar isso e manter a simplicidade, o fluxo de controle usa apenas dois serviços:
watchman.py: O cérebro. Gerencia load/unload do USB gadget, montagem, ingestão de clipes, lógica de reset do watchdogweb.py: Interface web somente leitura para listar, reproduzir e baixar clipes arquivados
Outros componentes:
watchman.conf: configuração centralizada (caminhos, timing, portas)create_disk.sh: cria/formata o container USB baseado em arquivo - Usado apenas durante o processo de setupsetup.sh: setup do host + configuração de boot + instalação de serviços - Usado apenas durante o processo de setupwatchman.serviceewatchman-web.service: serviço systemd, para subir/derrubar o daemon
Como o Modo USB Gadget funciona ?
No Pi Zero, a porta USB OTG pode rodar em modo gadget. Isso significa que o Pi pode se apresentar como um dispositivo USB, não apenas como host. Para isso, você precisa de alguns ajustes, como habilitar dwc2 e g_mass_storage.
dwc2na configuração de bootg_mass_storageem runtime, apontando para um container de arquivo (padrão/ghostdrive.bin)
Em runtime o módulo é carregado com alguns parâmetros como:
modprobe g_mass_storage file=/ghostdrive.bin removable=1 ro=0 stall=0 \
idVendor=0x0781 idProduct=0x5571 iManufacturer=GhostDrive iProduct=USB_Drive
Repare que eu estou usando o arquivo ghostdrive.bin. Ele é criado pelo create_disk.sh, e ele é basicamente um arquivo que serve como um “container”. Isso faz com que fique facil para redimensionar o disco virtual, recriar, etc.
Pipeline de Ingestão (Passo a Passo)
O watchman.py funciona da seguinte forma:
- Descarrega o módulo USB gadget para que o Blink seja temporariamente desconectado.
- Monta o container localmente (ghostdrive.bin).
- Pesquisa por todos os arquivos
.mp4recursivamente. - Move os clipes para
ARCHIVE_DIR/YYYY-MM-DD. - Trata colisões de nome de arquivo (
clip.mp4,clip_1.mp4, etc.). - Descarrega/Desmonta o container.
- Recarrega o módulo USB gadget para que o Blink possa continuar escrevendo.
Os controles de timing da configuração são importantes aqui, eles previnem colisões e tentam minimizar a quantidade de conexões/desconexões:
SETTLE_TIME: esperar após as escritas estabilizarem antes de ciclarMIN_INTERVAL: evitar ingestão excessivaWATCHDOG_THRESHOLD: número de falhas antes do caminho de reset USB
Quando o threshold do watchdog é atingido, o Watchman faz um reset completo: descarrega o usb gadget, sobe o dwc2, e descarrega o gadget.
Você pode perguntar: Por que você está desconectando o módulo com tanta frequência? Bom, se você tiver uma solução melhor, me avise. Mas a razão por trás disso foi simplesmente evitar uma situação onde o Blink está escrevendo no dispositivo enquanto o script está fazendo uma operação. Você pode precisar ajustar o timing de acordo com suas necessidades.
Camada Web e Verificações de Segurança
O app Flask é intencionalmente simples:

/mostra as datas de gravação disponíveis/date/<date>lista vídeos de uma data/video/<date>/<filename>reproduz mp4/download/<date>/<filename>baixa mp4
Eu também criei algumas proteções básicas mas importantes:
- verificações do formato de data
- filtragem de travessia de nome de arquivo (evitar os famosos ../../etc/passwd)
Esse modulo web foi construído para uso em uma rede confiável, não como uma plataforma de mídia totalmente blindada para internet. Talvez eu coloque atrás de um reverse proxy no futuro para acessar remotamente sem precisar estar na VPN. Mas isso fica para depois.
Se você quer aprender sobre implementar seu próprio reverse proxy com Caddy com Entra ID, confira o post Protegendo Home Assistant com Caddy e Microsoft Entra ID.
Modelo de Serviço e Operações
Ambos os componentes rodam como serviços systemd e iniciam automaticamente no boot. Isso possibilita:
- reiniciar o serviço automáticamente em caso de falha
- verificar o status do serviço
- logs centralizados no journald e quem sabe até enviar para um syslog remoto
Você pode usar os comandos que ja está acostumado no journalctl para fazer troubleshooting:
journalctl -u watchman -f
journalctl -u watchman-web -f
Tradeoffs e Próximos Passos
Eu sei que a solução não é perfeita, mas contando que isso tudo levou algumas horas de design e vibe coding, estou ok com os tradeoffs.
Para um próximo release, definitivamente vou adicionar alguma extensibilidade como:
- replicação fora do dispositivo (NAS/object storage)
- políticas de retenção/limpeza
- integração com Home Assistant - Sim, eu quero assistir a gravação no meu Dashboard do Home Assistant
- endpoint básico de health + métricas
Tem alguma outra feature/capacidade que você gostaria de ver incorporada? Me avise ou melhor ainda, contribua com o projeto!
Este projeto removeu mais uma assinatura recorrente da minha vida.
No fim do dia, se um serviço me entrega valor claro, eu não tenho problema nenhum em assinar. Agora se o modelo de negocios é cobrar aluguel nos meus próprios dados, ou se a empresa não está alinhada com meus valores, eu prefiro construir eu mesmo.