annotate src/com/aurellem/capture/Capture.java @ 55:b05f629fc296

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