Recording a Video

It is often useful to record a video of an animation sequence. The VideoRecorder interface, shown in Listing 1, defines methods that make this easy.

Listing 1. VideoRecorder Methods

public void createVideo() throws IOException; // displays “save as” dialog
public void createVideo(String fileName) throws IOException;
public void createVideo(String fileName, int width, int height) throws IOException;
public void setFrameDuration(double millis); // milliseconds
public void addFrame(Image image) throws IOException;
public void saveVideo() throws IOException;

A video is empty when first created. Frames are added by passing Java images to the recorder. When a video is created without a specified width and height, its dimensions are those of the first image added. Once a video has been saved, no further frames can be added.

Recording an Animation Video

An example that uses VideoRecorder to record a simple animation of a rotating arrow (screenshot below) is shown in Listing 2.

Figure 2. Recording an Animation

Recording an animation video

Listing 2. VideoRecorderApp

import java.io.*;
import java.awt.image.*;
import javax.swing.*;
import org.opensourcephysics.display.*;
import org.opensourcephysics.media.*;
import org.opensourcephysics.media.gif.*;

public class GifRecorderApp {

public GifRecorderApp() {
String fileName = "Rotates.gif";

// create a drawing panel and frame
DrawingPanel panel = new VideoPanel();
DrawingFrame frame = new DrawingFrame(panel);
frame.setVisible(true); // will also work with a hidden frame

// record and save a video
frame.setTitle("Recording \"" + fileName + "\"");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// create a gif video recorder
GifVideoRecorder recorder = new GifVideoRecorder();

// create an image to use for rendering
BufferedImage image = new BufferedImage(panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_RGB);

// add an arrow to animate
Arrow arrow = new Arrow(0, 0, 0, 0);
panel.addDrawable(arrow);
try {

// define the video file and set the frame duration
recorder.createVideo(fileName);
recorder.setFrameDuration(100); // 10 fps

// get gif encoder to set optional repeat in browser (default is 1)
recorder.getGifEncoder().setRepeat(0); // repeats (plays) continuously

// gif encoder can also set transparent color or quality
recorder.getGifEncoder().setTransparent(panel.getBackground());

// add animation frames to the video
for (int i = 0; i < 20; i++) {
arrow.setXlength(5 * Math.cos(i * Math.PI / 10));
arrow.setYlength(5 * Math.sin(i * Math.PI / 10));
panel.repaint(); // optional screen display while recording
panel.render(image); // render the image
recorder.addFrame(image);
}

// save the completed video file
recorder.saveVideo();
}
catch (IOException ex) {}

// play the new video
try {
frame.setTitle("Playing \"" + fileName + "\"");
Video video = recorder.getVideo(); // can throw IOException
panel.removeDrawable(arrow);
panel.addDrawable(video);
video.setLooping(true);
video.play();
panel.repaint();
}
catch (IOException ex) {}
}

public static void main(String[] args) {
new GifRecorderApp();
}
}

In this application, we create a VideoRecorder and use it to record an animated gif video of a rotating arrow that will play at 20 fps. In the animation loop, we render an image of each frame and add it to the video. When all of the frames have been added, the video is saved, then played.

Note that the video is created and saved inside a try-catch block. This is required since these methods may throw an IOException.