Java无法足够快地记录屏幕

时间:2013-11-30 05:15:14

标签: java swing screen-capture recording

我正在尝试用Java创建一个记录程序。我宁愿不使用除JMF(Java Media Framework)之外的任何外部库。我正在使用两个Swing Timers(作为它的Swing应用程序),一个用于捕获屏幕&将它添加到队列中,另一个将BufferedImage从队列中取出把它写到文件中。这是我的计时器: 要插入队列:

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();
                    }
                }
            });
        }
    });

要写图像:

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();
                    }
                }
            });

我的问题是它似乎没有足够快的记录。例如,默认值为25 FPS,我只获得6 FPS。我试过改变许多不同的东西&amp;在互联网上搜索,我找不到解决方案。我想知道我在哪里得到足够快的记录。提前感谢任何想出来的人(我已经坚持了三天)。

编辑:我计划将其更改为一个计时器&amp;使用一种方法来写(我最初有两个因为写延迟),如SimonC所说。

3 个答案:

答案 0 :(得分:1)

试试Monte Media Library screen recorder。我上次测试时得到了很好的结果。

  

Windows Media Player说它无法打开它..

AFAIR WMP用所有 MOV表示。非常恼人,因为它声称文件关联。尝试使用非WMP的播放器。


从长远来看,您可能希望将MOV转换为其他格式。使用JMF生成的是 huge。

答案 1 :(得分:0)

尝试独立于计时器运行这些线程。我的意思是,不要使用这些计时器。使用Thread启动sleep(1000/FPS)并实施时间安排。

答案 2 :(得分:0)

使用Swing Timer保持屏幕捕获任务是值得的,但是图像编写任务应该在添加后立即移动到简单的Thread拉出队列中的图像。由于您将在多个线程之间进行协调,因此请考虑将队列更改为BlockingQueue