F4L – Distribuição Automatizada de Música no YouTube
2024Ferramenta de distribuição YouTube ponta a ponta para selos independentes. Faça upload de um WAV e um PNG de capa, preencha título e descrição — o F4L codifica um vídeo 1080p inteiramente no navegador com FFmpeg WASM, faz staging no Google Cloud Storage e sobe diretamente ao YouTube via Data API v3. Zero processamento de vídeo no servidor.
F4L (Friend4Label) é uma ferramenta de automação full-stack criada para a Tropical Twista Records — um selo musical independente com um fluxo de distribuição no YouTube repetitivo. Para cada lançamento, a equipe precisava abrir manualmente um editor de vídeo, fazer loop da capa pelo tempo da faixa, exportar um MP4 1080p, abrir o YouTube Studio, fazer upload e preencher os metadados. O F4L elimina cada etapa manual após a seleção de arquivos: forneça um WAV e uma imagem de capa, preencha título e descrição, e a ferramenta cuida da codificação, staging e upload para o YouTube.
Selos musicais independentes lançam músicas com frequência mas não têm equipe técnica ou tempo para a criação manual de vídeo que a distribuição no YouTube exige. Produzir um 'vídeo estático' (arte em loop + áudio) para cada faixa leva de 20 a 30 minutos de trabalho completamente repetitivo e totalmente automatizável. O processo escala mal: um álbum de 10 faixas significa 10 passes manuais separados pelo mesmo fluxo.
Construir uma ferramenta de página única que: (1) autentique via Google OAuth2 com escopo de upload do YouTube; (2) codifique um vídeo 1080p a partir de WAV + PNG inteiramente no navegador sem processamento de vídeo no servidor; (3) faça staging no GCS e upload ao YouTube com metadados fornecidos pelo usuário; (4) permita pré-visualizar o vídeo antes do passo final de upload.
- ◈Desenvolvedor solo — arquitetura, frontend, backend, integração OAuth2, API do YouTube
- 01FFmpeg compilado para WebAssembly para codificação in-browser — a decisão arquitetural mais significativa. Usando @ffmpeg/ffmpeg com o core WASM multi-threaded (core-mt), a codificação roda inteiramente no navegador: transcode WAV → AAC, PNG → vídeo 1080p em loop, depois mux. Zero custo de GPU ou CPU no servidor. O tradeoff: exige SharedArrayBuffer, que requer headers COOP/COEP e o plugin Vite vite-plugin-cross-origin-isolation.
- 02GCS como camada de staging temporária — em vez de enviar o vídeo diretamente do navegador para a API do YouTube, a arquitetura usa o Google Cloud Storage como intermediário: o navegador faz upload do MP4 para o Express, que transmite ao GCS; o JSON de metadados é enviado separadamente; uma chamada submit final instrui o backend a buscar ambos no GCS e enviar ao YouTube. Isso desacopla a codificação do timing do upload.
- 03Arquivos no GCS com namespace UUID — cada sessão gera um UUID no mount. Todos os objetos GCS (video-<uuid>.mp4, metadata-<uuid>.json) usam esse UUID como namespace, evitando colisões entre usuários simultâneos ou múltiplas abas sem coordenação de backend.
- 04Extração de duração via parsing do log do FFmpeg — para determinar a duração do vídeo para o comando -loop 1, o código executa ffmpeg -i inputAd.wav intencionalmente para acionar o output de informações, captura o stream de log e analisa 'Duration: HH:MM:SS.xx' com regex. Um padrão não oficial, mas confiável, para metadados de mídia no WASM.
- 05Fluxo OAuth2 de código de autorização manual após iterar por 3 abordagens de auth — o codebase contém rastros de passport-google-oauth20, @react-oauth/google e botões HTML do Google Identity Services. A solução final usa uma troca de código de autorização no lado do servidor, dando controle total sobre armazenamento de tokens e configuração de escopo.
- 06Backoff exponencial na busca de dados do usuário — a função login() implementa um loop de retry manual (até 5 tentativas, começando em 1s, dobrando a cada tentativa) para lidar com a race condition entre a escrita no Firestore e a chamada imediata de GET /getuser.
- 07Cache de usuário em memória no backend — o backend escreve no Firestore (persistente) e armazena os dados do usuário como variável em nível de módulo na memória. GET /getuser lê da memória, evitando round-trip ao banco a cada hidratação de sessão, ao custo de perder o cache ao reiniciar o servidor.
- →FFmpeg WASM é viável para produção em codificação de vídeo leve a média no navegador, mas os requisitos de headers COOP/COEP para SharedArrayBuffer exigem coordenação cuidadosa entre a config do dev server Vite e o servidor Express de produção — uma má configuração cai silenciosamente para modo single-threaded sem aviso.
- →A camada de staging no GCS adiciona um hop de rede, mas oferece uma vitória de UX: codificação e entrada de metadados são totalmente desacopladas, permitindo que o usuário revise o vídeo e preencha a descrição enquanto o arquivo ainda está fazendo upload.
- →Iterar por múltiplas bibliotecas de auth antes de chegar a um fluxo OAuth2 manual foi demorado, mas produziu um entendimento muito mais profundo da troca de tokens, negociação de escopo e ciclo de vida de sessão — tornando o debugging do auth de produção mais tratável.
- →Armazenamento de arquivos com escopo UUID é uma estratégia de isolamento simples e robusta: não requer sincronização de sessão no backend e é trivialmente testável — basta verificar que duas sessões simultâneas produzem caminhos de objetos GCS diferentes.
- →Fazer parsing de metadados de mídia a partir do output de log do FFmpeg é frágil mas pragmático para inputs WAV onde a duração está sempre presente em formato previsível. Para uma ferramenta de produção que lida com múltiplos formatos de container, uma etapa de extração dedicada (ex: ffprobe) seria mais robusta.
Com features completas — construído para a Tropical Twista Records