Files
rose-ash/artdag/test/templates/process-pair.sexp
giles 1a74d811f7
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m33s
Incorporate art-dag-mono repo into artdag/ subfolder
Merges full history from art-dag/mono.git into the monorepo
under the artdag/ directory. Contains: core (DAG engine),
l1 (Celery rendering server), l2 (ActivityPub registry),
common (shared templates/middleware), client (CLI), test (e2e).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

git-subtree-dir: artdag
git-subtree-mainline: 1a179de547
git-subtree-split: 4c2e716558
2026-02-27 09:07:23 +00:00

113 lines
4.4 KiB
Common Lisp

;; process-pair template
;;
;; Reusable video-pair processor: takes a single video source, creates two
;; clips (A and B) with opposite rotations and sporadic effects, blends them,
;; and applies a per-pair slow rotation driven by a beat scan.
;;
;; All sporadic triggers (invert, hue-shift, ascii) and pair-level controls
;; (blend opacity, rotation) are defined internally using seed offsets.
;;
;; Parameters:
;; video - source video node
;; energy - energy analysis node (drives rotation/zoom amounts)
;; beat-data - beat analysis node (drives sporadic triggers)
;; rng - RNG object from (make-rng seed) for auto-derived seeds
;; rot-dir - initial rotation direction: 1 (clockwise) or -1 (anti-clockwise)
;; rot-a/b - rotation ranges for clip A/B (e.g. [0 45])
;; zoom-a/b - zoom ranges for clip A/B (e.g. [1 1.5])
(deftemplate process-pair
(video energy beat-data rng rot-dir rot-a rot-b zoom-a zoom-b)
;; --- Sporadic triggers for clip A ---
;; Invert: 10% chance per beat, lasts 1-5 beats
(def inv-a (scan beat-data :rng rng :init 0
:step (if (> acc 0) (- acc 1) (if (< (rand) 0.1) (rand-int 1 5) 0))
:emit (if (> acc 0) 1 0)))
;; Hue shift: 10% chance, random hue 30-330 deg, lasts 1-5 beats
(def hue-a (scan beat-data :rng rng :init (dict :rem 0 :hue 0)
:step (if (> rem 0)
(dict :rem (- rem 1) :hue hue)
(if (< (rand) 0.1)
(dict :rem (rand-int 1 5) :hue (rand-range 30 330))
(dict :rem 0 :hue 0)))
:emit (if (> rem 0) hue 0)))
;; ASCII art: 5% chance, lasts 1-3 beats
(def ascii-a (scan beat-data :rng rng :init 0
:step (if (> acc 0) (- acc 1) (if (< (rand) 0.05) (rand-int 1 3) 0))
:emit (if (> acc 0) 1 0)))
;; --- Sporadic triggers for clip B (offset seeds) ---
(def inv-b (scan beat-data :rng rng :init 0
:step (if (> acc 0) (- acc 1) (if (< (rand) 0.1) (rand-int 1 5) 0))
:emit (if (> acc 0) 1 0)))
(def hue-b (scan beat-data :rng rng :init (dict :rem 0 :hue 0)
:step (if (> rem 0)
(dict :rem (- rem 1) :hue hue)
(if (< (rand) 0.1)
(dict :rem (rand-int 1 5) :hue (rand-range 30 330))
(dict :rem 0 :hue 0)))
:emit (if (> rem 0) hue 0)))
(def ascii-b (scan beat-data :rng rng :init 0
:step (if (> acc 0) (- acc 1) (if (< (rand) 0.05) (rand-int 1 3) 0))
:emit (if (> acc 0) 1 0)))
;; --- Pair-level controls ---
;; Internal A/B blend: randomly show A (0), both (0.5), or B (1), every 1-11 beats
(def pair-mix (scan beat-data :rng rng
:init (dict :rem 0 :opacity 0.5)
:step (if (> rem 0)
(dict :rem (- rem 1) :opacity opacity)
(dict :rem (rand-int 1 11) :opacity (* (rand-int 0 2) 0.5)))
:emit opacity))
;; Per-pair rotation: one full rotation every 20-30 beats, alternating direction
(def pair-rot (scan beat-data :rng rng
:init (dict :beat 0 :clen 25 :dir rot-dir :angle 0)
:step (if (< (+ beat 1) clen)
(dict :beat (+ beat 1) :clen clen :dir dir
:angle (+ angle (* dir (/ 360 clen))))
(dict :beat 0 :clen (rand-int 20 30) :dir (* dir -1)
:angle angle))
:emit angle))
;; --- Clip A processing ---
(def clip-a (-> video (segment :start 0 :duration (bind energy duration))))
(def rotated-a (-> clip-a
(effect rotate :angle (bind energy values :range rot-a))
(effect zoom :amount (bind energy values :range zoom-a))
(effect invert :amount (bind inv-a values))
(effect hue_shift :degrees (bind hue-a values))
;; ASCII disabled - too slow without GPU
;; (effect ascii_art
;; :char_size (bind energy values :range [4 32])
;; :mix (bind ascii-a values))
))
;; --- Clip B processing ---
(def clip-b (-> video (segment :start 0 :duration (bind energy duration))))
(def rotated-b (-> clip-b
(effect rotate :angle (bind energy values :range rot-b))
(effect zoom :amount (bind energy values :range zoom-b))
(effect invert :amount (bind inv-b values))
(effect hue_shift :degrees (bind hue-b values))
;; ASCII disabled - too slow without GPU
;; (effect ascii_art
;; :char_size (bind energy values :range [4 32])
;; :mix (bind ascii-b values))
))
;; --- Blend A+B and apply pair rotation ---
(-> rotated-a
(effect blend rotated-b
:mode "alpha" :opacity (bind pair-mix values) :resize_mode "fit")
(effect rotate
:angle (bind pair-rot values))))