APIs · Serviço

AZ Media

O serviço que recebe toda foto e todo vídeo da plataforma, guarda os arquivos, decide o que pode ser publicado e é dono do AZ Play. Este documento descreve o caminho completo, do toque em “publicar” até o conteúdo aparecer no aplicativo.

  • Repositório api.az.media.collectionsaz.com
  • Tecnologia Hono · Prisma · RabbitMQ
  • Estado Só em homologação

O que ele é dono

O AZ Collections divide responsabilidades entre serviços, e cada dado tem um único dono. Quem é dono decide, guarda e avisa os outros — os demais mantêm cópias apenas para ler.

Dono

Fotos e vídeos

Todo arquivo enviado por usuário: foto de post, imagem de produto, avatar, capa e vídeo do AZ Play.

Dono

AZ Play

O vídeo em si e o engajamento dele — curtidas, comentários, respostas, salvamentos e visualizações.

Dono

Moderação de conteúdo

A decisão sobre publicar ou barrar cada mídia, e o registro do motivo.

Do servidor principal

Usuários e seguidores

Nome, avatar e quem segue quem. O AZ Media mantém uma cópia local, alimentada por eventos.

Da Cloudflare

Os arquivos em si

Imagens ficam no R2; vídeos, no Stream, que também faz a conversão e a entrega.

A consequência que mais importa

Os arquivos nunca ficam no servidor. O aplicativo envia direto para a Cloudflare, e o AZ Media só guarda o registro — quem enviou, para quê, em que estado está e onde o arquivo mora. É por isso que o disco do servidor não cresce com o uso, por mais conteúdo que seja publicado.

O mapa em uma tela

Duas características do desenho explicam quase tudo o que vem a seguir: o arquivo não passa pelo servidor e os serviços não se chamam diretamente — eles trocam mensagens por uma fila, o que permite que um fique fora do ar sem derrubar o outro.

Fluxo 1 · Envio de imagem

PENDING UNDER_REVIEW READY REJECTED

  1. Aplicativo → AZ Media Pedido de autorização

    O aplicativo informa a finalidade da imagem, o tipo do arquivo e o tamanho. A finalidade é o que define as regras: uma foto de perfil e uma imagem de produto têm limites diferentes.

  2. AZ Media Validação e reserva

    O serviço recusa tipo não permitido e tamanho acima do limite antes de qualquer arquivo trafegar. Garante que o autor exista na cópia local de usuários, grava o registro em PENDING e devolve uma URL de envio assinada, com validade curta.

  3. Aplicativo → Cloudflare R2 Envio do arquivo

    O aplicativo envia os bytes diretamente para o R2, sem passar pelo servidor. Isso poupa banda e memória, e é o motivo de uma falha aqui não aparecer em nenhum registro do servidor — o tráfego acontece entre o aparelho e a Cloudflare.

  4. Aplicativo → AZ Media Confirmação

    Concluído o envio, o aplicativo avisa. Com a moderação desligada, a imagem vai direto para READY. Com ela ligada, fica em UNDER_REVIEW e uma mensagem de pedido de análise entra na fila.

  5. AZ Media (consumindo a própria fila) Análise e veredito

    A imagem passa pelas duas camadas de IA descritas adiante. Aprovada, vira READY; reprovada, REJECTED, com o motivo registrado. Nos dois casos, o resultado é publicado na fila para o servidor principal.

Finalidades aceitas e seus limites de tamanho.
FinalidadeOnde apareceLimite
POST_IMAGEFoto de publicação no feed15 MB
ITEM_IMAGEFoto de produto anunciado15 MB
PROFILE_BANNERCapa do perfil10 MB
GALLERY_COVERCapa de coleção10 MB
JOURNAL_COVERCapa de publicação editorial10 MB
SHOWCASE_IMAGEImagem de vitrine10 MB
PROFILE_IMAGEFoto de perfil5 MB
AZPLAY_COVERCapa personalizada de vídeo5 MB
AZPLAYVídeo do AZ Play512 MB

Imagens aceitam JPEG, PNG e WebP; vídeos aceitam MP4, QuickTime e WebM.

Fluxo 2 · Envio de vídeo

O vídeo segue o mesmo início, mas com uma diferença importante: o AZ Media não sabe quando o vídeo ficou pronto. Quem avisa é a Cloudflare, depois de converter o arquivo.

PENDING PROCESSING UNDER_REVIEW READY REJECTED / FAILED

  1. Aplicativo → AZ Media → Cloudflare Stream Reserva e envio

    Igual à imagem, mas o destino é o Stream, que aceita arquivos de até 512 MB e cuida da conversão para os formatos de reprodução.

  2. Cloudflare Stream → AZ Media Aviso de conclusão

    O Stream chama o AZ Media de volta conforme o processamento avança. Enquanto não está pronto, o vídeo fica em PROCESSING. Só vira pronto quando o aviso traz, ao mesmo tempo, a confirmação de conclusão e o endereço de reprodução.

  3. AZ Media Verificação de duração

    A duração é conferida a partir do que a Cloudflare informa, não do que o aplicativo declarou — o número declarado pelo cliente é justamente o que alguém mal-intencionado controlaria. Vídeo acima do teto vai para FAILED, com o motivo registrado.

  4. AZ Media Moderação sobre as capas

    A análise de vídeo não examina o arquivo inteiro: usa as miniaturas geradas pelo Stream, cinco por padrão. Cada miniatura passa pelas duas camadas, como se fosse uma imagem. Qualquer uma reprovada reprova o vídeo.

A cópia de usuários

O AZ Media precisa saber o nome e o avatar de quem publicou para montar a tela do AZ Play, e precisa saber quem segue quem para a aba “Seguindo”. Nada disso é dele — pertence ao servidor principal. Em vez de perguntar a cada abertura de tela, ele mantém uma cópia local, atualizada por eventos.

Por que cópia e não consulta

Consultar o servidor principal a cada abertura do feed o colocaria no caminho mais quente do aplicativo: toda rolagem de vídeo viraria uma chamada extra. Com a cópia, o AZ Media responde sozinho, e uma indisponibilidade do servidor principal não derruba o AZ Play.

Como a cópia se mantém

Eventos que alimentam a cópia local, todos vindos do servidor principal.
EventoEfeito no AZ Media
user.createdCria a linha do usuário na cópia.
user.updatedAtualiza nome e avatar.
user.deletedAnonimiza em vez de apagar — fotos, vídeos e reels apontam para essa linha.
follow.createdRegistra que alguém passou a seguir outra pessoa.
follow.deletedRemove o vínculo.

O detalhe que evita um erro comum

A sincronização é assíncrona: o evento pode demorar, ou não chegar por diferença de ambiente. Se alguém enviasse uma foto antes de a cópia receber o usuário, a gravação falharia por referência inexistente.

Para evitar isso, o serviço cria um registro provisório do autor no momento do envio, usando a identidade do token — que é confiável, porque a chave de assinatura é compartilhada com o servidor principal. Quando o evento chega, nome e avatar são preenchidos por cima.

As duas sincronizações têm filas separadas, e isso é deliberado: uma falha ao gravar o grafo de seguidores não pode atrasar ou descartar o nome e o avatar de um usuário, que é o que toda tela exibe.

A conversa com o servidor principal

Os dois serviços nunca se chamam diretamente. Toda comunicação passa por uma fila de mensagens, com um endereço único por assunto. Quem publica não sabe quem escuta, e quem escuta não precisa que o outro esteja no ar naquele instante.

O que o AZ Media escuta

Quatro filas próprias, cada uma com sua responsabilidade.
FilaEscutaPara quê
user-synccriação, alteração e exclusão de usuárioManter nome e avatar na cópia local.
follow-syncseguir e deixar de seguirAlimentar a aba “Seguindo” do AZ Play.
media-deletedexclusão de mídiaMarcar a mídia como removida, iniciando a contagem da retenção.
moderationpedido de análiseRodar a moderação. Publicada pelo próprio AZ Media — a fila serve para não travar a resposta ao aplicativo.

O que o AZ Media anuncia

Eventos publicados e o que o servidor principal faz com cada um.
EventoSignificaO servidor principal usa para
media.readyMídia aprovada e disponívelLiberar a publicação que dependia dela.
media.rejectedBarrada pela moderaçãoAvisar o autor e não exibir o conteúdo.
media.failedFalhou no processamentoMostrar o erro ao autor.
azplay.publishedVídeo publicadoAlimentar a busca global, que mistura vídeos e publicações numa lista só.
azplay.updatedVídeo alteradoAtualizar essa mesma projeção.
azplay.deletedVídeo removidoRetirar da busca.
azplay.saved / unsavedSalvo ou removido dos salvosMontar a aba “Salvos” do perfil, misturando publicações e vídeos.
azplay.metricsContadores de visualizaçãoOrdenar a fileira de vídeos mais vistos.
azplay.comment.createdNovo comentárioNotificar o autor do vídeo.
azplay.reply.createdResposta a comentárioNotificar o autor do comentário.
mention.createdAlguém citou um @ em algum textoResolver o @ e notificar — a gramática dos nomes vive no servidor principal.
Duas decisões de projeto que valem conhecer

Cada evento de vídeo carrega a informação completa, não apenas o que mudou. Assim, um evento perdido se corrige sozinho no próximo, e um evento repetido não causa dano — é o que permite reprocessar a fila quantas vezes for preciso, sem medo.

Não existe evento por curtida ou por visualização. Uma mensagem a cada visualização inundaria a fila só para manter um número atualizado. Os contadores viajam junto do próximo evento e podem ficar alguns minutos atrasados, o que é aceitável para o que representam.

Mensagens que falham repetidamente vão para uma fila de mensagens problemáticas, em vez de bloquear a fila principal. E cada evento processado fica registrado, de modo que receber a mesma mensagem duas vezes não produz efeito duplicado.

A filtragem por IA

Toda mídia enviada passa por uma análise automática antes de aparecer para alguém. O objetivo é barrar pornografia, violência explícita, drogas e armas — e o que a análise reprova nunca chega ao feed.

São duas camadas, com a mesma lógica de um filtro grosso seguido de um fino: uma análise barata resolve os casos evidentes, e só a zona de dúvida sobe para uma análise mais cara, que entende contexto.

Como calibrar

As duas configurações que definem o comportamento do filtro.
ConfiguraçãoPadrãoO que faz
MODERATION_UNCERTAIN_LOW 0,35 Abaixo disso, aprova direto. Menor = mais rígido, porque manda mais conteúdo para a segunda camada conferir.
MODERATION_UNCERTAIN_HIGH 0,7 A partir disso, reprova direto na primeira camada. Menor = mais rígido, porque reprova com menos certeza.

Combinações úteis:

  • Tudo passa pela segunda camada: limite inferior em 0 e superior em 1. Nada é decidido localmente — mas a primeira camada continua rodando, como explicado abaixo.
  • Só a primeira camada: os dois limites iguais, por exemplo ambos em 0,5. A zona de dúvida desaparece e nada é enviado para fora.
  • Auditar antes de valer: manter a moderação desligada e observar os registros num ambiente de teste, calibrando as faixas com conteúdo real.

Os limites não podem ser invertidos

A verificação de reprovação acontece antes da de aprovação. Com o limite superior menor que o inferior, a zona de dúvida fica vazia e qualquer pontuação acima do superior é reprovada sem consulta à segunda camada — o oposto do pretendido.

Os dois valores precisam estar entre 0 e 1, e o inferior deve ser menor que o superior. Valores fora dessa faixa impedem o serviço de subir.

Onde cada camada roda — e por que isso importa

As duas camadas fazem trabalhos diferentes e, hoje, rodam em lugares diferentes:

No servidor

Camada 1 · filtragem

Dois modelos carregados na memória do próprio serviço. Responde por 2,5 GB de memória e por um pico de 115% de processamento a cada análise.

Na nuvem

Camada 2 · modelo de visão

Hospedado pela Cloudflare. Não consome memória nem processamento do servidor — para ele, é apenas uma chamada de rede e uma espera.

Por que a filtragem existe

Ela não é uma exigência de qualidade — é uma economia. O modelo de visão custa entre 23 e 52 vezes mais por imagem analisada. A filtragem resolve localmente os casos evidentes e envia para fora apenas a zona de dúvida, mantendo o consumo do serviço de nuvem numa fração da cota gratuita.

Sem ela, toda imagem consultaria o modelo de visão. Isso funciona no volume atual, mas consome entre 34% e 54% da cota diária gratuita — e o teto fica próximo.

O que seria um classificador hospedado

A saída natural para o custo da camada 1 seria mantê-la, mas fora do servidor: em vez de carregar os modelos na própria memória, chamar um classificador hospedado — um modelo de classificação de imagem que roda na infraestrutura de um provedor, do mesmo jeito que a camada 2 já faz.

O funcionamento é o mesmo da camada atual: envia-se a imagem e recebe-se de volta uma lista de rótulos com pontuação de confiança. A diferença está apenas em onde a conta é feita — e o preço é irrisório: cerca de 0,23 unidade de consumo por imagem, contra 5 a 12 do modelo de visão. Com a cota diária gratuita seria possível classificar dezenas de milhares de imagens sem custo.

O impedimento — vale conhecer antes de planejar

O classificador de imagem disponível no catálogo da Cloudflare é treinado para reconhecer objetos — cerca de mil categorias do tipo “revólver”, “faca”, “garrafa”. Ele identificaria armas, mas não detecta nudez, que é a categoria mais sensível das quatro que a moderação precisa cobrir.

Os modelos de segurança de conteúdo do mesmo catálogo analisam texto, não imagem. Não existe hoje, ali, equivalente hospedado do detector que roda localmente.

Restam, portanto, três caminhos com cobertura completa: manter a filtragem no servidor com os ajustes de contenção; movê-la para um contêiner sob demanda, que executa o mesmo modelo fora da máquina; ou contratar um serviço especializado em moderação de imagem, cujo produto é exatamente esta função. A comparação entre eles, com números, está na análise de infraestrutura.

A primeira camada roda sempre

Ampliar a zona de dúvida para que tudo seja encaminhado à segunda camada não elimina o processamento local: é a primeira camada que produz a pontuação usada para decidir o encaminhamento, e ela é executada antes de qualquer escalonamento. Nessa configuração somam-se os dois custos.

Executar apenas a camada remota exigiria um caminho no código que dispensasse a análise local — algo que hoje não existe. É o que dá peso a esse serviço na análise de infraestrutura.

Armazenamento e retenção

Imagens

Cloudflare R2

Armazenamento de objetos. O caminho do arquivo é organizado por finalidade, e o envio acontece por URL assinada de validade curta.

Vídeos

Cloudflare Stream

Recebe, converte para os formatos de reprodução, gera as miniaturas e entrega ao aplicativo.

Banco próprio

Registros

Quem enviou, para quê, em que estado está, onde o arquivo mora e o histórico da moderação. Nenhum byte de mídia.

Exclusão em duas etapas

Apagar mídia é feito em dois tempos, e isso é proposital — dá margem para desfazer engano e para atender pedido de suporte.

  1. Marcação

    Ao receber o aviso de exclusão, a mídia é marcada como removida e some do aplicativo. O arquivo continua onde está.

  2. Exclusão definitiva

    Uma rotina diária, às 03:00, apaga em definitivo o que foi marcado há mais tempo que o período de retenção — o arquivo na Cloudflare e o registro no banco. É a única rotina agendada do serviço, e ela apaga de verdade: vale conhecer antes de mexer no horário ou no prazo.

Por que o serviço roda em instância única

A rotina diária e o consumo das filas acontecem dentro do mesmo processo que atende as requisições — não há um processo trabalhador separado.

Duas cópias do serviço significariam duas exclusões definitivas às 03:00 e dois consumidores disputando a mesma fila. É por isso que ele precisa rodar em uma instância só, e é uma das razões pelas quais não se encaixa em modelos de execução que criam e destroem cópias livremente.

Autenticação

O AZ Media não emite credencial nenhuma. Quem autentica é o servidor principal: ele assina o token, e o AZ Media apenas confere a assinatura com a mesma chave, sem precisar consultá-lo.

A armadilha desse desenho

Se a chave dos dois serviços divergir, toda requisição ao AZ Media é recusada — e a mensagem que chega ao aplicativo é apenas “não foi possível conectar”, que não aponta para a causa. A esteira de publicação exige que a chave esteja definida, mas não tem como verificar se o valor é o mesmo dos dois lados.