一種選擇是做多線程的處理。一個線程可以專門用於截屏,而其他線程可以寫入磁盤。由於寫入磁盤不是CPU密集型操作,因此可以同時運行其中的許多操作,每個寫入不同的文件。下面的程序工作正常,我的機器上,擁有512M堆大小:
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ImageWritingMain
{
public static void main(String[] args) throws Exception
{
// a queue
final BlockingQueue<BufferedImage> queue =
new LinkedBlockingQueue<BufferedImage>();
// schedule a thread to take 20 images per second and put them in
// the queue
int fps = 20;
final ScreenShotRecorder recorder =
new ScreenShotRecorder(new Robot(), queue);
Timer timer = new Timer();
timer.scheduleAtFixedRate(recorder, 0, (1000L/fps));
// make a directory to hold the screenshot images
String id = new Date().toString().replace(' ', '-').replace(':', '-');
File imageDir = new File("images-" + id);
imageDir.mkdirs();
// start 10 threads, and each thread reads from the queue and
// writes the image to a file
int nWriterThreads = 10;
ExecutorService threadPool = Executors.newFixedThreadPool(nWriterThreads);
for (int i = 0; i < nWriterThreads; i++)
{
ImageWriter task = new ImageWriter(queue, imageDir);
threadPool.submit(task);
}
System.out.println("Started all threads ..");
// wait as long as you want the program to run (1 minute, for example) ...
Thread.sleep(60 * 1000L);
// .. and shutdown the threads
System.out.println("Shutting down all threads");
threadPool.shutdownNow();
timer.cancel();
if (! queue.isEmpty())
{
System.out.println("Writing " + queue.size() + " remaining images");
// write the remaining images to disk in the main thread
ImageWriter writer = new ImageWriter(queue, imageDir);
BufferedImage img = null;
while ((img = queue.poll()) != null)
{
writer.writeImageToFile(img);
}
}
}
}
class ScreenShotRecorder extends TimerTask
{
private static final Rectangle screenRect =
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
private static final AtomicInteger counter = new AtomicInteger();
private final Robot robot;
private final BlockingQueue<BufferedImage> imageQueue;
ScreenShotRecorder(Robot robot, BlockingQueue<BufferedImage> imageQueue)
{
this.robot = robot;
this.imageQueue = imageQueue;
}
@Override
public void run()
{
try
{
BufferedImage image = robot.createScreenCapture(screenRect);
imageQueue.put(image);
System.out.println(Thread.currentThread() +
": Took screenshot #" + counter.incrementAndGet());
}
catch (InterruptedException e)
{
System.out.println("Finishing execution of " + Thread.currentThread());
return;
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class ImageWriter implements Runnable
{
private static final AtomicInteger counter = new AtomicInteger();
private final BlockingQueue<BufferedImage> imageQueue;
private final File dir;
ImageWriter(BlockingQueue<BufferedImage> imageQueue, File dir)
{
this.imageQueue = imageQueue;
this.dir = dir;
}
@Override
public void run()
{
while (true)
{
try
{
BufferedImage image = imageQueue.take();
writeImageToFile(image);
}
catch (InterruptedException e)
{
System.out.println("Finishing execution of " + Thread.currentThread());
return;
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public void writeImageToFile(BufferedImage image) throws IOException
{
File file = new File(dir, "screenshot-" + counter.incrementAndGet());
ImageIO.write(image, "JPG", file);
System.out.println(Thread.currentThread() +
": Wrote " + file.getCanonicalPath());
}
}
爲了得到20fps的,你應該可以在驅動器 – millimoose 2012-07-05 22:06:08
使用一個真正的視頻編解碼器,而不是爆破JPEG格式的看到的屏幕錄像[蒙媒體庫] (http://www.randelshofer.ch/monte/)可以以20 FPS的速度進行全屏(1920x1080像素)視頻拍攝。它使用JMF&直接編碼到MOV或AVI。 – 2012-07-05 23:19:23
這看起來像我想要的!當我下班回家並報告回來時,我們會有一些樂趣。 – camerongray 2012-07-06 10:45:11