;; ASCII with Alternating Rotation Directions ;; ;; Checkerboard pattern: even cells rotate clockwise, odd cells rotate counter-clockwise ;; Rotation amount scaled by energy and position (more at top-right) (recipe "ascii_alternating_rotate" :version "1.0" :description "ASCII art with alternating rotation directions per cell" :minimal-primitives true :encoding (:codec "libx264" :crf 20 :preset "medium" :audio-codec "aac" :fps 30) :params ( (cols :type int :default 50 :range [20 100] :desc "Number of character columns") (rotation_scale :type float :default 60 :range [0 180] :desc "Max rotation in degrees") (duration :type float :default 10 :range [1 300] :desc "Clip duration in seconds") ) ;; Registry (effect ascii_fx_zone :path "../sexp_effects/effects/ascii_fx_zone.sexp") ;; Effects used in cell_effect lambda (effect rotate :path "../sexp_effects/effects/rotate.sexp") (analyzer energy :path "../../artdag-analyzers/energy/analyzer.py") ;; Source files (def video (source :path "../monday.webm")) (def audio (source :path "../dizzy.mp3")) ;; Stage 1: Analysis (stage :analyze :outputs [energy-data] (def audio-clip (-> audio (segment :start 60 :duration duration))) (def energy-data (-> audio-clip (analyze energy)))) ;; Stage 2: Process (stage :process :requires [:analyze] :inputs [energy-data] :outputs [result audio-clip] (def clip (-> video (segment :start 0 :duration duration))) (def audio-clip (-> audio (segment :start 60 :duration duration))) (def result (-> clip (effect ascii_fx_zone :cols cols :char_size (bind energy-data values :range [10 20]) :color_mode "color" :background "black" :energy (bind energy-data values :range [0 1]) :rotation_scale rotation_scale ;; Alternating rotation: even cells clockwise, odd cells counter-clockwise ;; Scaled by energy * position (more at top-right) :cell_effect (lambda [cell zone] (rotate cell (* (if (= (mod (+ (get zone "row") (get zone "col")) 2) 0) 1 -1) (* (get zone "energy") (get zone "rotation_scale") (* 1.5 (+ (get zone "col-norm") (- 1 (get zone "row-norm")))))))))))) ;; Stage 3: Output (stage :output :requires [:process] :inputs [result audio-clip] (mux result audio-clip)))