Mercurial > jmeCapture
comparison src/com/aurellem/capture/Capture.java @ 56:afc437f637bd
improved formating
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Dec 2011 19:25:27 -0600 |
parents | b05f629fc296 |
children | 302d5e9ad120 |
comparison
equal
deleted
inserted
replaced
55:b05f629fc296 | 56:afc437f637bd |
---|---|
16 import com.jme3.scene.Spatial; | 16 import com.jme3.scene.Spatial; |
17 import com.jme3.system.AppSettings; | 17 import com.jme3.system.AppSettings; |
18 import com.jme3.system.JmeSystem; | 18 import com.jme3.system.JmeSystem; |
19 | 19 |
20 /** | 20 /** |
21 * Use the methods in this class for capturing consistent, high quality video and audio from a | 21 * Use the methods in this class for capturing consistent, high quality video |
22 * jMonkeyEngine3 application. To capture audio or video do the following: | 22 * and audio from a jMonkeyEngine3 application. To capture audio or video do |
23 * the following: | |
23 * | 24 * |
24 * 1.) Set your application's timer to an IsoTimer. Create the IsoTimer with the desired video | 25 * 1.) Set your application's timer to an IsoTimer. Create the IsoTimer with the |
25 * frames-per-second. | 26 * desired video frames-per-second. |
26 * 2.) Call captureAudio and/or captureVideo on the Application as desired before starting the Application. | 27 * |
28 * 2.) Call captureAudio and/or captureVideo on the Application as desired | |
29 * before starting the Application. | |
27 * | 30 * |
28 * See the Basic and Advanced demos in the examples section for more information. If you have any trouble, | 31 * See the Basic and Advanced demos in the examples section for more |
29 * please PM me on the jMonkeyEngine forums. My username is bortreb. | 32 * information. If you have any trouble, please PM me on the jMonkeyEngine |
33 * forums. My username is bortreb. | |
30 * | 34 * |
31 * @author Robert McIntyre | 35 * @author Robert McIntyre |
32 */ | 36 */ |
33 | 37 |
34 public class Capture { | 38 public class Capture { |
35 | 39 |
36 /** | 40 /** |
37 * Use this function to capture video from your application. You specify the framerate at which | 41 * Use this function to capture video from your application. You |
38 * the video will be recording by setting the Application's timer to an IsoTimer created with the | 42 * specify the framerate at which the video will be recording by setting |
39 * desired frames-per-second. | 43 * the Application's timer to an IsoTimer created with the desired |
40 * | 44 * frames-per-second. |
41 * There are three ways to record and they are selected by the properties of the file that you | 45 * |
42 * specify. | 46 * There are three ways to record and they are selected by the |
43 * | 47 * properties of the file that you specify. |
44 * 1.) (Preferred) | 48 * |
45 * If you supply an empty directory as the file, then the video will | 49 * 1.) (Preferred) If you supply an empty directory as the file, then |
46 * be saved as a sequence of .png files, one file per frame. The files start at | 50 * the video will be saved as a sequence of .png files, one file per |
47 * 0000000.png and increment from there. You can then combine the frames into your | 51 * frame. The files start at 0000000.png and increment from there. |
48 * preferred container/codec. If the directory is not empty, then writing video frames | 52 * You can then combine the frames into your preferred |
49 * to it will fail, and nothing will be written. | 53 * container/codec. If the directory is not empty, then writing |
50 * | 54 * video frames to it will fail, and nothing will be written. |
51 * 2.) If the filename ends in ".avi" then the frames will be encoded as a RAW stream | 55 * |
52 * inside an AVI 1.0 container. The resulting file will be quite large and you will | 56 * 2.) If the filename ends in ".avi" then the frames will be encoded as |
53 * probably want to re-encode it to your preferred container/codec format. Be advised | 57 * a RAW stream inside an AVI 1.0 container. The resulting file |
54 * that some video payers cannot process AVI with a RAW stream, and that AVI 1.0 files | 58 * will be quite large and you will probably want to re-encode it to |
55 * generated by this method that exceed 2.0GB are invalid according to the AVI 1.0 spec | 59 * your preferred container/codec format. Be advised that some |
56 * (but many programs can still deal with them.) Thanks to Werner Randelshofer for his | 60 * video payers cannot process AVI with a RAW stream, and that AVI |
57 * excellent work which made AVI file writer option possible. | 61 * 1.0 files generated by this method that exceed 2.0GB are invalid |
58 * | 62 * according to the AVI 1.0 spec (but many programs can still deal |
59 * 3.) Any non-directory file ending in anything other than ".avi" will be processed through | 63 * with them.) Thanks to Werner Randelshofer for his excellent work |
60 * Xuggle. Xuggle provides the option to use many codecs/containers, but you will have to | 64 * which made AVI file writer option possible. |
61 * install it on your system yourself in order to use this option. Please visit | 65 * |
62 * http://www.xuggle.com/ to learn how to do this. | 66 * 3.) Any non-directory file ending in anything other than ".avi" will |
63 * | 67 * be processed through Xuggle. Xuggle provides the option to use |
64 * @param app The Application from which you wish to record Video. | 68 * many codecs/containers, but you will have to install it on your |
65 * @param file The file to which the video will be captured. | 69 * system yourself in order to use this option. Please visit |
66 * @throws IOException | 70 * http://www.xuggle.com/ to learn how to do this. |
67 */ | 71 * |
72 * @param app The Application from which you wish to record Video. | |
73 * @param file The file to which the video will be captured. | |
74 * @throws IOException | |
75 */ | |
68 | 76 |
69 public static void captureVideo(final Application app, final File file) throws IOException{ | 77 public static void captureVideo(final Application app, final File file) throws IOException{ |
70 final AbstractVideoRecorder videoRecorder; | 78 final AbstractVideoRecorder videoRecorder; |
71 | 79 |
72 if (file.getCanonicalPath().endsWith(".avi")){ | 80 if (file.getCanonicalPath().endsWith(".avi")){ |
73 videoRecorder = new AVIVideoRecorder(file);} | 81 videoRecorder = new AVIVideoRecorder(file);} |
74 else if (file.isDirectory()){ | 82 else if (file.isDirectory()){ |
75 videoRecorder = new FileVideoRecorder(file);} | 83 videoRecorder = new FileVideoRecorder(file);} |
76 else { videoRecorder = new XuggleVideoRecorder(file);} | 84 else { videoRecorder = new XuggleVideoRecorder(file);} |
77 | 85 |
78 Callable<Object> thunk = new Callable<Object>(){ | 86 Callable<Object> thunk = new Callable<Object>(){ |
79 public Object call(){ | 87 public Object call(){ |
80 | 88 |
81 ViewPort viewPort = | 89 ViewPort viewPort = |
82 app.getRenderManager() | 90 app.getRenderManager() |
83 .createPostView("aurellem video record", app.getCamera()); | 91 .createPostView("aurellem video record", app.getCamera()); |
84 | 92 |
85 viewPort.setClearFlags(false, false, false); | 93 viewPort.setClearFlags(false, false, false); |
86 | 94 |
87 // get GUI node stuff | 95 // get GUI node stuff |
88 for (Spatial s : app.getGuiViewPort().getScenes()){ | 96 for (Spatial s : app.getGuiViewPort().getScenes()){ |
89 viewPort.attachScene(s); | 97 viewPort.attachScene(s); |
90 } | 98 } |
91 | 99 |
92 app.getStateManager().attach(videoRecorder); | 100 app.getStateManager().attach(videoRecorder); |
93 viewPort.addProcessor(videoRecorder); | 101 viewPort.addProcessor(videoRecorder); |
94 return null; | 102 return null; |
95 } | 103 } |
96 }; | 104 }; |
97 app.enqueue(thunk); | 105 app.enqueue(thunk); |
98 } | 106 } |
99 | 107 |
100 | 108 |
101 /** | 109 /** |
102 * Use this function to capture audio from your application. Audio data will be saved in linear | 110 * Use this function to capture audio from your application. Audio data |
103 * PCM format at 44,100 hertz in the wav container format to the file that you specify. | 111 * will be saved in linear PCM format at 44,100 hertz in the wav container |
104 * | 112 * format to the file that you specify. |
105 * Note that you *have* to use an IsoTimer for your Application's timer while recording audio or | 113 * |
106 * the recording will fail. Also ensure that your IsoTimer obeys the following constraints: | 114 * Note that you *have* to use an IsoTimer for your Application's timer |
107 * | 115 * while recording audio or the recording will fail. Also ensure that your |
108 * - The frames-per-second value of the IsoTimer cannot be lower than 10 frames-per-second. | 116 * IsoTimer obeys the following constraints: |
109 * - The frames-per-second value of the IsoTimer must evenly divide 44,100. | 117 * |
110 * | 118 * 1.) The frames-per-second value of the IsoTimer cannot be lower than 10 |
111 * @param app The Application from which you wish to record Audio. | 119 * frames-per-second. |
112 * @param file the target file to which you want to record audio data. | 120 * |
113 * @throws IOException | 121 * 2.) The frames-per-second value of the IsoTimer must evenly divide |
114 */ | 122 * 44,100. |
123 * | |
124 * @param app The Application from which you wish to record Audio. | |
125 * @param file the target file to which you want to record audio data. | |
126 * @throws IOException | |
127 */ | |
115 | 128 |
116 public static void captureAudio(final Application app, final File file) throws IOException{ | 129 public static void captureAudio(final Application app, final File file) throws IOException{ |
117 AppSettings settings = null; | 130 AppSettings settings = null; |
118 if (app.getContext() != null){settings = app.getContext().getSettings();} | 131 if (app.getContext() != null){settings = app.getContext().getSettings();} |
119 if (settings == null){settings = new AppSettings(true);} | 132 if (settings == null){settings = new AppSettings(true);} |
120 settings.setAudioRenderer("Send"); | 133 settings.setAudioRenderer("Send"); |
121 app.setSettings(settings); | 134 app.setSettings(settings); |
122 | 135 |
123 JmeSystem.setSystemDelegate(new AurellemSystemDelegate()); | 136 JmeSystem.setSystemDelegate(new AurellemSystemDelegate()); |
124 | 137 |
125 final WaveFileWriter writer = new WaveFileWriter(file); | 138 final WaveFileWriter writer = new WaveFileWriter(file); |
126 | 139 |
127 Callable<Object> thunk = new Callable<Object>(){ | 140 Callable<Object> thunk = new Callable<Object>(){ |
128 public Object call(){ | 141 public Object call(){ |
129 AudioRenderer ar = app.getAudioRenderer(); | 142 AudioRenderer ar = app.getAudioRenderer(); |
130 if (ar instanceof MultiListener){ | 143 if (ar instanceof MultiListener){ |
131 MultiListener ml = (MultiListener)ar; | 144 MultiListener ml = (MultiListener)ar; |
132 ml.registerSoundProcessor(writer); | 145 ml.registerSoundProcessor(writer); |
133 } | 146 } |
134 return null; | 147 return null; |
135 } | 148 } |
136 }; | 149 }; |
137 app.enqueue(thunk); | 150 app.enqueue(thunk); |
138 } | 151 } |
139 } | 152 } |