Código, Música e ChatGPT

Feb 12 2023
Construindo um site visualizador de forma de onda de som simples com ChatGPT
A imagem acima é uma captura de tela de um site criado com o ChatGPT. A transcrição completa do ChatGPT está aqui.

A imagem acima é uma captura de tela de um site criado com o ChatGPT. A transcrição completa do ChatGPT está aqui . O código resultante está no github . A faixa de música representada é Transmission de Eelke Kleijn .

A aplicação

  • Você arrasta e solta um arquivo MP3 na caixa.
  • O arquivo é carregado e uma tarefa assíncrona em segundo plano é colocada na fila. O front-end verifica continuamente o status do trabalho até que seja concluído (ou falhe).
  • Quando a tarefa é processada, o MP3 é analisado e uma matriz de dados de forma de onda é enviada ao cliente. Há uma forma de onda separada para agudos e médios graves (semelhante ao software de DJ).
  • O cliente, ao receber a matriz de dados da forma de onda, visualiza os dados em uma Tela HTML.
  • É uma tarefa de engenharia de software não trivial : há um front-end, que precisa ter uma aparência decente. Há um back-end, que lida com tarefas assíncronas e processamento de som.
  • Requer várias bibliotecas de terceiros e descobrir como elas funcionam.
  • Conhecimento interdisciplinar é necessário : você precisa ler o mp3, executar uma transformada de Fourier e dividir corretamente as faixas de frequência.

Ao longo da construção do aplicativo, nós (ChatGPT e eu) fizemos pequenas iterações e testamos o que tínhamos em cada etapa. As citações da transcrição abaixo são links para as linhas correspondentes na transcrição.

Um front-end básico

Escreva o front-end de um site onde os usuários carregam um mp3 arrastando e soltando. o mp3 é carregado no back-end para processamento assíncrono e a interface do usuário exibe atualizações de status no status do trabalho (em fila/processamento/concluído).

O ChatGPT chegou a um resultado razoável com apenas algumas iterações.

ok, agora reescreva a seção para usar pure.css e escreva um pouco de css para deixar a página mais bonita

Isso também foi fácil.

o back-end

Ok, agora escreva um aplicativo em node.js/express que atenda à página da Web acima e, adicionalmente, despache tarefas que processam os mp3s carregados. Por enquanto, o processamento deve ser um trabalho fictício que simplesmente é concluído em 5 segundos.

Isso estava funcionando imediatamente. Adicionamos iterativamente mais funcionalidades ao trabalho :

ótimo, agora faça o script acima calcular a duração do mp3 nas tarefas

Isso foi rápido. Então começaram os problemas:

perfeito, agora altere o processMp3, para que ele retorne um objeto de análise de trilha. Deve ficar assim :
{
duração: <duração da música em segundos>,
forma de onda: [{
graves: <um valor de 0 a 100 indicando o volume das baixas frequências neste intervalo>,
médios: <um valor de 0 a 100 indicando o volume das frequências médias neste intervalo>,
altos: <um valor de 0 a 100 indicando o volume das frequências altas neste intervalo>,
}, … ]}

(a matriz de forma de onda no objeto deve ter 512 baldes.)

Para fazer a transformada de Fourier necessária, o ChatGPT tentou usar bibliotecas que presumiam a existência de um windowobjeto global, indicando que eram destinadas ao uso de front-end.

estas são bibliotecas de front-end, elas não funcionam no back-end, use outra coisa

Ele sugeriu o uso de pydub, que é uma biblioteca python, e produziu um código que tenta usar pydub em javascript — o que obviamente não funciona. Aí começou a inventar coisas:

ChatGPT: Nesse caso, você pode usar a biblioteca de áudio para realizar a análise de áudio e gerar a forma de onda .

Em seguida, produziu um trecho de código que usa uma biblioteca de áudio inventada que não existe ou não pode ser usada dessa forma. Ele rapidamente admitiu seu erro:

Eu: não existe tal pacote npm

ChatGPT : Peço desculpas, você está correto. Não há biblioteca de áudio no npm. Nesse caso, você pode usar a biblioteca de transformada de Fourier para realizar a análise de áudio e gerar a forma de onda.

Em seguida, produziu um trecho de código que faz sentido — exceto que usou uma função que não foi definida:

let audio = await decode(audioData);

import { MP3Decoder } from "lamejs";

Desculpe, mas o processamento de áudio no lado do servidor é bastante complexo, especialmente sem o uso de uma biblioteca pré-existente. Eu recomendo usar uma biblioteca pré-existente, como ffmpeg, sox ou libsndfile, que fornece uma API de alto nível para processamento de áudio. Essas bibliotecas podem ser usadas para extrair os dados de áudio do arquivo MP3, processar os dados de áudio para determinar a duração e o volume do áudio e gerar os dados da forma de onda.

Quando pressionado mais, o ChatGPT continuou apresentando desculpas e maneiras de evitar escrever a parte com a qual claramente estava lutando.

Claramente era hora de dar um passo para trás. Pedi ao ChatGPT para escrever o programa em python , torná-lo saída para stdout e executá-lo a partir do script node.js. Isso funcionou bem e produziu o seguinte código:

import numpy as np
import matplotlib.pyplot as plt
from pydub import AudioSegment

def process_mp3(mp3_path):
    audio = AudioSegment.from_file(mp3_path, format="mp3")
    samples = np.array(audio.get_array_of_samples())
    duration = len(audio) / 1000
    sample_rate = audio.frame_rate
    num_samples = len(samples)
    num_buckets = 512
    bucket_size = num_samples // num_buckets

    waveform = []
    for i in range(num_buckets):
        start = i * bucket_size
        end = start + bucket_size
        bucket_samples = samples[start:end]
        
        fft = np.fft.rfft(bucket_samples)
        fft = np.abs(fft)

        low_freq = int(sample_rate * 0.05)
        mid_freq = int(sample_rate * 0.5)
        high_freq = int(sample_rate * 0.95)

        lows = np.mean(fft[:low_freq])
        mids = np.mean(fft[low_freq:mid_freq])
        highs = np.mean(fft[mid_freq:high_freq])

        waveform.append({
            "lows": lows,
            "mids": mids,
            "highs": highs
        })

    return {
        "duration": duration,
        "waveform": waveform
    }

if __name__ == "__main__":
    mp3_path = sys.argv[1]
    waveform_data = process_mp3(mp3_path)
    print(json.dumps(waveform_data))

Escrever o código para plotar os dados da forma de onda não foi difícil, mas exigiu algumas iterações e alguma depuração assistida pelo ChatGPT. Em algum momento, mostrei ao ChatGPT um trecho dos dados da forma de onda para ajudá-lo a corrigir seu código .

O Arquiteto e o Macaco do Código

Observei uma interessante separação de tarefas durante esse processo:

  • Atuei como arquiteto de software : decidi o que construir e tomei decisões sobre o design geral. Dividi o aplicativo em pequenas partes que podem ser construídas de forma incremental. Eu indiquei questões de segurança. Eu fiz o teste.
  • O ChatGPT agiu como um macaco de código : funcionou bem nas partes chatas: escrever o código real, depurar e decidir quais bibliotecas usar.

Passei algum tempo tentando fazer com que o ChatGPT também atuasse como o arquiteto de software, fazendo-o usar outra instância de si mesmo como um macaco de código. Até agora, não tive sucesso, mas é isso que estou tentando:

Nesta conversa, você desempenhará o papel de arquiteto de software construindo um programa com ChatGPT, uma IA de codificação. Você pode interagir apenas com dois agentes:
* ChatGPT, anexando suas respostas com CHATGPT:
* Um terminal unix, anexando suas respostas comTERMINAL:

Todas as suas mensagens, sem exceções, devem ser precedidas por CHATGPT:ou TERMINAL:. Não saia do personagem. Não faça perguntas esclarecedoras - em vez disso, use suas melhores suposições. Vou responder às suas mensagens, fingindo ser o ChatGPT ou o terminal.

Como arquiteto de software, você é bom em design de sistema de alto nível, mas deseja delegar as partes mais chatas de escrever software (escrever o código real) para chatgpt. No entanto, o ChatGPT não é bom para lidar com projetos complexos, então você terá que dividir o projeto em pequenas tarefas específicas. O ChatGPT também comete erros, então você é encorajado a testar o código que ele fornece.

Darei um exemplo de uma conversa que você poderia ter, se quisesse criar um aplicativo que imprima hello world na saída padrão:

— —
> CHATGPT: Escreva um programa em C++ que imprima "Hello, world!".
> Ok, aqui está o seu programa:

#include<cstdio> int main() { printf("Olá, mundo"); retorna 0; }

> TERMINAL: mkdir olá-mundo && cd olá-mundo && echo “#include<cstdio> int main() { printf(\”Olá, mundo\”); retorna 0; }” > prog.cpp && g++ prog.cpp && ./a.out
> Olá, mundo!
——

OK. Agora crie um aplicativo que imprima “Hello, world, again!” usando chatgpt, como acima.