Pitch: Fiz um player de vídeo em ASCII para rodar no terminal. Achei que seria piada, mas virou um baita problema técnico.
Tem projeto que nasce de uma necessidade real.
E tem projeto que nasce de uma ideia tão absurda que você só continua porque quer descobrir até onde dá pra levar.
O Kairo nasceu assim.
A proposta é simples de explicar e meio ridícula de ouvir pela primeira vez: reproduzir vídeos diretamente no terminal, frame por frame, em ASCII, com cor e com áudio sincronizado.
Na prática, é isso aqui:
kairo video.mp4
E o terminal vira um player de vídeo em texto.
No começo parecia só uma brincadeira técnica.
Pegar frame, converter pra caracteres, imprimir na tela, fim.
Só que eu comecei a mexer nisso e o buraco era bem mais interessante do que parecia.
Porque fazer “aparecer um frame em ASCII” é fácil.
O difícil é fazer isso rápido o suficiente pra deixar de ser uma demo e começar a parecer um player de verdade.
E quando você adiciona áudio na equação, o problema fica ainda mais interessante.
Foi aí que o projeto deixou de ser piada e virou engenharia.
O problema real
Se você quiser transformar vídeo em ASCII do jeito mais ingênuo possível, o caminho é mais ou menos esse:
- Decodifica o vídeo
- Pega um frame
- Converte os pixels em caracteres
- Imprime tudo no terminal
- Repete
Funciona.
Mas funciona mal.
Muito mal.
O terminal não foi feito pra isso.
Cada frame tem muita informação.
Cada caractere tem custo.
Cada atualização de tela pode virar gargalo.
E ainda existe outro problema: áudio.
Se o vídeo roda em uma velocidade e o áudio em outra, a experiência quebra completamente.
Então o desafio do Kairo virou esse:
Como fazer um vídeo em ASCII colorido rodar no terminal com áudio sincronizado e ainda manter uma taxa de frames decente?
Como o Kairo funciona
O pipeline básico do Kairo funciona em algumas etapas.
Primeiro o vídeo é decodificado frame por frame.
Cada frame vira uma matriz de pixels.
Depois o frame passa por um processo de redução espacial para caber na resolução do terminal.
Cada bloco da imagem representa um caractere.
Em seguida acontece o mapeamento de luminância.
Cada região da imagem é convertida para um caractere ASCII baseado na intensidade do pixel.
Caracteres mais densos representam regiões mais escuras.
Caracteres mais leves representam regiões claras.
Algo nessa linha:
.:-=+*#%@
Só que ASCII puro ainda ficava meio sem graça.
Então o Kairo também usa cores ANSI 24-bit para preservar a cor original da imagem.
Ou seja, cada caractere não representa só brilho.
Ele também carrega a cor daquele ponto do frame.
Isso muda completamente o resultado visual.
De repente não parece mais um monte de símbolos aleatórios.
Parece um vídeo rodando dentro do terminal.
E surpreendentemente funciona melhor do que parece.
O desafio do áudio
Renderizar vídeo em ASCII já é um problema de performance.
Mas sincronizar isso com áudio adiciona outra camada de complexidade.
O áudio precisa ser reproduzido continuamente enquanto os frames são processados.
Isso significa que o render de vídeo não pode simplesmente rodar o mais rápido possível.
Ele precisa respeitar o tempo real do vídeo.
Então o Kairo usa o timestamp dos frames como referência de tempo.
Cada frame só é renderizado quando chega o momento correto na timeline.
Se o processamento de um frame demora mais do que deveria, o sistema precisa compensar para não deixar o áudio sair de sincronia.
Na prática o player precisa equilibrar três coisas ao mesmo tempo:
- decodificação do vídeo
- renderização ASCII
- reprodução de áudio
Tudo acontecendo em paralelo.
Não é um player completo como VLC ou MPV, claro.
Mas já envolve vários problemas clássicos de sincronização audiovisual.
Balanceando qualidade e performance
Uma coisa que ficou muito clara durante o desenvolvimento é que existe um trade-off constante entre fidelidade visual e performance.
Quanto mais caracteres você usa para representar o frame, mais detalhada a imagem fica.
Mas também mais pesado fica renderizar.
Então o Kairo tenta encontrar um ponto de equilíbrio entre:
- densidade de caracteres
- tamanho do terminal
- velocidade de renderização
- FPS
Dependendo da máquina e do terminal, dá pra assistir vídeos surpreendentemente bem.
O que o Kairo pode fazer
Hoje o Kairo já consegue:
- reproduzir vídeos diretamente no terminal
- converter frames para ASCII em tempo real
- renderizar vídeo colorido usando ANSI 24-bit
- reproduzir áudio sincronizado com o vídeo
- ajustar densidade de caracteres
- controlar FPS
- adaptar a renderização ao tamanho do terminal
Também estou experimentando algumas coisas novas como:
- modo com emojis em vez de ASCII
- modos de render com mais fidelidade visual
- modo focado em performance
- diferentes ramps de caracteres para estilos visuais diferentes
A ideia é permitir que o usuário escolha entre qualidade visual ou velocidade, dependendo do terminal.
O objetivo nunca foi ser só meme
A parte mais engraçada do projeto é que ele começa como meme e aos poucos vira algo tecnicamente interessante.
Porque no fundo o Kairo toca em vários temas legais de engenharia:
- processamento de vídeo
- representação visual com restrições
- sincronização de áudio e vídeo
- renderização eficiente em terminal
- trade-offs entre qualidade e performance
- design de CLI
É o tipo de projeto que parece inútil por alguns segundos.
Até você abrir o código e perceber a quantidade de detalhe envolvida pra fazer a brincadeira funcionar direito.
No fim, era sobre isso
Eu gosto muito de projeto que faz alguém pensar:
"peraí… isso não deveria existir."
E logo depois:
"ok, mas isso aqui ficou bom."
O Kairo é exatamente esse tipo de projeto.
Não é a forma mais sensata de assistir vídeo.
Mas talvez seja uma das mais divertidas.
Se alguém quiser testar, olhar o código, sugerir melhorias ou contribuir, o projeto está aberto.