media, e quem o usa —
a aula, a capa do curso, a marca do club — aponta para essa linha. Reuso sai de
graça: a mesma mídia em dois lugares são dois donos apontando para a mesma
linha, não duas cópias.
Pastas
Árvore de até seis níveis, comparent_id. O nome é único dentro da mesma
pasta. Mover uma pasta para dentro dela mesma — ou de uma subpasta dela — é 422
invalid_folder: seria um ciclo, e o ramo sumiria da árvore.
Apagar uma pasta sobe as pastas de dentro e as mídias um nível. Conteúdo não
some porque alguém organizou a biblioteca.
Uma mídia está em uma pasta. Estar em vários lugares ao mesmo tempo é etiqueta,
e etiqueta ainda não existe.
Enviar
Vídeo mora na Bunny Stream, que transcodifica e entrega HLS. Imagem, áudio e documento moram no R2. Os dois sobem direto do browser, e o arquivo nunca passa pela API.
A chave da conta nunca vai para o browser: o que viaja é uma assinatura, que
vale para um arquivo e por pouco tempo.
Na conclusão do arquivo, quem confirma é o bucket — a API pergunta a ele se
o objeto existe, qual o tamanho e qual o tipo. “Enviado” não é a palavra de quem
enviou: sem essa conferência, um envio interrompido viraria uma aula com
material que não abre.
É ali também que o limite de tamanho vale (500 MB por arquivo, por padrão):
a assinatura autoriza o objeto, não o tamanho dele. O que passa do teto é
apagado do bucket e a mídia fica
failed, com o motivo.
Envio que nunca termina não fica “enviando” para sempre: uma varredura pergunta
ao bucket de tempos em tempos, recupera o que chegou atrasado e dá por perdido o
que não chegou depois de 24 horas.
Pública ou privada
Toda mídia nasce privada. Publicar é escolha explícita, e a diferença é de bucket: objeto privado não tem endereço público, então nenhum erro de código consegue publicá-lo.
O que o endereço estável resolve: a prévia de link do WhatsApp busca a imagem
dias depois; a capa dentro de um e-mail precisa continuar abrindo; e o CDN só
cacheia o que não muda. Uma URL assinada falha nos três.
Vídeo também pode ser público — é o trailer do curso ou a aula de
demonstração, entregue sem token para quem ainda não comprou.
Trocar a visibilidade move o arquivo entre os buckets, server-side: os bytes
não passam pela API. Com uma trava: publicar uma mídia que está em uma aula é
recusado com 409
media_in_use. Material pago que vira público por um clique
distraído é o erro que não se desfaz — quem baixou, baixou.
Imagem
Imagem pública é entregue redimensionada pelo CDN, em dois tamanhos fixos: 400 px para grade e card, 1600 px para a página. O formato é escolhido pelo browser (AVIF ou WebP), e imagem menor que o pedido não é ampliada. Nada é gerado no envio nem guardado: a transformação acontece no primeiro acesso e fica no cache. Os tamanhos são fixos de propósito — cada largura diferente é uma entrada nova no cache, e duas variantes bem escolhidas acertam quase sempre. Imagem privada sai no tamanho original: a URL assinada aponta para fora da zona do CDN, e cada resposta tem uma assinatura diferente, então não haveria cache a aproveitar.Estados
uploading → processing → ready, ou failed com o motivo em error. O
provedor avisa por webhook quando termina, e o aviso não é acreditado: ele
serve como “vá olhar este vídeo”, e o que é gravado vem da consulta à API dele.
Se o aviso se perder, uma varredura pergunta de novo — mídia parada não fica
parada para sempre.
Entrega
O endereço do arquivo é assinado no momento em que a resposta sai, com prazo curto, e depois de o direito e a agenda terem decidido. Ele não é guardado em coluna nem em cache: link assinado dentro de cache é link que expira guardado. Para arquivo, toda entrega é assinada por construção: o bucket não é público. Para vídeo,signed: false significa que a zona está sem chave de token e o
arquivo é servido a quem souber a URL — a resposta diz isso em vez de fingir
proteção.
Tirar da biblioteca
- Arquivar tira do seletor e a mídia continua sendo entregue onde já está em uso. É o que fazer na dúvida.
- Excluir apaga também no provedor, e só funciona com zero usos: se
alguma aula, anexo, capa ou marca aponta para ela, a resposta é 409
media_in_usecom a lista de onde.
GET /media/{id}/usage responde essa pergunta a qualquer momento.