Livecoding відеосинт у браузері · hydra.ojack.xyz · клік по коду = копія
osc(6, 0.05, 0.8).out()noise(3, 0.1).out()voronoi(5, 0.3, 0.3).out()shape(4, 0.3, 0.05).out()gradient(0.3).out()solid(1, 0, 0.4, 1).out()src(o0).out(o1)osc(10).rotate(0.5, 0.1).out()shape(4).scale(1.5, 0.5).out()noise(3).pixelate(20, 20).out()osc(9,0.1,1).kaleid(6).out()shape(4,0.2).repeat(3,3).out()osc(10).scrollX(0,0.1).out()osc(20).color(1,0.4,0.8).out()osc(30,0,1).hue(0.3).out()osc(10,0,1).saturate(3).out()noise(2).colorama(0.1).out()noise(3).posterize(3,0.6).out()noise(3).thresh(0.5,0.04).out()osc(10).invert(1).out()noise(3).contrast(2).out()osc(10).brightness(0.2).out()osc(10,0,1).luma(0.5,0.1).out()noise(2).shift(0.1,0.3,0.6).out()osc(9).add(noise(3), 0.5).out()osc(9).mult(shape(4)).out()osc(9).blend(noise(2),0.5).out()osc(9).diff(osc(13)).out()osc(9).layer(shape(4).luma()).out()osc(30).mask(shape(4,0.5)).out()osc(4).modulate(noise(3),0.5).out()voronoi(5).modulateScale(osc(4),0.5).out()osc(10).modulateRotate(osc(3),1).out()noise(3).modulatePixelate(noise(2),20).out()osc(9).modulateKaleid(osc(2),4).out()shape(4).modulateRepeat(osc(3),3,3).out().out() без аргументу — тоді кросфейд між евалами працює.
Явні .out(o1) / .out(o2) / .out(o3) цей ефект обходять — беріть їх лише тоді, коли справді потрібен named-буфер (напр. src(o0).diff(o1)).
Виняток — фідбек на самого себе: .out(o0) у парі з src(o0) лишається робочим.
osc(10).out(o1)render() // o0..o3osc(40,0,1).modulate(o0,0.04).out(o0)osc(10).rotate(()=>a.fft[0]*2).out()a.setBins(6)a.setSmooth(0.9)a.setCutoff(4); a.setScale(8)a.show()s0.initCam(); src(s0).out()s0.initVideo("video.mp4"); src(s0).out()s0.initImage("img.jpg"); src(s0).out()s0.initScreen(); src(s0).out()initVideo("https://youtube.com/watch?v=…"), ні через iframe-embed. Це не недоробка Hydra і не питання правильного прапорця: так влаштований браузер.
s0.initScreen(), обери ту вкладку у вікні браузера — і вона стає живою текстурою.
s0.initScreen()
src(s0).out()initVideo() кладе URL у <video>-елемент. Сторінка youtube.com/watch — це HTML-документ, а не медіафайл; <video> його просто не програє.
googlevideo.com — підписані, живуть кілька хвилин, прив’язані до сесії і не віддають CORS-заголовків. Навіть якщо висмикнути такий URL, Hydra ставить crossOrigin = "anonymous", і текстура повернеться чорною.
s0.initScreen()
src(s0).out()s0.initScreen()
src(s0)
.scale(1.1)
.saturate(1.3)
.contrast(1.2)
.out()s0.initScreen()
src(s0)
.modulate(noise(3), 0.15)
.out()a.setBins(4)
s0.initScreen()
src(s0)
.modulate(noise(2), () => a.fft[0] * 0.4)
.scale(() => 1 + a.fft[0] * 0.2)
.out()s0.initScreen()
src(s0)
.diff(src(s0).kaleid(6).rotate(() => time * 0.1))
.contrast(1.3)
.out()s0.initScreen()
osc(20, 0.1, 1)
.modulateKaleid(src(s0), 3)
.mask(src(s0).luma(0.35, 0.1))
.out()https. На LAN піднімай через ./flok-lan.sh --secure (Linux/macOS) або .\flok-lan.ps1 -Secure (Windows). По голому http:// на LAN-адресу браузер getDisplayMedia просто не дасть.
a.fft та Strudel не потрапляє. Хочеш реактивність — лови звук мікрофоном (a.setBins(…)) або керуй з боку Strudel.
initScreen(index) у браузері ігнорується — у вихідниках він позначений як актуальний лише для десктопних збірок. Вікно все одно обирається в діалозі.
flokvid. Він тягне ролик через yt-dlp, перекодовує в H.264 + faststart (браузери тихо відмовляються текстурити частину VP9/AV1-файлів), кладе у /root/cdn/flok/media/ і друкує готовий Hydra-сніпет.
Ця директорія віддається з Access-Control-Allow-Origin: * — без цього заголовка текстура була б чорною.
flokvid <url> [name] [--start HH:MM:SS] [--dur SECONDS] [--height 720]
flokvid --list
flokvid --rm <name>flokvid https://example.com/clip.mp4 mycut \
--start 00:01:30 --dur 15 --height 720s0.initVideo("https://mandrock-files.duckdns.org/flok/media/mycut.mp4")
src(s0).out()ERROR: [vimeo] …: Failed to fetch macos OAuth token: HTTP Error 401: Unauthorized
yt-dlp розв’язує JS-челендж через встановлений deno. Але це хитка рівновага: у логах видно Signature solving failed / n challenge solving failed, тож качається не найкращий формат, і YouTube будь-коли може почати віддавати
ERROR: … Sign in to confirm you're not a bot
yt-dlp --cookies / --cookies-from-browser), або завантажити ролик на своїй машині (домашня IP таких перевірок не ловить) і залити результат у /root/cdn/flok/media/.
flokvid працює без застережень.
initVideo() сама виставляє muted, loop, autoplay і викликає play(), тож ролик крутиться по колу без звуку — типово робити нічого не треба.
Якщо стоїть на першому кадрі — дотягнись до самого елемента через s0.src (це і є той <video>). Увага: s0.src — null, поки не спрацював loadeddata, тож роби це окремим евалом.
s0.src.loop = true
s0.src.muted = true
s0.src.play()s0.src.playbackRate = 0.5 // вповільнити
s0.src.currentTime = 12 // перемотати на 12 с
s0.src.pause() // стоп-кадрs0.initCam()
src(s0).kaleid(4).out()s0.initImage("https://mandrock-files.duckdns.org/flok/media/img.jpg")
src(s0).modulate(noise(2), 0.1).out()initCam(), як і initScreen(), потребує secure context — тобто https або localhost.
initImage() теж ставить crossOrigin = "anonymous", тож картинка мусить віддаватися з CORS — /flok/media/ для цього вже налаштована.
osc(()=>10+Math.sin(time)*5).out()shape(4).rotate(()=>time*0.2).out()osc([10,40,80]).out()osc([10,40,80].fast(2).smooth()).out()osc(()=>mouse.x*0.1).out()hush()speed = 2; bpm = 60setResolution(1920,1080)update = (dt)=>{ /* logic */ }osc(10,0.1,1.2)
.rotate(0.5)
.kaleid(4)
.out()osc(4,0.1,1.2)
.modulate(noise(3), 0.4)
.colorama(0.1)
.out()osc(40,0,1)
.modulate(o0, 0.04)
.out(o0)a.setBins(4)
voronoi(5,0.3)
.modulateScale(osc(4), ()=>a.fft[0])
.out()shape(4,0.3)
.repeat(3,3)
.rotate(()=>time*0.1)
.thresh(0.5,0.04)
.out()osc(10).out(o0)
noise(3).rotate(1).out(o1)
src(o0).diff(o1).out(o2)
render()a.setBins(4)
shape(4,0.3)
.scale(()=>1 + a.fft[0]*0.7)
.out()a.setBins(4)
osc(8,0.1,1)
.kaleid(5)
.rotate(()=>a.fft[0]*3)
.out()a.setBins(3)
osc(20,0.1)
.color(()=>a.fft[0], ()=>a.fft[1], ()=>a.fft[2])
.out()a.setBins(4)
a.setSmooth(0.6)
noise(2)
.pixelate(()=>2+a.fft[3]*50, ()=>2+a.fft[3]*50)
.out()a.setBins(4)
a.setCutoff(2); a.setScale(6)
voronoi(8,0.2)
.brightness(()=>a.fft[0]-0.2)
.thresh(0.4)
.out()a.setBins(4)
src(o0)
.modulate(noise(2), ()=>a.fft[0]*0.1)
.scale(1.01)
.layer(osc(30,0.1,1).mask(shape(4,0.3)))
.out(o0)strudel, hydra). Нічого ставити не треба.
await initHydra()
osc(10, 0.1, 1.2).kaleid(4).out()
$: s("bd*4, ~ cp").bank("RolandTR909")await initHydra({ detectAudio: true })
osc(30)
.modulate(noise(3), ()=>a.fft[0])
.out()await initHydra()
osc(20)
.rotate(H("<0 0.5 1>"))
.out()await initHydra({ feedStrudel: true })
src(s0).kaleid(4).modulate(noise(2)).out()
$: note("c e g b").s("piano")// hydra-таргет у flok, синхронно з часом Strudel
shape(4)
.scale(() => P("<1 2 3>"))
.out()// hydra-таргет
p5.background(0)
p5.fill(255)
p5.circle(p5.width/2, p5.height/2, 200)a.fft, кожну Strudel-панель треба один раз перееваліти вручну (Ctrl+Enter) — інакше дані спектра не підхопляться.