我正在尝试从MJPEG流中捕获图像(jpeg)
根据本教程http://www.walking-productions.com/notslop/2010/04/20/motion-jpeg-in-flash-and-java/我应该只保存从Content-Length:开始到–myboundary结束的日期
但由于某种原因,当我打开保存的文件时,我会收到以下消息:无法打开此图片,因为文件似乎已损坏、损坏或太大。
public class MJPEGParser{
public static void main(String[] args){
new MJPEGParser("http://192.168.0.100/video4.mjpg");
}
public MJPEGParser(String mjpeg_url){
try{
URL url = new URL(mjpeg_url);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line;
while((line = in.readLine()) != null){
System.out.println(line);
if(line.contains("Content-Length:")){
BufferedWriter out = new BufferedWriter(new FileWriter("out.jpeg"));
String content = in.readLine();
while(!content.contains("--myboundary")){
out.write(content);
System.out.println(content);
content = in.readLine();
}
out.close();
in.close();
System.exit(0);
}
}
in.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
我将非常感谢任何提示。
有很多事情可能会导致您的代码失败:
-
并不是所有的MJPEG流都是按照教程建议的类似MIME的方式编码的
引用维基百科:[…]没有任何文档定义了一种单一的精确格式,该格式被公认为"运动JPEG"的完整规范,可在所有上下文中使用。
例如,可以使用MJPEG作为AVI(即RIFF)文件的视频编解码器。因此,请确保您的输入文件是教程所描述的格式。
- 文本
--myboundary
几乎可以肯定是一个占位符。在典型的多部分MIME消息中,全局MIME标头将提供boundary
属性,指示实际用于分隔部分的字符串。您必须在这里给出的字符串前面加上--
- 在使用
Reader
和Writer
时,操作的是字符,而不是字节。根据您的区域设置,这两者之间可能没有1:1的对应关系,从而打破了过程中数据的二进制格式。您应该对字节流进行操作,或者显式地使用一些字符编码,如ISO-8859-1,确实具有这样的1:1对应关系
我最近试图解决这个问题,我的谷歌研究多次将我带到这里。我最终解决了这个问题。关键部分是使用BufferedInputStream
和FileOutputStream
读取和写入jpeg字节,同时将字节缓冲区连接到字符串中,以读取和识别帧之间的标头:
int inputLine;
String s="";
byte[] buf = new byte[1]; //reading byte by byte
URL url = new URL("http://127.0.0.1:8080/?action=stream");
BufferedInputStream in = new BufferedInputStream(url.openStream());
OutputStream out = new FileOutputStream("output.jpg");
while ((inputLine = in.read(buf)) != -1) {
s= s+ new String(buf, 0, inputLine);
if (s.contains("boundarydonotcross")){
System.out.println("Found a new header");
s="";
}
如果有人需要,完整的代码就在这里:
https://github.com/BabelCoding/MJPEG-to-JPG