Bildschirmvideo mit java

Windhund

Mitglied
Hallo liebe Community

Ich bin auf der Suche nach einer Möglichkeit mit Java 30 oder mehr Bildschirmfotos pro Sekunde zu machen.

Suche schon seid einiger Zeit aber habe bis jetzt nichts brauchbares gefunden. Nur immer wieder ansätze mit der getScreenCapture Funktion der Robot Klasse. Die ist aber effektiv VIEL zu langsam, damit komm ich grademal auf 5 Bilder pro Sekunde.

Habe schon versucht durch Threads die anzahl zu erhöhen, leider erfolglos.

Eine andere Möglichkeit als diese Robot Klasse scheint es nicht zu geben um einen Screenshoot zu erstellen. Ich finde zumindest keine, lasse mir aber auch liebend gerne eines besseren Belehren :)

Würde mich über ein paar Ideen die ich noch ausprobieren könnte sehr freuen.
 
Hallo,

mit java.awt.Robot kann man in Verbindung mit einem schnellen JpegEncoder auf auf 25 Bilder / Sekunde kommen... wenn man mit dem Robot ein screen capture erstellt hat, darf man das nicht im selben Thread auf die Platte speichern, dass kostet zu viel Zeit. Hier bietet es sich an, die IO Operationen in eine Queue zu schreiben und diese asynchron von einem anderen Thread abarbeiten zu lassen....

Java:
package de.tutorials;

import java.awt.AWTException;
import java.awt.DisplayMode;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import static java.util.concurrent.TimeUnit.SECONDS;

public class FastScreenShooterExample {

	public static void main(String[] args) throws Exception {

		try (ScreenGrabber sg = new AWTRobotScreenGrabber()) {
			
			int benchmarkPeriodInSeconds = 10;
			long endTime = System.currentTimeMillis() + SECONDS.toMillis(benchmarkPeriodInSeconds);
			
			int grabs = 0;
			while (System.currentTimeMillis() < endTime) {
				sg.grabAndOutput("d:/temp/screens", "screen" + grabs);
				grabs++;
			}
			System.out.printf("%s grabs/s", grabs / benchmarkPeriodInSeconds).println();

		}

	}

	static interface ScreenGrabber extends Closeable {
		void grabAndOutput(String path, String imageName);
	}

	static abstract class AbstractScreenGrabber implements ScreenGrabber {
		protected Rectangle screenRect;

		protected ExecutorService imageWriterService;

		public AbstractScreenGrabber() {
			DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
			this.screenRect = new Rectangle(0, 0, displayMode.getWidth(),displayMode.getHeight());
			this.imageWriterService = Executors.newSingleThreadExecutor();
		}
		
		@Override
		public void grabAndOutput(String path, String imageName) {
			BufferedImage screenshot = grab();
			write(screenshot, path, imageName);
		}
		
		protected abstract BufferedImage grab();

		private void write(BufferedImage screenshot, String path, String imageName) {
			imageWriterService.submit(new WriteImageCommand(screenshot, path,imageName));
		}

		@Override
		public void close() throws IOException {
			imageWriterService.shutdown();
		}
	}

	static class AWTRobotScreenGrabber extends AbstractScreenGrabber {

		private Robot robot;

		public AWTRobotScreenGrabber() {
			try {
				this.robot = new Robot();
			} catch (AWTException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public BufferedImage grab() {
			return grab(this.screenRect);
		}

		public BufferedImage grab(Rectangle screenRect) {
			return robot.createScreenCapture(screenRect);
		}
	}
	
	static class WriteImageCommand implements Runnable {

		private final BufferedImage screenshot;
		private final String path;
		private final String imageName;

		public WriteImageCommand(BufferedImage screenshot, String path,String imageName) {
			this.screenshot = screenshot;
			this.path = path;
			this.imageName = imageName;
		}

		@Override
		public void run() {
			try (BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File(path, imageName + ".jpg")))) {
				//you have to disable the error for restricted / deprecated api ...
				JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bout);
				encoder.encode(screenshot);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

Ansonsten schau mal hier:
http://www.tutorials.de/java/260004-remote-screen-ubertragung-war-remote-anwendung-corba.html


Eine weitere (eventuell schnellere) Möglichkeit wäre Screenshots regelmäßig mit einem Command Line Utility (http://superuser.com/questions/75614/take-a-screen-shot-from-command-line-in-windows) zu erstellen, aber ich denke wenn man den Robot geschickt nutzt ist der schnell genug.

... wenn es hier um "richtige" Filme und keine bloßen Bilderfolgen gehen soll würde ich empfehlen zu ein Tool wie ffmpeg zu verwenden.
http://wiki.oz9aec.net/index.php/High_quality_screen_capture_with_Ffmpeg

Gruß Tom
 
Cool

Auf jedenfall schonmal vielen dank für die schnelle Antwort.

Werde mich mal durch den code und die Links durcharbeiten :)
 
Zurück