Executando verificação de segurança...
2

Como fazer upload massivo de fotos e vídeos de forma eficiente?

Olá a todos!

Estou desenvolvendo um projeto pessoal que pretendo colocar no ar e esbarrei na seguinte situação: para facilitar a vida do usuário quando ele subir fotos ou vídeos (a princípio, curtos, de até 90 segundos), quero oferecer a opção de selecionar vários arquivos em suas respectivas seções e enviar tudo de uma vez. Se ele tiver 3 mil fotos e mil vídeos, seleciona tudo e manda.

O sistema deve receber os arquivos no backend, transformar as fotos em WebP e converter os vídeos para MP4 (720p) usando FFmpeg, armazenando-os no bucket correto da AWS, dentro da pasta de cada cliente.

Se o cliente subir mil fotos e as de número 354 e 789 falharem por algum motivo, as demais devem ser enviadas ao bucket corretamente. O usuário deve visualizar na tela quais arquivos falharam para tentar o reenvio. A mesma lógica se aplica aos vídeos.

Além disso, não pode haver interferência entre usuários: se o "Cliente A" sobe 10 mil fotos, isso não pode travar o upload de apenas duas fotos do "Cliente B". Estou evitando ao máximo o uso de filas (como Kafka ou SQS) para manter a arquitetura simples, mas preciso levar em consideração o consumo de banda larga caso alguém faça uploads massivos.

Essa funcionalidade é a parte mais complexa do sistema até o momento. A forma mais simples que concebi foi fazer o frontend (Next.js + Axios) enviar batches de 50 fotos e 10 vídeos (devido ao processamento mais pesado do FFmpeg). Quando o backend (Java + Spring, embora eu considere mudar para Go por eficiência e custo na AWS) recebe os arquivos, ele abre threads para processar esses batches paralelamente, na lógica de uma thread por batch.

Alguém já lidou com uma situação parecida?

Obrigado!

Carregando publicação patrocinada...
1

O que eu faria:

Para cada arquivo bruto

  • Solicitar uma url de upload pré assinado do bucket da aws (ex. /uploads/{userId}/{fileId})
  • Fazer o upload DIRETO para a aws do arquivo bruto
  • enviar uma notificação para o backend que o upload foi concluído (pode ser agrupado em batch aqui, ex: a cada 25 concluidos enviar uma notificação com as ids dos 25)
  • o backend recebe essas ids e coloca e uma fila com RabbitMQ

Worker

  • Worker escuta a fila
  • Quando receber uma id baixa o arquivo da aws, processa e envia convertido no caminho final
  • Se não quiser guardar o bruto apaga o bruto

Pontos de falha

  • Upload deu erro (pode retentar o mesmo arquivo)
  • Conversão deu erro

Para a primeira eu já avisaria no front
Para a segunda precisa implementar algum tipo de notificação (server sent events ou coloca a lista de arquivos no db mesmo pra consultar depois)

Desafios

  • Mostrar o progresso da conversão dos arquivos, já que roda em um processo separado

Porque essa arquitetura?

Se você fizer o upload para o seu servidor, processar e enviar somente o arquivo final a aws vai precisar de um servidor muito forte. O cliente vai precisar esperar converter cada arquivo.

No final o cliente vai esperar: upload + conversao + upload bucket

Se colocar numa fila você pode deixar processando por horas em background e o cliente só espera realmente o upload. A conversão pode acontecer depois

1

Boa proposta, é mais ou menos a minha conclusão porque tentar sem fila está ruim, apesar de funcionar.

Meu único problema com isso é o usuário precisar da foto logo em seguida do upload. Se eu seguir esse caminho eu posso cair em algum cenário de colocar a conta do cliente em hold até que as fotos dele terminem de converter.

Sem falar nos vídeos. O FFMPEG consome muito recurso ao processar.

1

Se eu seguir esse caminho eu posso cair em algum cenário de colocar a conta do cliente em hold até que as fotos dele terminem de converter.

Mostra só o que está convertido, deixa um aviso de processando em algum lugar da tela

O FFMPEG consome muito recurso ao processar.

Sim

A questão é: porque você está fazendo isso? não encontro um cenário viável onde você precisa processar tantos arquivos.

1

Existem usuários que têm, por exemplo, 3k+ de fotos e 1k+ de videos. Nesses casos, mesmo esporádicos, eu preciso permitir que o usuário selecione as 3k de fotos ou 1k de vídeos e suba na plataforma. Como o back vai fazer pra processar nos formatos ideias e salvar no bucket do usuário é o desafio nesse cenário.