Mercurial > vba-clojure
view clojure/com/aurellem/run/final_cut.clj @ 545:2b6cdea9bcdb
audio now syncs properly, but moves no longer sync with main display.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Wed, 27 Jun 2012 13:41:01 -0500 |
parents | 86d23b6d433f |
children | 36e5fa62eb3c |
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 force-sync19 "keep the entire movie to a certain fps"20 [fps]23 )26 (defn render-files!27 ([^File target-dir initial-state moves]28 (let [ram-map-dir (File. target-dir "ram-map")29 frames-dir (File. target-dir "frames")30 audio-file (File. target-dir "audio.wav")31 _ (.mkdir target-dir)32 _ (.mkdir ram-map-dir)33 _ (.mkdir frames-dir)34 wave-writer (WaveWriter. audio-file)35 moves (vec moves)36 desired-fps 6037 seconds-per-frame (/ 1.0 desired-fps)39 ]40 (set-state! initial-state)41 ;; clear sound buffer42 (sound-bytes)43 (try44 (dorun45 (reduce46 (fn [[total-audio-samples47 total-video-samples] move]48 (run-moves @current-state (vector move))49 (let [sound (sound-bytes)50 total-audio-samples (+ total-audio-samples51 (count sound))52 total-audio-time53 (*54 (/ total-audio-samples 4)55 (/ 44100))57 total-video-time (* total-video-samples58 seconds-per-frame)60 av-diff (- total-audio-time61 total-video-time)62 write-video!63 (fn [index]64 ;; write screenshot67 (write-png!68 @current-state69 (File. frames-dir (format "%07d.png" index)))71 ;; write ram-image72 (write-ram-image!73 @current-state74 (File. ram-map-dir (format "%07d.png" index))))]75 ;;(println "audio-samples:" (count sound))77 ;; record audio78 (.process wave-writer sound gb-sound-format)80 ;; duplicate or drop frames depending on81 ;; desired-fps82 (if (> (Math/abs av-diff) (* 2 seconds-per-frame))83 (if (< 0 av-diff)84 ;; audio has gone past video, duplicate video.85 (do (println86 "duplicating frame, av-diff is" av-diff)87 (write-video! (+ 1 total-video-samples))88 (write-video! (+ 2 total-video-samples))89 [total-audio-samples90 (+ 2 total-video-samples)])91 ;; video has gone past audio, drop frame.92 (do (println93 "dropping frame, av-diff is" av-diff)94 [total-audio-samples95 total-video-samples]))96 ;; no frame dropping or duplication required.97 (do ;;(println "all normal")98 (write-video! (+ 1 total-video-samples))99 [total-audio-samples100 (+ 1 total-video-samples)]))))101 [0 0 0] moves))102 (finally103 (do104 (println "cleanup audio.")105 (.cleanup wave-writer))))))106 ([initial-state moves]107 (render-files! render-dir initial-state moves))108 ([moves]109 (render-files! (root) moves)))111 (defn file-names [#^File dir]112 (mapv #(.getCanonicalPath %) (next (sort (file-seq dir)))))114 (defn composite-frames-command115 [screenshot ram-map target move]116 (let [actual-keys (set move)117 keys [:a :b :start :select :u :d :l :r]118 button-on-name ["-size" "5x5" "xc:red"]119 button-off-name ["-size" "5x5" "xc:white"]]120 ["convert"121 "-size" "318x276" "xc:white"122 (map123 (fn [index]124 (let [position ["-geometry"125 (str "+" (+ 30 (* index 8))126 "+" "225") "-composite"]]127 (if (actual-keys (keys index))128 [button-on-name position]129 [button-off-name position])))130 (range (count keys)))131 screenshot "-geometry" "+10+10" "-composite"132 ram-map "-geometry" "+180+10" "-composite"133 target]))135 (defn generate-composite-frames!136 [^File rendered-dir moves]137 (let [final-frames (File. rendered-dir "final")138 _ (.mkdir final-frames)139 screenshots (file-names (File. rendered-dir "frames"))140 ram-maps (file-names (File. rendered-dir "ram-map"))141 targets (map #(.getCanonicalPath142 (File. final-frames (format "%07d.bmp" %)))143 (range (count screenshots)))]144 (dorun145 (map146 (comp147 (partial apply clojure.java.shell/sh)148 flatten149 (partial apply composite-frames-command)150 (fn [a b c d] (println c) [a b c d]))151 screenshots ram-maps targets moves))))154 (defn final-cut! [^File render-dir]155 (let [movie (File. render-dir "final.ogg")156 final-audio (File. render-dir "final.wav")157 final (File. render-dir "final")]158 (.delete movie)159 (clojure.java.shell/sh160 "sox" (.getCanonicalPath (File. render-dir "audio.wav"))161 (.getCanonicalPath final-audio))162 (clojure.java.shell/sh163 "ffmpeg" "-r" "60" ;; maybe 59.7 ???!164 "-i" (str (.getCanonicalPath final) "/" "%07d.bmp")165 "-i" (.getCanonicalPath final-audio)166 "-b:a" "128k"167 "-b:v" "9000k"168 "-c:a" "libvorbis"169 "-c:v" "libtheora"170 (.getCanonicalPath movie)) nil))173 (comment175 ;; step 1177 (render-files!178 render-dir (root)179 (take 9000 (first (control-checkpoint))))181 ;; step 2183 (generate-composite-frames!184 render-dir185 (take 9000 (first (control-checkpoint))))187 ;; step 3188 (final-cut! render-dir)189 )