问题
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.
回答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.
回答2:
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)
.
回答3:
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
.
来源:https://stackoverflow.com/questions/20296825/java-cant-record-the-screen-fast-enough