Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从截图生成视频提要的备选方案_Java_Screenshot_Video Capture_Video Encoding - Fatal编程技术网

Java 从截图生成视频提要的备选方案

Java 从截图生成视频提要的备选方案,java,screenshot,video-capture,video-encoding,Java,Screenshot,Video Capture,Video Encoding,我在一个远程管理玩具项目中工作。现在,我可以使用机器人类捕捉屏幕截图并控制鼠标。屏幕截图是buffereImage实例 首先,我的要求: -只有服务器和客户端。 -性能很重要,因为客户端可能是Android应用程序 我考虑过打开两个套接字连接,一个用于鼠标和系统命令,另一个用于视频提要 如何将截图转换为视频流?我应该将它们转换为已知的视频格式,还是只发送一系列序列化图像就可以了 压缩是另一个问题。根据我的初步测试,以全分辨率发送屏幕截图会导致低帧速率。我想我至少需要24帧来感知运动,所以我必须缩

我在一个远程管理玩具项目中工作。现在,我可以使用
机器人
类捕捉屏幕截图并控制鼠标。屏幕截图是
buffereImage
实例

首先,我的要求: -只有服务器和客户端。 -性能很重要,因为客户端可能是Android应用程序

我考虑过打开两个套接字连接,一个用于鼠标和系统命令,另一个用于视频提要

如何将截图转换为视频流?我应该将它们转换为已知的视频格式,还是只发送一系列序列化图像就可以了

压缩是另一个问题。根据我的初步测试,以全分辨率发送屏幕截图会导致低帧速率。我想我至少需要24帧来感知运动,所以我必须缩小和压缩。我可以将
BufferedImages
转换为jpg文件,然后设置压缩率,但我不想将文件存储在磁盘上,它们应该只存在于RAM中。另一种可能是将实例(表示未压缩的屏幕截图)序列化为GZipOutputStream。正确的方法是什么

总结如下:

  • 如果您推荐“图像系列”方法,您将如何将它们序列化到套接字
    OutputStream
  • 如果您的建议是转换为已知的视频格式,那么哪些类或库可用
提前谢谢

更新:我的测试,客户端和服务器在同一台机器上
-全屏序列化BuffereImage(仅维度、类型和int[]),无压缩:1.9 fps。
-通过GZip流的全屏图像:每秒2.6帧。
-缩小的图像(640宽)和GZip流:6.56 fps。
-全屏图像和RLE编码:4.14 fps。

-缩小规模的图像和RLE编码:7.29 fps。

我认为您在问题中描述了一个很好的解决方案。将图像转换为jpeg格式,但不要将其作为文件写入磁盘。如果希望它是已知的视频格式,请使用M-JPEG。是标准格式的jpeg帧流。许多数码相机,尤其是老式相机,都是以这种格式保存视频的

您可以从以下问题的答案中获得有关如何播放M-JPEG流的一些信息:


如果网络带宽是一个问题,那么您需要使用帧间压缩系统,如MPEG-2、h.264或类似系统。这比M-JPEG需要更多的处理,但效率要高得多。

首先,我可能建议只捕获屏幕的一小部分,而不是缩小尺寸并可能丢失信息,也许可以使用滑动窗口之类的东西,通过光标推动边缘来移动。这只是一个小小的设计建议

至于压缩,我认为一系列图像不会单独压缩,也不会使用合适的视频压缩方案进行压缩,特别是在这种情况下,帧可能在捕获之间保持一致

一个选择是使用Xugle,它能够通过Robot以多种视频格式afaiu捕获桌面,但我不知道你是否可以用它进行流媒体和解码

对于捕获JPEG并转换它们,您还可以使用

不过,流式播放这些视频似乎有点复杂

此外,似乎废弃的Java媒体框架支持此功能

我在这方面的知识不是很好,所以如果我浪费了你的时间,我很抱歉,但是似乎已经编译了一些关于使用Xugle作为屏幕共享器可行性的更有用的信息。这似乎也与他们自己关于现有方法的说明相联系

如果它不需要纯Java,我想这一切都会更容易使用,只需与本机屏幕捕获工具接口


也许这将是最简单的只是发送视频作为一系列的JPEG毕竟!如果你觉得有点疯狂,你可以实现你自己的压缩方案…

如果只是屏幕截图,我不会使用视频压缩方案来压缩它们,很可能你不想要有损压缩(小文本中的模糊细节等是最常见的缺陷)。 为了获得一个可行的“远程桌面”感觉,请记住之前发送的屏幕截图,只发送差异即可进入下一个屏幕截图。如果帧之间没有变化(或变化很小),这是非常有效的。 但是,在某些情况下,如玩视频、游戏或在文档中大量滚动,它将无法正常工作

压缩两个BuffereImage之间的差异可以使用或多或少复杂的方法来完成,一个非常简单但相当有效的方法是简单地从另一个图像中减去一个图像(导致它们完全相同的地方都是零),然后使用简单的RLE(游程编码)压缩结果

降低颜色精度可用于进一步减少数据量(根据使用情况,您可以省略每个颜色通道的最低有效N位,因为如果您将颜色从24位减少到15位,大多数GUI应用程序看起来没有太大差异)。

  • 将屏幕分成网格正方形(或条带)
  • 仅当网格方块与前一个不同时才发送网格方块
//服务器启动

sendScreenMetaToClient(); // width, height, how many grid squares
...

// server loop ImageBuffer[] prevScrnGrid while(isRunning) {

ImageBuffer scrn = captureScreen();
ImageBuffer[] scrnGrid = screenToGrid(scrn);
for(int i = 0; i < scrnGrid.length; i++) {
    if(isSameImage(scrnGrid[i], prevScrnGrid[i]) == false) {
        prevScrnGrid[i] = scrnGrid[i];
        sendGridSquareToClient(i, scrnGrid[i]); // send the client a message saying it will get grid square (i) then send the bytes for grid square (i)
    }
} }

如果您试图获得24fps视频,那么没有理由不使用现代视频编解码器。为什么要试着重新创造那个轮子


编码h264视频效果很好,听起来它能很好地满足您的需要。

尝试通过GZip流全屏发送包含BuffereImage数据的序列化holder对象。即使在同一台机器上运行客户端和服务器,帧速率也非常低(约1 fps)。很可能我会选择视频。我认为视频格式将提供关键帧压缩,这是ba
ByteArrayOutputStream imgBytes = new ByteArrayOutputStream();
ImageIO.write( bufferedImage, "jpg", imgBytes );
imgBytes.flush();