Java不能足够快地记录屏幕 [英] Java can't record the screen fast enough
问题描述
我正在尝试用 Java 制作一个记录程序.我不想使用 JMF(Java 媒体框架)以外的任何外部库.我正在使用两个 Swing 计时器(作为它的 Swing 应用程序),一个用于捕获屏幕和将其添加到队列中,另一个将 BufferedImage 从队列中取出 &将其写入文件.这是我的计时器:插入队列:
timer = new Timer(1000/FPS, new ActionListener() {//FPS 是用户输入的值,从 1-60 默认为 25@覆盖public void actionPerformed(ActionEvent ae) {executor.execute(new Runnable() {//executor 是一个 java.util.concurrent.Executor;//我把它们放在一个执行器中,这样计时器就不会等待代码完成@覆盖公共无效运行(){尝试 {图像.插入(R.createScreenCapture(屏幕));//图像是我自己的队列&R 是一个 java.awt.Robot//屏幕是一个矩形,即 Toolkit.getDefaultToolkit().getScreenSize()} 捕获(异常 e){ExceptionPrinter.PrintE(e);//这只是一个打印异常给我的方法System.out.print(images.length());定时器停止();timer2.stop();} catch (OutOfMemoryError e) {//这个主要是debug catch定时器停止();timer2.stop();System.out.print(images.length());e.printStackTrace();}}});}});
写入图像:
timer2 = new Timer(1000/FPS, new ActionListener() {@覆盖public void actionPerformed(ActionEvent ae) {executor.execute(new Runnable() {@覆盖公共无效运行(){尝试 {如果(图像.长度()!= 0){if (!(new File("C:").getFreeSpace() <= 10000000)) {String path=AppRunner.AppR3Directory + "VideoTemp" + File.pathSeparator + file + getModifier() + File.pathSeparator + image + ".JPEG";//AppRunner.AppR3Directory 是程序的工作目录(永不改变)//file 是用户输入的文件名 &getModifier() 是 "" 或大于 0 的数字(用于程序自动启动另一条记录时)ImageIO.write(images.pop(), "JPEG", new java.io.File(path));图像列表.添加(路径);//这会将它添加到我的图像列表中,以便我将其更改为 .mov(自定义数组)图像++;} 别的 {throw new SecurityException("内存不足!");}}} catch (IOException e) {ExceptionPrinter.PrintE(e);定时器停止();timer2.stop();} catch (SecurityException e) {ExceptionPrinter.PrintE(e);定时器停止();timer2.stop();}}});
我的问题是它似乎记录得不够快.例如,默认值为 25 FPS,我只能得到 6 FPS.我试过改变许多不同的东西 &在互联网上搜索,我找不到解决方案.我想找出让这个记录足够快的地方我不正确的地方.提前感谢任何解决问题的人(我已经坚持了三天).
我确实计划将其更改为一个计时器 &使用SimonC所说的写方法(我本来有两个,因为写延迟).
一>.我上次测试时得到了很好的结果.
<块引用>Windows Media Player 说无法打开它..
AFAIR WMP 说所有 MOV.很烦人,因为它声称文件关联.用不是 WMP 的播放器试试.
<小时>从长远来看,您可能希望将 MOV 转换为另一种格式.使用 JMF 生成的内容巨大.
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.
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.
这篇关于Java不能足够快地记录屏幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!