;; All Effects Showcase ;; Cycles through every sexp effect on beat, using entire audio (recipe "all-effects-showcase" :version "1.0" :encoding (:codec "libx264" :crf 20 :preset "medium" :audio-codec "aac" :fps 30) ;; Analyzers (analyzer beats :path "../artdag-analyzers/beats/analyzer.py") (analyzer bass :path "../artdag-analyzers/bass/analyzer.py") (analyzer energy :path "../artdag-analyzers/energy/analyzer.py") ;; All sexp effects (effect ascii_art :path "sexp_effects/effects/ascii_art.sexp") (effect ascii_zones :path "sexp_effects/effects/ascii_zones.sexp") (effect datamosh :path "sexp_effects/effects/datamosh.sexp") (effect pixelsort :path "sexp_effects/effects/pixelsort.sexp") (effect bloom :path "sexp_effects/effects/bloom.sexp") (effect blur :path "sexp_effects/effects/blur.sexp") (effect brightness :path "sexp_effects/effects/brightness.sexp") (effect color-adjust :path "sexp_effects/effects/color-adjust.sexp") (effect color_cycle :path "sexp_effects/effects/color_cycle.sexp") (effect contrast :path "sexp_effects/effects/contrast.sexp") (effect crt :path "sexp_effects/effects/crt.sexp") (effect echo :path "sexp_effects/effects/echo.sexp") (effect edge_detect :path "sexp_effects/effects/edge_detect.sexp") (effect emboss :path "sexp_effects/effects/emboss.sexp") (effect film_grain :path "sexp_effects/effects/film_grain.sexp") (effect fisheye :path "sexp_effects/effects/fisheye.sexp") (effect flip :path "sexp_effects/effects/flip.sexp") (effect grayscale :path "sexp_effects/effects/grayscale.sexp") (effect hue_shift :path "sexp_effects/effects/hue_shift.sexp") (effect invert :path "sexp_effects/effects/invert.sexp") (effect kaleidoscope :path "sexp_effects/effects/kaleidoscope.sexp") (effect mirror :path "sexp_effects/effects/mirror.sexp") (effect neon_glow :path "sexp_effects/effects/neon_glow.sexp") (effect noise :path "sexp_effects/effects/noise.sexp") (effect outline :path "sexp_effects/effects/outline.sexp") (effect pixelate :path "sexp_effects/effects/pixelate.sexp") (effect posterize :path "sexp_effects/effects/posterize.sexp") (effect rgb_split :path "sexp_effects/effects/rgb_split.sexp") (effect ripple :path "sexp_effects/effects/ripple.sexp") (effect rotate :path "sexp_effects/effects/rotate.sexp") (effect saturation :path "sexp_effects/effects/saturation.sexp") (effect scanlines :path "sexp_effects/effects/scanlines.sexp") (effect sepia :path "sexp_effects/effects/sepia.sexp") (effect sharpen :path "sexp_effects/effects/sharpen.sexp") (effect strobe :path "sexp_effects/effects/strobe.sexp") (effect swirl :path "sexp_effects/effects/swirl.sexp") (effect threshold :path "sexp_effects/effects/threshold.sexp") (effect tile_grid :path "sexp_effects/effects/tile_grid.sexp") (effect trails :path "sexp_effects/effects/trails.sexp") (effect vignette :path "sexp_effects/effects/vignette.sexp") (effect wave :path "sexp_effects/effects/wave.sexp") (effect zoom :path "sexp_effects/effects/zoom.sexp") ;; Constructs (construct slice-every-n :path "constructs/slice-every-n.sexp") ;; Sources with durations (seconds) (def video-a (source :path "monday.webm")) (def video-a-duration 30) ;; adjust to actual duration (def video-b (source :path "new.webm")) (def video-b-duration 60) ;; adjust to actual duration (def video-c (source :path "ecstacy.mp4")) (def video-c-duration 45) ;; adjust to actual duration ;; Video list with durations for easy lookup (def videos (list video-a video-b video-c)) (def video-durations (list video-a-duration video-b-duration video-c-duration)) ;; Audio - entire file (def audio (source :path "dizzy.mp3")) ;; Analysis (def beats-data (-> audio (analyze beats))) (def bass-data (-> audio (analyze bass))) (def energy-data (-> audio (analyze energy))) ;; Group every 21 beats into one segment (~42 segments for this track) (def beats-per-seg 21) ;; Slice into segments, one effect each ;; Wraps video start time; skips if segment longer than all videos (def segments (slice-every-n beats-data beats-per-seg :init 0 :reducer (fn [acc i start end] (let [seg-duration (- end start) ;; Try preferred video first, then others vid-idx (mod acc 3) ;; Find a video long enough for this segment valid-vid-idx (cond (>= (nth video-durations vid-idx) seg-duration) vid-idx (>= (nth video-durations (mod (+ vid-idx 1) 3)) seg-duration) (mod (+ vid-idx 1) 3) (>= (nth video-durations (mod (+ vid-idx 2) 3)) seg-duration) (mod (+ vid-idx 2) 3) :else nil)] ;; Skip if no video is long enough (if (= valid-vid-idx nil) {:skip true :acc (inc acc)} (let [src (nth videos valid-vid-idx) src-duration (nth video-durations valid-vid-idx) ;; Wrap start time within video duration wrapped-start (mod start src-duration) effect-idx (mod acc 42) fx (cond ;; Color effects 0-9 - DRAMATIC ranges for visible music reactivity (= effect-idx 0) {:effect invert} (= effect-idx 1) {:effect grayscale} (= effect-idx 2) {:effect sepia} (= effect-idx 3) {:effect brightness :amount (bind bass values :range [-80 80])} (= effect-idx 4) {:effect contrast :amount (bind energy values :range [0.5 2.5])} (= effect-idx 5) {:effect saturation :amount (bind bass values :range [0.2 3.0])} (= effect-idx 6) {:effect hue_shift :degrees (bind energy values :range [0 360])} (= effect-idx 7) {:effect color_cycle :speed 2} (= effect-idx 8) {:effect threshold :level 128} (= effect-idx 9) {:effect posterize :levels 6} ;; Blur/sharpen 10-13 - wider ranges (= effect-idx 10) {:effect blur :radius (bind bass values :range [1 30])} (= effect-idx 11) {:effect sharpen :amount (bind energy values :range [0.5 4])} (= effect-idx 12) {:effect bloom :intensity 0.6 :radius 20} (= effect-idx 13) {:effect color-adjust :brightness 20 :contrast 1.2} ;; Distortion 14-21 - much more dramatic (= effect-idx 14) {:effect swirl :strength (bind bass values :range [-6 6])} (= effect-idx 15) {:effect fisheye :strength (bind bass values :range [-0.5 0.8])} (= effect-idx 16) {:effect wave :amplitude (bind bass values :range [10 60]) :wavelength 60} (= effect-idx 17) {:effect ripple :amplitude (bind bass values :range [10 40]) :frequency 6} (= effect-idx 18) {:effect kaleidoscope :segments 6 :rotation_speed 30} (= effect-idx 19) {:effect zoom :factor (bind bass values :range [0.8 1.5])} (= effect-idx 20) {:effect rotate :angle (bind energy values :range [-30 30])} (= effect-idx 21) {:effect mirror :direction "horizontal"} ;; Stylization 22-28 - more variation (= effect-idx 22) {:effect pixelate :block_size (bind bass values :range [4 32])} (= effect-idx 23) {:effect ascii_art :char_size 8 :color_mode "color"} (= effect-idx 24) {:effect ascii_zones :char_size 10} (= effect-idx 25) {:effect edge_detect :low 50 :high 150} (= effect-idx 26) {:effect emboss :strength 1.5} (= effect-idx 27) {:effect outline :thickness 2} (= effect-idx 28) {:effect neon_glow :glow_radius 20 :glow_intensity 2} ;; Retro/film 29-33 (= effect-idx 29) {:effect crt :line_spacing 3 :vignette_amount 0.3} (= effect-idx 30) {:effect scanlines :spacing 3 :intensity 0.4} (= effect-idx 31) {:effect film_grain :intensity 0.25} (= effect-idx 32) {:effect vignette :strength 0.6} (= effect-idx 33) {:effect noise :amount (bind bass values :range [10 80])} ;; Chromatic 34 - bigger split (= effect-idx 34) {:effect rgb_split :offset_x (bind bass values :range [5 40])} ;; Temporal 35-37 (= effect-idx 35) {:effect echo :num_echoes 4 :decay 0.5} (= effect-idx 36) {:effect trails :persistence 0.7} (= effect-idx 37) {:effect strobe :frequency 4} ;; Geometric 38-39 (= effect-idx 38) {:effect flip :direction "horizontal"} (= effect-idx 39) {:effect tile_grid :rows 2 :cols 2} ;; Glitch 40-41 - more glitchy (= effect-idx 40) {:effect pixelsort :threshold_low 30 :threshold_high 220} (= effect-idx 41) {:effect datamosh :corruption (bind bass values :range [0.2 0.8]) :block_size 24} ;; Default fallback :else {:effect invert})] {:source src :start wrapped-start :duration seg-duration :effects (list fx) :acc (inc acc)})))))) ;; Error if no segments were created (all videos too short) (assert (> (len segments) 0) "No segments created - all videos too short for segment durations") ;; Sequence all segments (def showcase (-> segments (sequence :resize-mode :fit :priority :width))) ;; Output with original audio (mux showcase audio))