Mercurial > vba-clojure
view clojure/com/aurellem/run/final_cut.clj @ 547:b3b7a06686c4
all synching issues resolved.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Wed, 27 Jun 2012 19:38:13 -0500 |
parents | 36e5fa62eb3c |
children | 6ce1d5fd4911 |
line wrap: on
line source
1 (ns com.aurellem.run.final-cut2 (:use (com.aurellem.gb saves gb-driver util constants3 items vbm characters money4 rlm-assembly))5 (:use (com.aurellem.run util sound music title save-corruption6 bootstrap-0 bootstrap-17 ram-display8 ))9 (:require clojure.string)10 (:import [com.aurellem.gb.gb_driver SaveState])11 (:import java.awt.image.BufferedImage)12 (:import java.io.File)13 (:import com.aurellem.gb.WaveWriter))16 (def render-dir (File. user-home "proj/vba-clojure/render/test"))18 (defn write-move-image! [move target-file]19 (let [actual-keys (set move)20 keys [:a :b :start :select :u :d :l :r]21 button-on-name ["-size" "5x5" "xc:red"]22 button-off-name ["-size" "5x5" "xc:white"]]23 (apply24 clojure.java.shell/sh25 (flatten26 ["convert"27 "-size" "64x5" "xc:white"28 (map29 (fn [index]30 (let [position ["-geometry"31 (str "+" (* index 8)32 "+" "0") "-composite"]]33 (if (actual-keys (keys index))34 [button-on-name position]35 [button-off-name position])))36 (range (count keys)))37 (.getCanonicalPath target-file)]))))39 (defn render-files!40 ([^File target-dir initial-state moves]41 (let [ram-map-dir (File. target-dir "ram-map")42 frames-dir (File. target-dir "frames")43 moves-dir (File. target-dir "moves")44 audio-file (File. target-dir "audio.wav")45 _ (.mkdir target-dir)46 _ (.mkdir ram-map-dir)47 _ (.mkdir frames-dir)48 _ (.mkdir moves-dir)49 wave-writer (WaveWriter. audio-file)50 moves (vec moves)51 desired-fps 6052 seconds-per-frame (/ 1.0 desired-fps)]53 (set-state! initial-state)54 ;; clear sound buffer55 (sound-bytes)56 (try57 (dorun58 (reduce59 (fn [[total-audio-samples60 total-video-samples] move]61 (run-moves @current-state (vector move))62 (let [sound (sound-bytes)63 total-audio-samples (+ total-audio-samples64 (count sound))65 total-audio-time66 (*67 (/ total-audio-samples 4)68 (/ 44100))70 total-video-time (* total-video-samples71 seconds-per-frame)73 av-diff (- total-audio-time74 total-video-time)75 write-video!76 (fn [index]77 ;; write screenshot78 (write-move-image!79 move80 (File. moves-dir (format "%07d.png" index)))82 (write-png!83 @current-state84 (File. frames-dir (format "%07d.png" index)))86 ;; write ram-image87 (write-ram-image!88 @current-state89 (File. ram-map-dir (format "%07d.png" index))))]90 ;;(println "audio-samples:" (count sound))92 ;; record audio93 (.process wave-writer sound gb-sound-format)95 ;; duplicate or drop frames depending on96 ;; desired-fps97 (if (> (Math/abs av-diff) (* 2 seconds-per-frame))98 (if (< 0 av-diff)99 ;; audio has gone past video, duplicate video.100 (do (println101 "duplicating frame, av-diff is" av-diff)102 (write-video! (+ 1 total-video-samples))103 (write-video! (+ 2 total-video-samples))104 [total-audio-samples105 (+ 2 total-video-samples)])106 ;; video has gone past audio, drop frame.107 (do (println108 "dropping frame, av-diff is" av-diff)109 [total-audio-samples110 total-video-samples]))111 ;; no frame dropping or duplication required.112 (do ;;(println "all normal")113 (write-video! (+ 1 total-video-samples))114 [total-audio-samples115 (+ 1 total-video-samples)]))))116 [0 0 0] moves))117 (finally118 (do119 (println "cleanup audio.")120 (.cleanup wave-writer))))))121 ([initial-state moves]122 (render-files! render-dir initial-state moves))123 ([moves]124 (render-files! (root) moves)))126 (defn file-names [#^File dir]127 (mapv #(.getCanonicalPath %) (next (sort (file-seq dir)))))129 (defn composite-frames-command130 [move-image screenshot ram-map target]131 ["convert"132 "-size" "318x276" "xc:white"133 move-image "-geometry" "+30+225" "-composite"134 screenshot "-geometry" "+10+10" "-composite"135 ram-map "-geometry" "+180+10" "-composite"136 target])138 (defn generate-composite-frames!139 [^File rendered-dir]140 (let [final-frames (File. rendered-dir "final")141 _ (.mkdir final-frames)142 move-images (file-names (File. rendered-dir "moves"))143 screenshots (file-names (File. rendered-dir "frames"))144 ram-maps (file-names (File. rendered-dir "ram-map"))145 targets (map #(.getCanonicalPath146 (File. final-frames (format "%07d.bmp" %)))147 (range (count screenshots)))]148 (dorun149 (map150 (comp151 (partial apply clojure.java.shell/sh)152 flatten153 (partial apply composite-frames-command)154 (fn [a b c d] (println d) [a b c d]))155 move-images screenshots ram-maps targets))))158 (defn final-cut! [^File render-dir]159 (let [movie (File. render-dir "final.ogg")160 final-audio (File. render-dir "final.wav")161 final (File. render-dir "final")]162 (.delete movie)163 (.delete final-audio)164 (clojure.java.shell/sh165 "sox" (.getCanonicalPath (File. render-dir "audio.wav"))166 (.getCanonicalPath final-audio))167 (clojure.java.shell/sh168 "ffmpeg" "-r" "60" ;; maybe 59.7 ???!169 "-i" (str (.getCanonicalPath final) "/" "%07d.bmp")170 "-i" (.getCanonicalPath final-audio)171 "-b:a" "128k"172 "-b:v" "9000k"173 "-c:a" "libvorbis"174 "-f" "webm"175 "-g" "200"176 (.getCanonicalPath movie)) nil))179 (comment181 ;; step 1183 (render-files!184 render-dir (root)185 (take 9000 (first (control-checkpoint))))187 ;; step 2189 (generate-composite-frames!190 render-dir191 (take 9000 (first (control-checkpoint))))193 ;; step 3194 (final-cut! render-dir)195 )