2

I am trying to make a record program in Java. I would prefer not to use any external libraries other than JMF (Java Media Framework). I am using two Swing Timers (as its a Swing application), one to capture the screen & add it to a queue and the other to take the BufferedImage out of the queue & write it to a file. Here are my timers: To insert into the queue:

timer = new Timer(1000/FPS, new ActionListener() { //FPS is a user-inputed value from 1-60 by default its 25
        @Override
        public void actionPerformed(ActionEvent ae) {
            executor.execute(new Runnable() { //executor is a java.util.concurrent.Executor;
                //I put them in an executor so the timer wouldn't wait for the code to finish
                @Override
                public void run() {
                    try {
                        images.insert(R.createScreenCapture(Screen)); //Images is my own queue & R is a java.awt.Robot
                        //Screen is a rectangle that is Toolkit.getDefaultToolkit().getScreenSize()
                    } catch (Exception e) {
                        ExceptionPrinter.PrintE(e); //This is just a method to print the exception to me
                        System.out.print(images.length());
                        timer.stop();
                        timer2.stop();
                    } catch (OutOfMemoryError e) { //This is mainly a debug catch
                        timer.stop();
                        timer2.stop();
                        System.out.print(images.length());
                        e.printStackTrace();
                    }
                }
            });
        }
    });

To write the image:

timer2 = new Timer(1000 / FPS, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (images.length() != 0) {
                            if (!(new File("C:").getFreeSpace() <= 10000000)) {
                                String path=AppRunner.AppR3Directory + "VideoTemp" + File.pathSeparator + file + getModifier() + File.pathSeparator + image + ".JPEG";
                                //AppRunner.AppR3Directory is the working directory of the program (never changes)
                                //file is the user-inputed filename & getModifier() is either "" or a number above 0 (for when the program auto-starts another record)
                                ImageIO.write(images.pop(), "JPEG", new java.io.File(path));
                                imagelist.add(path); //This adds it to my list of images for when i change it to a .mov (custom array)
                                image++;
                            } else {
                                throw new SecurityException("Not enough memory!");
                            }
                        }
                    } catch (IOException e) {
                        ExceptionPrinter.PrintE(e);
                        timer.stop();
                        timer2.stop();
                    } catch (SecurityException e) {
                        ExceptionPrinter.PrintE(e);
                        timer.stop();
                        timer2.stop();
                    }
                }
            });

My problem is that it doesn't seem to record fast enough. For example with the default value of 25 FPS I only get 6 FPS. I have tried changing many different things & searched all over the internet and I can not find a solution. I would like to find out where I am incorrect in getting this to record fast enough. Thanks in advance to anyone that figures it out (I have been stuck on this for three days).

Edit: I do plan to change it to one timer & using a method to write (I originally had two because of the write delay) as said by SimonC.

David L
  • 33
  • 6
  • *"For example with the default value of 25 FPS I only get 6 FPS."* What screen resolution is that at? For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Nov 30 '13 at 05:20
  • What is `FPS` declared as? This is also a common issue, it simply takes to much time to capture the entire screen... – MadProgrammer Nov 30 '13 at 05:21
  • @Andrew Thompson: My screen resolution is 1366 x 768 – David L Nov 30 '13 at 05:59
  • @MadProgrammer it is a int value retrieved from a JSlider – David L Nov 30 '13 at 06:00
  • The speed part has already been asked a few month ago: http://stackoverflow.com/questions/17665529/faster-alternative-to-java-awt-robot-createscreencapture. The bug http://bugs.sun.com/view_bug.do?bug_id=5090776 of 2004 has not been closed yet. – Wolfgang Fahl Nov 30 '13 at 07:19

3 Answers3

1

Try the Monte Media Library screen recorder. I got good results from it last time I tested.

Windows Media Player says it can't open it..

AFAIR WMP says that with all MOVs. Quite irritating, given that it claims the file association. Try it with a player that is not WMP.


As to the longer term, you would be looking to convert the MOV to another format. The ones produced using JMF are huge.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
0

Try to run these threads independetly from timers. I mean, do not use these timers. Start Thread and implement timeing by using sleep(1000/FPS).

polis
  • 795
  • 7
  • 23
0

It's worth keeping the screen capture task using the Swing Timer, but the image writing task should be moved to a simple Thread pulling images off the queue as soon as they are added. Since you would then be co-ordinating between multiple threads, consider changing your queue to a BlockingQueue.

SimonC
  • 6,590
  • 1
  • 23
  • 40
  • From everything that I understand, it should be safe to call `Robot#createScreenCapture` outside the EDT...I could be wrong so I just wanted to ask if you knew something I didn't ;) – MadProgrammer Nov 30 '13 at 06:04