Sunday, December 18, 2016

Create your own Free Screen Recorder using Java

Their are many commercial software which allows you to record your desktop screen and save the video.
In this post we will learn how to create a simple screen recorder using Java. This recorder will be capable of recording full screen or record the user selected region.

How it works:
1) When user starts the recording then program starts 2 threads.
2) The first thread keeps on taking screenshot of the screen and saves them into local disk mentioned in variable inputImgDir
3) The second thread continuously looks over the inputImageDir and adds all the new images into the video.
4) When user press stop recording then both threads stop and final video is retrieved.

Language Used:
Java

Git Repo:
https://github.com/csanuragjain/recorder/tree/master/ScreenRecorder

POM Dependency:
Please add the below pom dependency from https://mvnrepository.com/artifact/org.bytedeco/javacv:
<dependency>   
   <groupId>org.bytedeco</groupId>   
   <artifactId>javacv</artifactId>   
   <version>1.0</version>   
  </dependency>  

Reference:
https://cooltrickshome.blogspot.in/2016/11/convert-movie-to-images-using-java.html
https://cooltrickshome.blogspot.in/2016/11/create-desktop-screenshot-maker.html

Program:

Variables:
      public static boolean videoComplete=false;  
      public static String inputImageDir="inputImgFolder"+File.separator;  
      public static String inputImgExt="png";  
      public static String outputVideo="recording.mp4";   
      public static int counter=0;  
      public static int imgProcessed=0;  
      public static FFmpegFrameRecorder recorder=null;  
      public static int videoWidth=1920;  
      public static int videoHeight=1080;  
      public static int videoFrameRate=3;  
      public static int videoQuality=0; // 0 is the max quality  
      public static int videoBitRate=9000;  
      public static String videoFormat="mp4";  
      public static int videoCodec=avcodec.AV_CODEC_ID_MPEG4;  
      public static Thread t1=null;  
      public static Thread t2=null;  
      public static JFrame frame=null;  
      public static boolean isRegionSelected=false;  
      public static int c1=0;  
      public static int c2=0;  
      public static int c3=0;  
      public static int c4=0;  


Explanation:
1) videoComplete variables tells if user has stopped the recording or not.
2) inputImageDir defines the input directory where screenshots will be stored which would be utilized by the video thread
3) inputImgExt denotes the extension of the image taken for screenshot.
4) outputVideo is the name of the recorded video file
5) counter is used for numbering the screenshots when stored in input directory.
6) recorder is used for starting and stopping the video recording
7) videoWidth, videoFrameRate etc define output video param
8) If user wants to record only a selected region then c1,c2,c3,c4 denotes the coordinate

getRecorder method:
      public static FFmpegFrameRecorder getRecorder() throws Exception  
      {  
            if(recorder!=null)  
            {  
                 return recorder;  
            }  
            recorder = new FFmpegFrameRecorder(outputVideo,videoWidth,videoHeight);  
            try  
            {  
            recorder.setFrameRate(videoFrameRate);  
      recorder.setVideoCodec(videoCodec);  
      recorder.setVideoBitrate(videoBitRate);  
      recorder.setFormat(videoFormat);  
      recorder.setVideoQuality(videoQuality); // maximum quality  
      recorder.start();  
            }  
            catch(Exception e)  
            {  
                 JOptionPane.showMessageDialog(frame, "Exception while starting the recorder object "+e.getMessage());  
                 System.out.println("Exception while starting the recorder object "+e.getMessage());  
                 throw new Exception("Unable to start recorder");  
            }  
      return recorder;  
      }  

Explanation:
1) This method is used to get the Recorder object.
2) We create an object of FFmpegFrameRecorder named "Recorder" and then set all its video parameters.
3) Lastly we start the recorder and then return the object.

getRobot method:
      public static Robot getRobot() throws Exception  
      {  
           Robot r=null;  
           try {  
                r = new Robot();  
                return r;  
           } catch (AWTException e) {  
                JOptionPane.showMessageDialog(frame, "Issue while initiating Robot object "+e.getMessage());  
                System.out.println("Issue while initiating Robot object "+e.getMessage());  
                throw new Exception("Issue while initiating Robot object");  
           }  
      }  

Explanation:
1) This method retrieves an object of Robot class which could be further utilized by remaining methods.

main Method:
      public static void main(String[] args) {  
           try {  
                if(getRecorder()==null)  
                {  
                     System.out.println("Cannot make recorder object, Exiting program");  
                     System.exit(0);  
                }  
                if(getRobot()==null)  
                {  
                     System.out.println("Cannot make robot object, Exiting program");  
                     System.exit(0);  
                }  
                File scanFolder=new File(inputImageDir);  
                scanFolder.delete();  
                scanFolder.mkdirs();  
                createGUI();  
           } catch (Exception e) {  
                System.out.println("Exception in program "+e.getMessage());  
           }  
      }  

Explanation:
1) We initialize the recorder and Robot object.
2) We create the input image folder.
3) Now we open up the GUI which will allow user to start/stop the recording.

createGUI method:
      public static void createGUI()  
      {  
           frame=new JFrame("Screen Recorder");  
           JButton b1=new JButton("Select Region for Recording");  
           JButton b2=new JButton("Start Recording");  
           JButton b3=new JButton("Stop Recording");  
           JLabel l1=new JLabel("<html><br/>If you dont select a region then full screen recording <br/> will be made when you click on Start Recording</html>");  
           l1.setFont (l1.getFont ().deriveFont (20.0f));  
           b1.addActionListener(new ActionListener() {  
       @Override  
       public void actionPerformed(ActionEvent e) {  
            try {  
                 JOptionPane.showMessageDialog(frame, "A new window will open. Use your mouse to select the region you like to record");  
                          new CropRegion().getImage();  
                     } catch (Exception e1) {  
                          // TODO Auto-generated catch block  
                          System.out.println("Issue while trying to call the module to crop region");  
                          e1.printStackTrace();  
                     }   
       }  
     });  
           b2.addActionListener(new ActionListener() {  
       @Override  
       public void actionPerformed(ActionEvent e) {  
            counter=0;  
         startRecording();  
       }  
     });  
           b3.addActionListener(new ActionListener() {  
       @Override  
       public void actionPerformed(ActionEvent e) {  
         stopRecording();  
         System.out.print("Exiting...");  
         System.exit(0);  
       }  
     });  
           frame.add(b1);  
           frame.add(b2);  
           frame.add(b3);  
           frame.add(l1);  
           frame.setLayout(new FlowLayout(0));  
           frame.setVisible(true);  
           frame.setSize(1000, 170);  
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
      }  

Explanation:
1) We make a JFrame with the button for staring and stopping the recording. One more button is added for allowing user to record only a selected portion of screen
2) If user clicks to select only certain region then we call a class CropRegion method getImage which helps in retrieving the coordinate of the region selected by user and update the same in variable c1,c2,c3,c4
3) If user clicks on start recording then startRecording method is called
4) If user clicks on stoprecording then stopRecording method is called

startRecording method:
      public static void startRecording()  
      {  
           t1=new Thread()  
           {  
             public void run() {  
               try {  
                          takeScreenshot(getRobot());  
                     } catch (Exception e) {  
                          JOptionPane.showMessageDialog(frame, "Cannot make robot object, Exiting program "+e.getMessage());  
                          System.out.println("Cannot make robot object, Exiting program "+e.getMessage());  
                          System.exit(0);  
                     }  
             }  
           };  
           t2=new Thread()  
           {  
             public void run() {  
               prepareVideo();  
             }  
           };  
           t1.start();  
           t2.start();  
           System.out.println("Started recording at "+new Date());  
      }  


Explanation:
1) Two threads are started in this module when user starts the recording
2) First thread calls the takeScreenshot module which keeps on taking screenshot of user screen and saves them on local disk.
3) Second thread calls the prepareVideo which monitors the screenshot created in step 2 and add them continuously on the video.

takeScreenshot method:
      public static void takeScreenshot(Robot r)  
      {  
           Dimension size = Toolkit.getDefaultToolkit().getScreenSize();  
           Rectangle rec=new Rectangle(size);  
           if(isRegionSelected)  
           {  
                rec=new Rectangle(c1, c2, c3-c1, c4-c2);  
           }  
           while(!videoComplete)  
           {  
           counter++;  
           BufferedImage img = r.createScreenCapture(rec);  
           try {  
                ImageIO.write(img, inputImgExt, new File(inputImageDir+counter+"."+inputImgExt));  
           } catch (IOException e) {  
                JOptionPane.showMessageDialog(frame, "Got an issue while writing the screenshot to disk "+e.getMessage());  
                System.out.println("Got an issue while writing the screenshot to disk "+e.getMessage());  
                counter--;  
           }  
           }  
      }  

Explanation:
1) If user has selected a region for recording then we set the rectangle with the coordinate value of c1,c2,c3,c4. Otherwise we set the rectangle to be full screen
2) Now we run a loop until videoComplete is false (remains false until user press stop recording.
3) Now we capture the region and write the same to the input image directory.
4) So when user starts the recording this method keeps on taking screenshot and saves them into disk.

prepareVideo method:
      public static void prepareVideo()  
      {  
           File scanFolder=new File(inputImageDir);  
           while(!videoComplete)  
           {  
                File[] inputFiles=scanFolder.listFiles();  
                try {  
                     getRobot().delay(500);  
                } catch (Exception e) {  
                }  
                //for(int i=0;i<scanFolder.list().length;i++)  
                for(int i=0;i<inputFiles.length;i++)  
                {  
                     //imgProcessed++;  
                     addImageToVideo(inputFiles[i].getAbsolutePath());  
                     //String imgToAdd=scanFolder.getAbsolutePath()+File.separator+imgProcessed+"."+inputImgExt;  
                     //addImageToVideo(imgToAdd);  
                     //new File(imgToAdd).delete();  
                     inputFiles[i].delete();  
                }  
           }  
           File[] inputFiles=scanFolder.listFiles();  
           for(int i=0;i<inputFiles.length;i++)  
           {  
                addImageToVideo(inputFiles[i].getAbsolutePath());  
                inputFiles[i].delete();  
           }  
      }  

Explanation:
1) We start a loop which will run until video complete is set true (done only when user press stop recording)
2) We keep on monitoring the input  Image directory
3) We traverse each file found in the input image directory and add those images to video using the addImageToVideo method. After the image has been added we delete the image
4) Using the loop in step1 we keep on repeating step 2 and 3 so that each image gets added to video. We added a delay of 500ms so that this module does not picks a half created image from the takeScreenshot module
5) When user press stop recording the loop gets broken. Now we finally traverse the input image directory and add the remaining images to video.

addImageToVideo method:
      public static void addImageToVideo(String imgPath)  
      {  
           try {  
                getRecorder().record(getFrameConverter().convert(cvLoadImage(imgPath)));  
           } catch (Exception e) {  
                JOptionPane.showMessageDialog(frame, "Exception while adding image to video "+e.getMessage());  
                System.out.println("Exception while adding image to video "+e.getMessage());  
           }  
      }  

Explanation:
1) cvLoadImage is used to load the image passed as argument
2) We call the convert method to convert the image to frame which could be used by the recorder
3) We pass the frame obtained in step 2 and add the same in the recorder by calling the record method.

getFrameConverter method:
      public static OpenCVFrameConverter.ToIplImage getFrameConverter()  
      {  
           OpenCVFrameConverter.ToIplImage grabberConverter = new OpenCVFrameConverter.ToIplImage();  
           return grabberConverter;  
      }  

Explanation:
1) We make an object of OpenCVFrameConverter.ToIplImage named grabberConverter and returns this object for other modules.

stopRecording method:
      public static void stopRecording()  
      {  
           try {  
                videoComplete=true;  
                System.out.println("Stopping recording at "+new Date());  
                t1.join();  
                System.out.println("Screenshot thread complete");  
                t2.join();  
                System.out.println("Video maker thread complete");  
                getRecorder().stop();  
                System.out.println("Recording has been saved successfully at "+new File(outputVideo).getAbsolutePath());  
                JOptionPane.showMessageDialog(frame, "Recording has been saved successfully at "+new File(outputVideo).getAbsolutePath());  
           } catch (Exception e) {  
                System.out.println("Exception while stopping the recorder "+e.getMessage());  
           }  
      }  


Explanation:
1) After user press the stop recording, we wait for both the threads to complete.
2) After thread completes, we stop the recorder and show the video path to user.

Output:

 Started recording at Sun Dec 18 18:29:36 IST 2016  
 Stopping recording at Sun Dec 18 18:29:51 IST 2016  
 Screenshot thread complete  
 Video maker thread complete  
 Recording has been saved successfully at C:\Users\anjain\workspace\BrowserMobProxy\cooltrickshome\recording.mp4  
 Exiting...libpng error: PNG unsigned integer out of range  
 Output #0, mp4, to 'recording.mp4':  
   Stream #0:0: Video: mpeg4, yuv420p, 1920x1080, q=2-31, 9 kb/s, 3 tbn, 3 tbc  

Full Program:

ScreenRecorder.java
 package com.cooltrickshome;  
 import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;  
 import java.awt.AWTException;  
 import java.awt.Dimension;  
 import java.awt.FlowLayout;  
 import java.awt.Rectangle;  
 import java.awt.Robot;  
 import java.awt.Toolkit;  
 import java.awt.event.ActionEvent;  
 import java.awt.event.ActionListener;  
 import java.awt.image.BufferedImage;  
 import java.io.File;  
 import java.io.IOException;  
 import java.util.Date;  
 import javax.imageio.ImageIO;  
 import javax.swing.JButton;  
 import javax.swing.JFrame;  
 import javax.swing.JLabel;  
 import javax.swing.JOptionPane;  
 import org.bytedeco.javacpp.avcodec;  
 import org.bytedeco.javacv.FFmpegFrameRecorder;  
 import org.bytedeco.javacv.OpenCVFrameConverter;  
 public class ScreenRecorder{  
      public static boolean videoComplete=false;  
      public static String inputImageDir="inputImgFolder"+File.separator;  
      public static String inputImgExt="png";  
      public static String outputVideo="recording.mp4";   
      public static int counter=0;  
      public static int imgProcessed=0;  
      public static FFmpegFrameRecorder recorder=null;  
      public static int videoWidth=1920;  
      public static int videoHeight=1080;  
      public static int videoFrameRate=3;  
      public static int videoQuality=0; // 0 is the max quality  
      public static int videoBitRate=9000;  
      public static String videoFormat="mp4";  
      public static int videoCodec=avcodec.AV_CODEC_ID_MPEG4;  
      public static Thread t1=null;  
      public static Thread t2=null;  
      public static JFrame frame=null;  
      public static boolean isRegionSelected=false;  
      public static int c1=0;  
      public static int c2=0;  
      public static int c3=0;  
      public static int c4=0;  
      public static void main(String[] args) {  
           try {  
                if(getRecorder()==null)  
                {  
                     System.out.println("Cannot make recorder object, Exiting program");  
                     System.exit(0);  
                }  
                if(getRobot()==null)  
                {  
                     System.out.println("Cannot make robot object, Exiting program");  
                     System.exit(0);  
                }  
                File scanFolder=new File(inputImageDir);  
                scanFolder.delete();  
                scanFolder.mkdirs();  
                createGUI();  
           } catch (Exception e) {  
                System.out.println("Exception in program "+e.getMessage());  
           }  
      }  
      public static void createGUI()  
      {  
           frame=new JFrame("Screen Recorder");  
           JButton b1=new JButton("Select Region for Recording");  
           JButton b2=new JButton("Start Recording");  
           JButton b3=new JButton("Stop Recording");  
           JLabel l1=new JLabel("<html><br/>If you dont select a region then full screen recording <br/> will be made when you click on Start Recording</html>");  
           l1.setFont (l1.getFont ().deriveFont (20.0f));  
           b1.addActionListener(new ActionListener() {  
       @Override  
       public void actionPerformed(ActionEvent e) {  
            try {  
                 JOptionPane.showMessageDialog(frame, "A new window will open. Use your mouse to select the region you like to record");  
                          new CropRegion().getImage();  
                     } catch (Exception e1) {  
                          // TODO Auto-generated catch block  
                          System.out.println("Issue while trying to call the module to crop region");  
                          e1.printStackTrace();  
                     }   
       }  
     });  
           b2.addActionListener(new ActionListener() {  
       @Override  
       public void actionPerformed(ActionEvent e) {  
            counter=0;  
         startRecording();  
       }  
     });  
           b3.addActionListener(new ActionListener() {  
       @Override  
       public void actionPerformed(ActionEvent e) {  
         stopRecording();  
         System.out.print("Exiting...");  
         System.exit(0);  
       }  
     });  
           frame.add(b1);  
           frame.add(b2);  
           frame.add(b3);  
           frame.add(l1);  
           frame.setLayout(new FlowLayout(0));  
           frame.setVisible(true);  
           frame.setSize(1000, 170);  
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
      }  
      public static void startRecording()  
      {  
           t1=new Thread()  
           {  
             public void run() {  
               try {  
                          takeScreenshot(getRobot());  
                     } catch (Exception e) {  
                          JOptionPane.showMessageDialog(frame, "Cannot make robot object, Exiting program "+e.getMessage());  
                          System.out.println("Cannot make robot object, Exiting program "+e.getMessage());  
                          System.exit(0);  
                     }  
             }  
           };  
           t2=new Thread()  
           {  
             public void run() {  
               prepareVideo();  
             }  
           };  
           t1.start();  
           t2.start();  
           System.out.println("Started recording at "+new Date());  
      }  
      public static Robot getRobot() throws Exception  
      {  
           Robot r=null;  
           try {  
                r = new Robot();  
                return r;  
           } catch (AWTException e) {  
                JOptionPane.showMessageDialog(frame, "Issue while initiating Robot object "+e.getMessage());  
                System.out.println("Issue while initiating Robot object "+e.getMessage());  
                throw new Exception("Issue while initiating Robot object");  
           }  
      }  
      public static void takeScreenshot(Robot r)  
      {  
           Dimension size = Toolkit.getDefaultToolkit().getScreenSize();  
           Rectangle rec=new Rectangle(size);  
           if(isRegionSelected)  
           {  
                rec=new Rectangle(c1, c2, c3-c1, c4-c2);  
           }  
           while(!videoComplete)  
           {  
           counter++;  
           BufferedImage img = r.createScreenCapture(rec);  
           try {  
                ImageIO.write(img, inputImgExt, new File(inputImageDir+counter+"."+inputImgExt));  
           } catch (IOException e) {  
                JOptionPane.showMessageDialog(frame, "Got an issue while writing the screenshot to disk "+e.getMessage());  
                System.out.println("Got an issue while writing the screenshot to disk "+e.getMessage());  
                counter--;  
           }  
           }  
      }  
      public static void prepareVideo()  
      {  
           File scanFolder=new File(inputImageDir);  
           while(!videoComplete)  
           {  
                File[] inputFiles=scanFolder.listFiles();  
                try {  
                     getRobot().delay(500);  
                } catch (Exception e) {  
                }  
                //for(int i=0;i<scanFolder.list().length;i++)  
                for(int i=0;i<inputFiles.length;i++)  
                {  
                     //imgProcessed++;  
                     addImageToVideo(inputFiles[i].getAbsolutePath());  
                     //String imgToAdd=scanFolder.getAbsolutePath()+File.separator+imgProcessed+"."+inputImgExt;  
                     //addImageToVideo(imgToAdd);  
                     //new File(imgToAdd).delete();  
                     inputFiles[i].delete();  
                }  
           }  
           File[] inputFiles=scanFolder.listFiles();  
           for(int i=0;i<inputFiles.length;i++)  
           {  
                addImageToVideo(inputFiles[i].getAbsolutePath());  
                inputFiles[i].delete();  
           }  
      }  
      public static FFmpegFrameRecorder getRecorder() throws Exception  
      {  
            if(recorder!=null)  
            {  
                 return recorder;  
            }  
            recorder = new FFmpegFrameRecorder(outputVideo,videoWidth,videoHeight);  
            try  
            {  
            recorder.setFrameRate(videoFrameRate);  
      recorder.setVideoCodec(videoCodec);  
      recorder.setVideoBitrate(videoBitRate);  
      recorder.setFormat(videoFormat);  
      recorder.setVideoQuality(videoQuality); // maximum quality  
      recorder.start();  
            }  
            catch(Exception e)  
            {  
                 JOptionPane.showMessageDialog(frame, "Exception while starting the recorder object "+e.getMessage());  
                 System.out.println("Exception while starting the recorder object "+e.getMessage());  
                 throw new Exception("Unable to start recorder");  
            }  
      return recorder;  
      }  
      public static OpenCVFrameConverter.ToIplImage getFrameConverter()  
      {  
           OpenCVFrameConverter.ToIplImage grabberConverter = new OpenCVFrameConverter.ToIplImage();  
           return grabberConverter;  
      }  
      public static void addImageToVideo(String imgPath)  
      {  
           try {  
                getRecorder().record(getFrameConverter().convert(cvLoadImage(imgPath)));  
           } catch (Exception e) {  
                JOptionPane.showMessageDialog(frame, "Exception while adding image to video "+e.getMessage());  
                System.out.println("Exception while adding image to video "+e.getMessage());  
           }  
      }  
      public static void stopRecording()  
      {  
           try {  
                videoComplete=true;  
                System.out.println("Stopping recording at "+new Date());  
                t1.join();  
                System.out.println("Screenshot thread complete");  
                t2.join();  
                System.out.println("Video maker thread complete");  
                getRecorder().stop();  
                System.out.println("Recording has been saved successfully at "+new File(outputVideo).getAbsolutePath());  
                JOptionPane.showMessageDialog(frame, "Recording has been saved successfully at "+new File(outputVideo).getAbsolutePath());  
           } catch (Exception e) {  
                System.out.println("Exception while stopping the recorder "+e.getMessage());  
           }  
      }  
 }  

CropRegion.java
 package com.cooltrickshome;  
 import java.awt.AWTException;  
 import java.awt.Dimension;  
 import java.awt.FlowLayout;  
 import java.awt.Graphics;  
 import java.awt.Rectangle;  
 import java.awt.Robot;  
 import java.awt.Toolkit;  
 import java.awt.event.MouseEvent;  
 import java.awt.event.MouseListener;  
 import java.awt.event.MouseMotionListener;  
 import java.awt.image.BufferedImage;  
 import java.io.IOException;  
 import javax.swing.JFrame;  
 import javax.swing.JLabel;  
 import javax.swing.JOptionPane;  
 public class CropRegion implements MouseListener,  
           MouseMotionListener {  
      int drag_status = 0;  
      int c1;  
      int c2;  
      int c3;  
      int c4;  
      JFrame frame=null;  
      static int counter=0;  
      JLabel background=null;  
      public void getImage() throws AWTException, IOException, InterruptedException {  
           Dimension size = Toolkit.getDefaultToolkit().getScreenSize();  
        Robot robot = new Robot();  
        BufferedImage img = robot.createScreenCapture(new Rectangle(size));  
        ImagePanel panel = new ImagePanel(img);  
        frame=new JFrame();  
        frame.add(panel);  
        frame.setLocation(0, 0);  
        frame.setSize(size);  
        frame.setLayout(new FlowLayout());  
        frame.setUndecorated(true);  
        frame.setVisible(true);  
        frame.addMouseListener(this);  
        frame.addMouseMotionListener(this);  
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);  
      }  
      public void draggedScreen() throws Exception {  
           ScreenRecorder.c1=c1;  
           ScreenRecorder.c2=c2;  
           ScreenRecorder.c3=c3;  
           ScreenRecorder.c4=c4;  
           ScreenRecorder.isRegionSelected=true;  
           JOptionPane.showMessageDialog(frame, "Region Selected.Please click on Start Recording button to record the selected region.");  
           frame.dispose();  
      }  
      public void mouseClicked(MouseEvent arg0) {  
      }  
      public void mouseEntered(MouseEvent arg0) {  
      }  
      public void mouseExited(MouseEvent arg0) {  
      }  
      public void mousePressed(MouseEvent arg0) {  
           paint();  
           this.c1 = arg0.getX();  
           this.c2 = arg0.getY();  
      }  
      public void mouseReleased(MouseEvent arg0) {  
           paint();  
           if (this.drag_status == 1) {  
                this.c3 = arg0.getX();  
                this.c4 = arg0.getY();  
                try {  
                     draggedScreen();  
                } catch (Exception e) {  
                     e.printStackTrace();  
                }  
           }  
      }  
      public void mouseDragged(MouseEvent arg0) {  
           paint();  
           this.drag_status = 1;  
           this.c3 = arg0.getX();  
           this.c4 = arg0.getY();  
      }  
      public void mouseMoved(MouseEvent arg0) {  
      }  
      public void paint() {  
           Graphics g = frame.getGraphics();  
           frame.repaint();  
           int w = this.c1 - this.c3;  
           int h = this.c2 - this.c4;  
           w *= -1;  
           h *= -1;  
           if (w < 0) {  
                w *= -1;  
           }  
           g.drawRect(this.c1, this.c2, w, h);  
      }  
 }  

ImagePanel.java
 package com.cooltrickshome;  
 import java.awt.Dimension;  
 import java.awt.Graphics;  
 import java.awt.Image;  
 import javax.swing.ImageIcon;  
 import javax.swing.JPanel;  
 class ImagePanel  
  extends JPanel  
 {  
  private Image img;  
  public ImagePanel(String img)  
  {  
   this(new ImageIcon(img).getImage());  
  }  
  public ImagePanel(Image img)  
  {  
   this.img = img;  
   Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));  
   setPreferredSize(size);  
   setMinimumSize(size);  
   setMaximumSize(size);  
   setSize(size);  
   setLayout(null);  
  }  
  public void paintComponent(Graphics g)  
  {  
   g.drawImage(this.img, 0, 0, null);  
  }  
 }  


Note:
I am not sure if there could be a way to reduce the resulting video size. If you have please let me know
Right now I am using an int variable named counter to name the screenshot. For a long recording this will cause an issue since int range will be exhausted. Need to think about an alternative for same.
I have recorded for few minutes but haven't tested for longer duration.

If you have any suggestions on this, please feel free to contact me via comments or directly at my email cs.anurag.jain@gmail.com :)

Hope it helps :)