Bonsai - Visão Geral do Desenvolvimento
28 de dezembro de 2024
Bonsai é uma plataforma que ajuda artistas a elevarem a experiência dos fãs e transformarem um momento em algo que vale a pena mostrar. Ela facilita a conexão entre um artista e seus fãs em várias plataformas, dando aos artistas uma melhor visão de sua base de fãs e permitindo que eles se comuniquem com seu público de forma criativa.
Um dos principais recursos da Bonsai são seus audiogramas; superfãs podem perguntar qualquer coisa aos seus artistas favoritos através de seus conteúdos e comunidades (YouTube, Discord, etc.) e os artistas podem responder fazendo pequenas gravações de áudio que, quando combinadas com nossa tecnologia, geram bonsais, um pequeno visualizador de áudio que pode ser facilmente compartilhado em plataformas sociais.
Inicialmente, a Bonsai entrou em contato comigo para pedir ajuda fazendo um upgrade em seu visualizador de audio.
Abordagem
A versão existente do visualizador foi criada usando o canvas providenciado por HTML, por meio de uma implementação vanilla, porém complexa, de pontos de linha, conectados e manipulados com base em dados de áudio para dar o efeito desejado. Meu objetivo era resolver três prioridades:
- Simplificar a implementação do visualizador
- Apromixar de forma melhor a implementação final do visualizador aos designs originais.
- Fazer o visualizador ser mais responsivo em relação aos dados de áudio recebidos.
Como tudo isso estava sendo feito do lado do cliente, minha abordagem foi usar Three.js. O motivo por trás da decisão foi que Three.js nos permitiria manter alguma familiaridade na nova abordagem ao continuar a usar um canvas ao mesmo tempo que forneceria geometrias pré-construídas que poderiam ser configuradas mais facilmente e estendidas por meio de shaders. Essa flexibilidade era importante, pois a Bonsai já tinha três layouts de visualizador diferentes construídos, e eu queria garantir que já houvesse uma estrutura disponível para criar futuros layouts.
Como o código é proprietário, não posso compartilhar trechos de código nem me aprofundar na implementação, mas há alguns pontos que posso abordar.
API Web Áudio
Para lidar com gravação de áudio e dados de frequência, usei a API de áudio da web, que já estava em uso na implementação anterior. A maior parte da lógica lá permaneceu a mesma, no entanto, usei meu conhecimento musical 😎 para adicionar uns enfeites adicionais aos dados. A principal mudança nesse contexto foi a implementação de um filtro Savitzky-Golay para suavizar os dados de frequência (isso foi particularmente útil para o layout de ondas que você pode ver mais abaixo), dando às nossas geometrias em movimento uma aparência mais uniforme.
Three.js
Para aqueles já familiarizados com Three.js, a implementação foi muito direta. Todos os layouts criados foram feitos usando uma geometria Line2 (para que tivéssemos suporte à espessura da linha). A parte central do esforço de trabalho que foi para esta etapa foi em
- garantir que os dados de frequência fossem distribuídos adequadamente entre as geometrias
- nos certificar de gerar apenas geometrias suficientes para caber na tela visível, e ao mesmo tempo possibilitar adaptar o audiograma às proporções disponíveis (1:1 e 9:16)
- Fazer com que o visualizador de áudio fosse o mais otimizado e eficiente possível (feito por meio de técnicas simples, como limpar adequadamente todas as geometrias não utilizadas para evitar que referências mortas permanecessem na memória, reduzindo o uso da GPU).
O resultado final dos três layouts pode ser visto abaixo:
Indo além
Ao concluir o visualizador de áudio 2.0, discutimos em equipe como poderíamos levar os audiogramas para o próximo nível e criar uma melhor experiência para o usuário. Decidimos remover completamente o visualizador do lado do cliente, deixando apenas os recursos de gravação no frontend. Quanto aos visuais, nossa meta era criar uma solução serverless que receberia o áudio gravado, geraria o audiograma na nuvem e retornaria o produto final ao usuário como um mp4. A meta com isso era desacoplar nossa ferramenta das restrições que vêm da GPU e do navegador do usuário. Se tudo funcionasse como esperávamos, nossa solução seria muito mais estável, simplificaria todo o processo de geração de audiogramas e nos permitiria ter melhor controle sobre a taxa de quadros.
Mais uma vez, como as soluções são proprietárias, só posso fornecer uma breve visão geral da abordagem do visualizador de áudio 3.0.
Para desenvolver nossa solução, optamos por usar Rust, que é uma linguagem de programação de baixo nível incrivelmente rápida e com uso eficiente de memória. Como não estávamos mais trabalhando com navegadores e o Three.js é construído sobre WebGL, o mesmo não era mais uma solução viável. Em vez disso, tivemos que procurar ferramentas mais próximas do OpenGL nativo e, por fim, decidimos fazer todo o nosso desenvolvimento visual usando wgpu. Depois que estabelecemos essas ferramentas, o desenvolvimento em si se concentrou principalmente em migrar a lógica da implementação existente enquanto nos adaptávamos às nuances da linguagem Rust.
A parte mais desafiadora até este ponto (o projeto inteiro ainda é um trabalho em andamento no momento em que este post foi escrito) foi definir a arquitetura apropriada para o microsserviço que estávamos desenvolvendo. Após várias iterações, chegamos à seguinte stack:
- Docker - para conteinerizar nosso gerador de audiogramas
- LambdaLabs - para hospedar nosso contêiner do Docker e, ao mesmo tempo, fornecer os recursos de GPU necessários
- AWS SNS - Para comunicação entre processos e acionamento dos recursos apropriados
- AWS S3 - Para armazenar todos os audiogramas gerados e acessar os dados pertinentes
Como resultado da arquitetura e linguagem de codificação escolhidas, terminamos com o seguinte audiograma (trecho mp4 convertido em gif).
Resultados
Então, quais foram os resultados do visualizador de áudio 3.0?
Primeiro e mais importante, desacoplamos com sucesso nossa ferramenta do navegador e da GPU do usuário. Isso significa que a geração de audiogramas foi padronizada; usuários com computadores lentos não precisam mais se preocupar com uma experiência de usuário lenta, pois todos os processos intensivos são executados fora de seu ambiente.
Segundo, simplificamos vários processos internos, particularmente aqueles relativos a como os audiogramas eram gerados anteriormente por meio de nossas ferramentas AWS. Tudo isso reduz potencialmente os custos de uso e torna nossas integrações mais fáceis de manter.
Finalmente, temos um controle muito melhor sobre a taxa de quadros. Isso pode não fazer sentido apenas olhando para o audiograma final, no entanto, devido à maneira como construímos este visualizador, podemos realmente definir a taxa de quadros que gostaríamos para nosso mp4 gerado. Nós pessoalmente fizemos a escolha de ficar com 60 fps, pois funciona mais do que perfeitamente para todos os nossos objetivos, mas ter a opção de aumentar/diminuir esse valor sem ter que nos preocupar com quedas de quadros é uma conquista fantástica.