SimpleRecorder.java Source code

Java tutorial

Introduction

Here is the source code for SimpleRecorder.java

Source

/*
    
Java Media APIs: Cross-Platform Imaging, Media and Visualization
Alejandro Terrazas
Sams, Published November 2002, 
ISBN 0672320940
*/

import javax.media.*;
import javax.media.format.*;
import javax.media.protocol.*;
import java.util.*;

/*******************************************************************************
 * A simple application to allow users to capture audio or video through devices
 * connected to the PC. Via command-line arguments the user specifies whether
 * audio (-a) or video (-v) capture, the duration of the capture (-d) in
 * seconds, and the file to write the media to (-f).
 * 
 * The application would be far more useful and versatile if it provided control
 * over the formats of the audio and video captured as well as the content type
 * of the output.
 * 
 * The class searches for capture devices that support the particular default
 * track formats: linear for audio and Cinepak for video. As a fall-back two
 * device names are hard-coded into the application as an example of how to
 * obtain DeviceInfo when a device's name is known. The user may force the
 * application to use these names by using the -k (known devices) flag.
 * 
 * The class is static but employs the earlier Location2Location example to
 * perform all the Processor and DataSink related work. Thus the application
 * chiefly involves CaptureDevice related operations.
 * 
 * @author Michael (Spike) Barlow
 ******************************************************************************/
public class SimpleRecorder {

    /////////////////////////////////////////////////////////////
    // Names for the audio and video capture devices on the
    // author's system. These will vary system to system but are
    // only used as a fallback.
    /////////////////////////////////////////////////////////////
    private static final String AUDIO_DEVICE_NAME = "DirectSoundCapture";

    private static final String VIDEO_DEVICE_NAME = "vfw:Microsoft WDM Image Capture:0";

    ///////////////////////////////////////////////////////////
    // Default names for the files to write the output to for
    // the case where they are not supplie by the user.
    //////////////////////////////////////////////////////////
    private static final String DEFAULT_AUDIO_NAME = "file://./captured.wav";

    private static final String DEFAULT_VIDEO_NAME = "file://./captured.avi";

    ///////////////////////////////////////////
    // Type of capture requested by the user.
    //////////////////////////////////////////
    private static final String AUDIO = "audio";

    private static final String VIDEO = "video";

    private static final String BOTH = "audio and video";

    ////////////////////////////////////////////////////////////////////
    // The only audio and video formats that the particular application
    // supports. A better program would allow user selection of formats
    // but would grow past the small example size.
    ////////////////////////////////////////////////////////////////////
    private static final Format AUDIO_FORMAT = new AudioFormat(AudioFormat.LINEAR);

    private static final Format VIDEO_FORMAT = new VideoFormat(VideoFormat.CINEPAK);

    public static void main(String[] args) {

        //////////////////////////////////////////////////////
        // Object to handle the processing and sinking of the
        // data captured from the device.
        //////////////////////////////////////////////////////
        Location2Location capture;

        /////////////////////////////////////
        // Audio and video capture devices.
        ////////////////////////////////////
        CaptureDeviceInfo audioDevice = null;
        CaptureDeviceInfo videoDevice = null;

        /////////////////////////////////////////////////////////////
        // Capture device's "location" plus the name and location of
        // the destination.
        /////////////////////////////////////////////////////////////
        MediaLocator captureLocation = null;
        MediaLocator destinationLocation;
        String destinationName = null;

        ////////////////////////////////////////////////////////////
        // Formats the Processor (in Location2Location) must match.
        ////////////////////////////////////////////////////////////
        Format[] formats = new Format[1];

        ///////////////////////////////////////////////
        // Content type for an audio or video capture.
        //////////////////////////////////////////////
        ContentDescriptor audioContainer = new ContentDescriptor(FileTypeDescriptor.WAVE);
        ContentDescriptor videoContainer = new ContentDescriptor(FileTypeDescriptor.MSVIDEO);
        ContentDescriptor container = null;

        ////////////////////////////////////////////////////////////////////
        // Duration of recording (in seconds) and period to wait afterwards
        ///////////////////////////////////////////////////////////////////
        double duration = 10;
        int waitFor = 0;

        //////////////////////////
        // Audio or video capture?
        //////////////////////////
        String selected = AUDIO;

        ////////////////////////////////////////////////////////
        // All devices that support the format in question.
        // A means of "ensuring" the program works on different
        // machines with different capture devices.
        ////////////////////////////////////////////////////////
        Vector devices;

        //////////////////////////////////////////////////////////
        // Whether to search for capture devices that support the
        // format or use the devices whos names are already
        // known to the application.
        //////////////////////////////////////////////////////////
        boolean useKnownDevices = false;

        /////////////////////////////////////////////////////////
        // Process the command-line options as to audio or video,
        // duration, and file to save to.
        /////////////////////////////////////////////////////////
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-d")) {
                try {
                    duration = (new Double(args[++i])).doubleValue();
                } catch (NumberFormatException e) {
                }
            } else if (args[i].equals("-w")) {
                try {
                    waitFor = Integer.parseInt(args[++i]);
                } catch (NumberFormatException e) {
                }
            } else if (args[i].equals("-a")) {
                selected = AUDIO;
            } else if (args[i].equals("-v")) {
                selected = VIDEO;
            } else if (args[i].equals("-b")) {
                selected = BOTH;
            } else if (args[i].equals("-f")) {
                destinationName = args[++i];
            } else if (args[i].equals("-k")) {
                useKnownDevices = true;
            } else if (args[i].equals("-h")) {
                System.out.println(
                        "Call as java SimpleRecorder [-a | -v | -b] [-d duration] [-f file] [-k] [-w wait]");
                System.out.println("\t-a\tAudio\n\t-v\tVideo\n\t-b\tBoth audio and video (system dependent)");
                System.out.println("\t-d\trecording Duration (seconds)");
                System.out
                        .println("\t-f\tFile to save to\n\t-k\tuse Known device names (don't search for devices)");
                System.out.println("\t-w\tWait the specified time (seconds) before abandoning capture");
                System.out.println(
                        "Defaults: 10 seconds, audio, and captured.wav or captured.avi, 4x recording duration wait");
                System.exit(0);
            }
        }

        /////////////////////////////////////////////////////////////////
        // Perform setup for audio capture. Includes finding a suitable
        // device, obatining its MediaLocator and setting the content
        // type.
        ////////////////////////////////////////////////////////////////
        if (selected.equals(AUDIO)) {
            devices = CaptureDeviceManager.getDeviceList(AUDIO_FORMAT);
            if (devices.size() > 0 && !useKnownDevices) {
                audioDevice = (CaptureDeviceInfo) devices.elementAt(0);
            } else
                audioDevice = CaptureDeviceManager.getDevice(AUDIO_DEVICE_NAME);
            if (audioDevice == null) {
                System.out.println("Can't find suitable audio device. Exiting");
                System.exit(1);
            }
            captureLocation = audioDevice.getLocator();
            formats[0] = AUDIO_FORMAT;
            if (destinationName == null)
                destinationName = DEFAULT_AUDIO_NAME;
            container = audioContainer;
        }
        /////////////////////////////////////////////////////////////////
        // Perform setup for video capture. Includes finding a suitable
        // device, obatining its MediaLocator and setting the content
        // type.
        ////////////////////////////////////////////////////////////////
        else if (selected.equals(VIDEO)) {
            devices = CaptureDeviceManager.getDeviceList(VIDEO_FORMAT);
            if (devices.size() > 0 && !useKnownDevices)
                videoDevice = (CaptureDeviceInfo) devices.elementAt(0);
            else
                videoDevice = CaptureDeviceManager.getDevice(VIDEO_DEVICE_NAME);
            if (videoDevice == null) {
                System.out.println("Can't find suitable video device. Exiting");
                System.exit(1);
            }
            captureLocation = videoDevice.getLocator();
            formats[0] = VIDEO_FORMAT;
            if (destinationName == null)
                destinationName = DEFAULT_VIDEO_NAME;
            container = videoContainer;
        } else if (selected.equals(BOTH)) {
            captureLocation = null;
            formats = new Format[2];
            formats[0] = AUDIO_FORMAT;
            formats[1] = VIDEO_FORMAT;
            container = videoContainer;
            if (destinationName == null)
                destinationName = DEFAULT_VIDEO_NAME;
        }

        ////////////////////////////////////////////////////////////////////
        // Perform all the necessary Processor and DataSink preparation via
        // the Location2Location class.
        ////////////////////////////////////////////////////////////////////
        destinationLocation = new MediaLocator(destinationName);
        System.out.println("Configuring for capture. Please wait.");
        capture = new Location2Location(captureLocation, destinationLocation, formats, container, 1.0);

        /////////////////////////////////////////////////////////////////////////////
        // Start the recording and tell the user. Specify the length of the
        // recording. Then wait around for up to 4-times the duration of
        // recording
        // (can take longer to sink/write the data so should wait a bit incase).
        /////////////////////////////////////////////////////////////////////////////
        System.out.println("Started recording " + duration + " seconds of " + selected + " ...");
        capture.setStopTime(new Time(duration));
        if (waitFor == 0)
            waitFor = (int) (4000 * duration);
        else
            waitFor *= 1000;
        int waited = capture.transfer(waitFor);

        /////////////////////////////////////////////////////////
        // Report on the success (or otherwise) of the recording.
        /////////////////////////////////////////////////////////
        int state = capture.getState();
        if (state == Location2Location.FINISHED)
            System.out.println(selected + " capture successful in approximately " + ((int) ((waited + 500) / 1000))
                    + " seconds. Data written to " + destinationName);
        else if (state == Location2Location.FAILED)
            System.out.println(selected + " capture failed after approximately " + ((int) ((waited + 500) / 1000))
                    + " seconds");
        else {
            System.out.println(selected + " capture still ongoing after approximately "
                    + ((int) ((waited + 500) / 1000)) + " seconds");
            System.out.println("Process likely to have failed");
        }

        System.exit(0);
    }
}