
La premisa
TouchDesigner es un entorno de programación visual. Arrastras nodos, los conectas con cables y sale video en tiempo real. Es la herramienta estándar para instalaciones inmersivas, VJing y arte generativo. Y su interfaz principal es eso: visual. Ratón, cables, parámetros, preview en vivo.
Pero TouchDesigner tiene un secreto que casi nadie explota: toda la interfaz es scripteable en Python. Cada nodo que puedes crear con el mouse lo puedes crear con base.create(noiseTOP, 'nombre'). Cada cable que conectas a mano lo puedes conectar con inputConnectors[0].connect(otro_nodo). Cada parámetro tiene su .par.
Eso significa que una red completa de TouchDesigner se puede describir como texto. Y si se puede describir como texto, un LLM puede generarla.
El experimento
El proyecto vive en un repo que conecta Claude Code con la API de scripting de TD. La idea es simple: le describes en lenguaje natural qué visualización quieres, el agente genera un script Python que crea la red completa de operadores, y tú pegas ese script en un Script DAT dentro de TouchDesigner. Ctrl+Enter. La red aparece.
No es un plugin de TouchDesigner. No es una integración en tiempo real. Es algo más crudo y más interesante: un LLM que escribe el código que construye el instrumento visual.
El primer test fue un hello world. Ruido de Perlin animado, un texto encima, un composite, un null de output. Cuatro nodos. Nada espectacular. Pero cuando lo pegué en TD y la red se materializó exacta, con los nodos posicionados donde el script decía que debían estar, entendí que el concepto funcionaba.
Después vinieron los templates reales.
Tres visualizadores, cero nodos manuales
El repo tiene tres templates que cubren tres paradigmas distintos de visualización de audio.
El primero es un espectro FFT en 3D. El script crea un pipeline de análisis de audio: audiodevInCHOP capturando desde Soundcollider vía dispositivo virtual, audiospectrumCHOP separando 32 bandas de frecuencia, un mathCHOP escalando amplitudes, un lagCHOP suavizando la animación. Después monta la geometría: un boxSOP como barra base, instancing para clonarla 32 veces, un material PBR con metallic y roughness, cámara, luz, render, bloom, feedback, composite, null de salida. MIDI entra por otro brazo: midiinCHOP, selectCHOP para filtrar CC1 y CC2, mathCHOP para normalizar de 0-127 a 0-1. CC1 controla la altura de las barras. CC2 el color.
Son 18 nodos creados programáticamente. Conectados. Parametrizados. Posicionados en el canvas con coordenadas nodex/nodey para que la red sea legible cuando la abres.
El segundo template es un campo de 50,000 partículas. Acá la arquitectura de audio se bifurca: en lugar de FFT, el script separa tres bandas con audiofilterCHOP. Lowpass a 200 Hz para el kick, bandpass 200-2000 Hz para el snare, highpass a 2000 Hz para el hihat. Cada banda pasa por un audioRMSCHOP para sacar energía. El kick además pasa por un triggerCHOP para detección de beat con threshold y atenuación configurados. Las tres bandas se fusionan en un mergeCHOP y se renombran a canales claros: kick, mid, high.
La parte visual: una esfera SOP como emisor, conversión a CHOP para acceder a posiciones XYZ, un campo de ruido que se modula con la energía de los highs, suma de posiciones base más turbulencia. El resultado alimenta un geoCOMP con instancing. 50,000 puntos moviéndose en el espacio, cada uno respondiendo al audio. Render oscuro, bloom intenso, feedback para trails.
El tercero es el más técnico: un shader GLSL custom. El script no solo crea nodos sino que escribe código GLSL completo dentro de un textDAT. El fragment shader recibe el waveform crudo del audio como textura 1D (1024 samples vía trailCHOP convertido a choptoTOP), dibuja la onda con tres capas de grosor distinto (línea fina de detalle, línea principal, glow difuso), aplica un efecto de espejo vertical, distorsión UV reactiva al audio, gradiente de fondo que respira con la energía, y un feedback loop donde el shader lee su propio frame anterior para generar trails.
Los colores cambian con la energía: cyan en reposo, blanco en picos, naranja cuando el waveform satura. El MIDI controla dos uniforms: CC74 ajusta la intensidad del feedback (mapeado a un rango útil de 0.8 a 0.98 para que nunca se apague ni se sature), CC1 controla la distorsión. Los uniforms se actualizan vía un chopexecuteDAT que escucha cambios en el CHOP de MIDI y los pasa al glslTOP.
Lo que esto dice sobre code-as-art
Hay una tradición larga de arte generado por código. Processing, openFrameworks, Cinder, los live coders de TOPLAP que programan sintetizadores en vivo. En todos esos casos, el artista escribe el código. El código es el medio pero la intención es humana en cada línea.
Acá la situación es distinta. Le dices al modelo “crea un visualizador de espectro con 64 bandas en forma de círculo, estética oscura con colores neón” y el modelo decide la arquitectura: qué nodos usar, cómo conectarlos, qué parámetros setear, cómo posicionarlos. El modelo tiene que entender simultáneamente la semántica visual (qué aspecto debería tener), la arquitectura de señal (cómo fluyen los datos de audio a través de la red) y la API de scripting de TD (qué clases existen, qué parámetros aceptan, cómo se conectan).
Lo interesante no es que el modelo pueda hacer esto. Lo interesante es que el resultado es código que a su vez genera una herramienta visual que a su vez genera imágenes en tiempo real. Son tres capas de abstracción entre la intención y el pixel.
El modo interactivo del agente lleva esto un paso más allá. Puedes iterar conversacionalmente: “base: campo de puntos oscuro”, “añade reactividad al kick”, “ahora agrega aberración cromática de post-procesado”, “el MIDI CC1 controla la intensidad”. Cada instrucción modifica o extiende la red. Es como pair programming con un artista visual que entiende DSP.
La estructura que hace posible esto
Cada script sigue un patrón modular que el modelo aprendió a replicar:
setup_audio_*() → Captura y análisis de audio
setup_midi_*() → Entrada MIDI normalizada
setup_visuals() → Red de geometría/shader/render
setup_render_*() → Cámara, luces, post-procesado, output
main() → Orquesta todo usando root como base
La convención de nombres es estricta. Audio input siempre se llama audio_in. MIDI input siempre midi_in. Output final siempre OUT, un nullTOP con .viewer = True. Canales MIDI normalizados se nombran cc1, cc2, cc74. Bandas de audio: kick, mid, high.
Esa rigidez no es capricho. Es lo que permite que el modelo genere redes compatibles entre sí, que puedas componer templates, que un script nuevo se conecte a la misma fuente de audio que otro.
Lo que falta
El agente todavía no puede ver el resultado. No tiene feedback visual de lo que generó. Escribe el código, tú lo ejecutas, y si algo no se ve bien, le describes el problema en texto. Eso limita la iteración a un loop humano-en-el-medio.
El siguiente paso lógico sería capturar un frame del output de TD, pasárselo al modelo como imagen, y dejar que ajuste parámetros basándose en lo que ve. Un loop cerrado donde el modelo genera, observa y corrige. Eso convertiría al agente de un constructor ciego en algo más parecido a un artista que mira su lienzo.
Otra limitación: los scripts se ejecutan una vez. Crean la red estática. No hay un runtime donde el modelo pueda intervenir en tiempo real, modificando parámetros frame a frame. TD tiene la infraestructura para eso (todo es live, todo es scripteable en cada frame), pero el overhead de llamar a un LLM 60 veces por segundo es absurdo con la latencia actual.
Por qué importa
No porque vaya a reemplazar a los artistas visuales. Sino porque abre una pregunta que antes no existía: ¿qué pasa cuando la barrera de entrada al arte generativo en tiempo real se reduce a una conversación?
TouchDesigner tiene una curva de aprendizaje pronunciada. Entender qué es un CHOP vs un TOP vs un SOP, cómo fluyen los datos, qué nodos existen, cómo se parametrizan. Toma meses. Este agente no elimina esa complejidad pero la oculta detrás de una interfaz de lenguaje natural. Un músico que no sabe programar puede decir “quiero que mis kicks generen explosiones de partículas” y obtener un script funcional.
El código fuente de la pieza visual no lo escribió un humano. Pero la intención, la dirección estética, la decisión de qué sonido mueve qué pixel, eso sigue siendo nuestro.
Por ahora.