如何开发屏幕截图到video应用程序
我在stackoverflow中发现了类似的问题。 但我想要具体。 我访问了一个网站screencast-o-matic 。 他们有一个java applet的web应用程序,它捕获屏幕以导出为video。 我想开发类似的应用程序。 这样做需要哪些知识和步骤?
感谢致敬。
编辑另一个网站屏幕 。
- 要获取屏幕截图,请使用
Robot.createScreenCapture(Rectangle)
。 - 要获得许多屏幕截图,请在(Swing)
Timer
调用的循环中调用它。 将它们添加到可扩展的集合(如ArrayList
。 - 使用
ImageIO.write()
将BufferedImage
对象转换为JPEG格式。 - 要将这些屏幕截图组成一个.MOV,请使用JMF的JpegImagesToMovie(是的JMF已过时,但仍可正常工作的部件,工作正常)。
由于我找不到JpegImagesToMovie来源的爱情和搜索的副本,这里是一个旧版本,我适合我使用。 我认为这个版本是在进行任何更改之前。
请注意,Java applet需要经过数字签名(由您)和受信任(由最终用户)才能获得单个屏幕截图。 它还需要信任(或插件2 JRE中的JNLP API服务)才能将MOV保存到客户端的本地文件系统。
JpegImagesToMovie.java
/* * @(#)JpegImagesToMovie.java 1.3 01/03/13 * * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */ import java.io.*; import java.util.*; import java.awt.Dimension; import javax.media.*; import javax.media.control.*; import javax.media.protocol.*; import javax.media.protocol.DataSource; import javax.media.datasink.*; import javax.media.format.VideoFormat; /** * This program takes a list of JPEG image files and convert them into * a QuickTime movie. */ public class JpegImagesToMovie implements ControllerListener, DataSinkListener { public boolean doIt(int width, int height, int frameRate, Vector inFiles, MediaLocator outML) { ImageDataSource ids = new ImageDataSource(width, height, frameRate, inFiles); Processor p; try { System.err.println("- create processor for the image datasource ..."); p = Manager.createProcessor(ids); } catch (Exception e) { System.err.println("Yikes! Cannot create a processor from the data source."); return false; } p.addControllerListener(this); // Put the Processor into configured state so we can set // some processing options on the processor. p.configure(); if (!waitForState(p, p.Configured)) { System.err.println("Failed to configure the processor."); return false; } // Set the output content descriptor to QuickTime. p.setContentDescriptor(new ContentDescriptor(FileTypeDescriptor.QUICKTIME)); // Query for the processor for supported formats. // Then set it on the processor. TrackControl tcs[] = p.getTrackControls(); Format f[] = tcs[0].getSupportedFormats(); if (f == null || f.length <= 0) { System.err.println("The mux does not support the input format: " + tcs[0].getFormat()); return false; } tcs[0].setFormat(f[0]); System.err.println("Setting the track format to: " + f[0]); // We are done with programming the processor. Let's just // realize it. p.realize(); if (!waitForState(p, p.Realized)) { System.err.println("Failed to realize the processor."); return false; } // Now, we'll need to create a DataSink. DataSink dsink; if ((dsink = createDataSink(p, outML)) == null) { System.err.println("Failed to create a DataSink for the given output MediaLocator: " + outML); return false; } dsink.addDataSinkListener(this); fileDone = false; System.err.println("start processing..."); // OK, we can now start the actual transcoding. try { p.start(); dsink.start(); } catch (IOException e) { System.err.println("IO error during processing"); return false; } // Wait for EndOfStream event. waitForFileDone(); // Cleanup. try { dsink.close(); } catch (Exception e) {} p.removeControllerListener(this); System.err.println("...done processing."); return true; } /** * Create the DataSink. */ DataSink createDataSink(Processor p, MediaLocator outML) { DataSource ds; if ((ds = p.getDataOutput()) == null) { System.err.println("Something is really wrong: the processor does not have an output DataSource"); return null; } DataSink dsink; try { System.err.println("- create DataSink for: " + outML); dsink = Manager.createDataSink(ds, outML); dsink.open(); } catch (Exception e) { System.err.println("Cannot create the DataSink: " + e); return null; } return dsink; } Object waitSync = new Object(); boolean stateTransitionOK = true; /** * Block until the processor has transitioned to the given state. * Return false if the transition failed. */ boolean waitForState(Processor p, int state) { synchronized (waitSync) { try { while (p.getState() < state && stateTransitionOK) waitSync.wait(); } catch (Exception e) {} } return stateTransitionOK; } /** * Controller Listener. */ public void controllerUpdate(ControllerEvent evt) { if (evt instanceof ConfigureCompleteEvent || evt instanceof RealizeCompleteEvent || evt instanceof PrefetchCompleteEvent) { synchronized (waitSync) { stateTransitionOK = true; waitSync.notifyAll(); } } else if (evt instanceof ResourceUnavailableEvent) { synchronized (waitSync) { stateTransitionOK = false; waitSync.notifyAll(); } } else if (evt instanceof EndOfMediaEvent) { evt.getSourceController().stop(); evt.getSourceController().close(); } } Object waitFileSync = new Object(); boolean fileDone = false; boolean fileSuccess = true; /** * Block until file writing is done. */ boolean waitForFileDone() { synchronized (waitFileSync) { try { while (!fileDone) waitFileSync.wait(); } catch (Exception e) {} } return fileSuccess; } /** * Event handler for the file writer. */ public void dataSinkUpdate(DataSinkEvent evt) { if (evt instanceof EndOfStreamEvent) { synchronized (waitFileSync) { fileDone = true; waitFileSync.notifyAll(); } } else if (evt instanceof DataSinkErrorEvent) { synchronized (waitFileSync) { fileDone = true; fileSuccess = false; waitFileSync.notifyAll(); } } } public static void main(String args[]) { if (args.length == 0) prUsage(); // Parse the arguments. int i = 0; int width = -1, height = -1, frameRate = 1; Vector inputFiles = new Vector(); String outputURL = null; while (i < args.length) { if (args[i].equals("-w")) { i++; if (i >= args.length) prUsage(); width = new Integer(args[i]).intValue(); } else if (args[i].equals("-h")) { i++; if (i >= args.length) prUsage(); height = new Integer(args[i]).intValue(); } else if (args[i].equals("-f")) { i++; if (i >= args.length) prUsage(); frameRate = new Integer(args[i]).intValue(); } else if (args[i].equals("-o")) { i++; if (i >= args.length) prUsage(); outputURL = args[i]; } else { inputFiles.addElement(args[i]); } i++; } if (outputURL == null || inputFiles.size() == 0) prUsage(); // Check for output file extension. if (!outputURL.endsWith(".mov") && !outputURL.endsWith(".MOV")) { System.err.println("The output file extension should end with a .mov extension"); prUsage(); } if (width < 0 || height < 0) { System.err.println("Please specify the correct image size."); prUsage(); } // Check the frame rate. if (frameRate < 1) frameRate = 1; // Generate the output media locators. MediaLocator oml; if ((oml = createMediaLocator(outputURL)) == null) { System.err.println("Cannot build media locator from: " + outputURL); System.exit(0); } JpegImagesToMovie imageToMovie = new JpegImagesToMovie(); imageToMovie.doIt(width, height, frameRate, inputFiles, oml); System.exit(0); } static void prUsage() { System.err.println("Usage: java JpegImagesToMovie -w -h -f -o
java屏幕录像机库:
https://code.google.com/p/java-screen-recorder/
你需要包含java-screen-recorder lib中的所有.jar
以及jmf
lib(可以在http://www.oracle.com/technetwork/java/javase/download-142937.html下载)以确保RecordingConverter
正在工作。
例
try { //Temp file for the Recorder File file = new File("D:\\Users\\USER\\Desktop", "screen.cap"); OutputStream out = new FileOutputStream(file); ScreenRecorder screenRecorder = new DesktopScreenRecorder(out,this); screenRecorder.startRecording(); try { Thread.sleep(5000); screenRecorder.stopRecording(); //We reformat the video to .mov file RecordingConverter.main(new String[]{file.getAbsolutePath()}); } catch(InterruptedException e) { e.printStackTrace(); } out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }