我已经尝试过去两周从网络摄像头录制到文件,但我无法在我的Raspberry Pi模型B +上运行Webcam Capture API。
应用程序启动,但最终冻结而没有任何控制台错误。
Java source code从网络摄像头录制,但最后冻结并留下100%的CPU使用率,直到用ctrl + c终止。
Xuggle Xuggler似乎工作正常,但是甚至可以使用Xuggle Xuggler录制视频吗?
我找到了Xuggle Xuggler的演示,但没有一个来自网络摄像头的记录文件
是否可以使用xuggle xuggler和java库录制视频,还是只是浪费时间?
答案 0 :(得分:0)
这似乎并不浪费时间......
下面的源代码将仅使用Xuggle Xuggler和Java库捕获视频到文件。当仅使用分辨率为320x240或更高的分辨率时,源代码将起作用,因为xuggle xugglers lousy webcam support。
我还在等待更好更快的解决方案,以解决我的原始问题。
package webcam;
import com.xuggle.mediatool.IMediaWriter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IContainerFormat;
import com.xuggle.xuggler.IError;
import com.xuggle.xuggler.IMetaData;
import com.xuggle.xuggler.IPacket;
import com.xuggle.xuggler.IPixelFormat;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;
import com.xuggle.xuggler.IVideoPicture;
import com.xuggle.xuggler.IVideoResampler;
import com.xuggle.xuggler.Utils;
import com.xuggle.xuggler.video.ConverterFactory;
import com.xuggle.xuggler.video.IConverter;
import java.awt.image.BufferedImage;
import java.io.File;
public class Uusi {
@SuppressWarnings("deprecation")
public static void main(String[] args) throws Throwable {
File file = new File("output.h264");
IMediaWriter writer = ToolFactory.makeWriter(file.getName());
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, 320, 240);
String driverName = "vfwcap";
String deviceName = "0";
// Let's make sure that we can actually convert video pixel formats.
if (!IVideoResampler.isSupported(IVideoResampler.Feature.FEATURE_COLORSPACECONVERSION)) {
throw new RuntimeException("you must install the GPL version of Xuggler (with IVideoResampler support) for this demo to work");
}
// Create a Xuggler container object
IContainer container = IContainer.make();
// Tell Xuggler about the device format
IContainerFormat format = IContainerFormat.make();
if (format.setInputFormat(driverName) < 0) {
throw new IllegalArgumentException("couldn't open webcam device: " + driverName);
}
// devices, unlike most files, need to have parameters set in order
// for Xuggler to know how to configure them, for a webcam, these
// parameters make sense
IMetaData params = IMetaData.make();
params.setValue("framerate", "30/1");
params.setValue("video_size", "320x240");
// Open up the container
int retval = container.open(deviceName, IContainer.Type.READ, format,
false, true, params, null);
if (retval < 0) {
// This little trick converts the non friendly integer return value into
// a slightly more friendly object to get a human-readable error name
IError error = IError.make(retval);
throw new IllegalArgumentException("could not open file: " + deviceName + "; Error: " + error.getDescription());
}
// query how many streams the call to open found
int numStreams = container.getNumStreams();
// and iterate through the streams to find the first video stream
int videoStreamId = -1;
IStreamCoder videoCoder = null;
for (int i = 0; i < numStreams; i++) {
// Find the stream object
IStream stream = container.getStream(i);
// Get the pre-configured decoder that can decode this stream;
IStreamCoder coder = stream.getStreamCoder();
if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
videoStreamId = i;
videoCoder = coder;
break;
}
}
if (videoStreamId == -1) {
throw new RuntimeException("could not find video stream in container: " + deviceName);
}
/*
* Now we have found the video stream in this file. Let's open up our decoder so it can
* do work.
*/
if (videoCoder.open() < 0) {
throw new RuntimeException("could not open video decoder for container: " + deviceName);
}
IVideoResampler resampler = null;
if (videoCoder.getPixelType() != IPixelFormat.Type.BGR24) {
// if this stream is not in BGR24, we're going to need to
// convert it. The VideoResampler does that for us.
resampler = IVideoResampler.make(videoCoder.getWidth(), videoCoder.getHeight(), IPixelFormat.Type.BGR24,
videoCoder.getWidth(), videoCoder.getHeight(), videoCoder.getPixelType());
if (resampler == null) {
throw new RuntimeException("could not create color space resampler for: " + deviceName);
}
}
/*
* Now, we start walking through the container looking at each packet.
*/
IPacket packet = IPacket.make();
long start = System.currentTimeMillis();
int i = 0;
while (container.readNextPacket(packet) >= 0 && i < 100) {
/*
* Now we have a packet, let's see if it belongs to our video stream
*/
if (packet.getStreamIndex() == videoStreamId) {
/*
* We allocate a new picture to get the data out of Xuggler
*/
IVideoPicture picture = IVideoPicture.make(videoCoder.getPixelType(),
videoCoder.getWidth(), videoCoder.getHeight());
int offset = 0;
while (offset < packet.getSize()) {
/*
* Now, we decode the video, checking for any errors.
*
*/
int bytesDecoded = videoCoder.decodeVideo(picture, packet, offset);
if (bytesDecoded < 0) {
throw new RuntimeException("got error decoding video in: " + deviceName);
}
offset += bytesDecoded;
/*
* Some decoders will consume data in a packet, but will not be able to construct
* a full video picture yet. Therefore you should always check if you
* got a complete picture from the decoder
*/
if (picture.isComplete()) {
IVideoPicture newPic = picture;
/*
* If the resampler is not null, that means we didn't get the video in BGR24 format and
* need to convert it into BGR24 format.
*/
if (resampler != null) {
// we must resample
newPic = IVideoPicture.make(resampler.getOutputPixelFormat(), picture.getWidth(), picture.getHeight());
if (resampler.resample(newPic, picture) < 0) {
throw new RuntimeException("could not resample video from: " + deviceName);
}
}
if (newPic.getPixelType() != IPixelFormat.Type.BGR24) {
throw new RuntimeException("could not decode video as BGR 24 bit data in: " + deviceName);
}
// Convert the BGR24 to an Java buffered image
BufferedImage javaImage = Utils.videoPictureToImage(newPic);
System.out.println("Capture frame " + i);
BufferedImage image = ConverterFactory.convertToType(javaImage, BufferedImage.TYPE_3BYTE_BGR);
IConverter converter = ConverterFactory.createConverter(image, IPixelFormat.Type.YUV420P);
IVideoPicture frame = converter.toPicture(image, (System.currentTimeMillis() - start) * 1000);
frame.setKeyFrame(i == 0);
frame.setQuality(0);
writer.encodeVideo(0, frame);
i++;
}
}
} else {
/*
* This packet isn't part of our video stream, so we just silently drop it.
*/
do {
} while (false);
}
}
writer.close();
System.out.println("Video recorded in file: " + file.getAbsolutePath());
}
}
更新:在Raspberry Pi Model B +上测试上面的代码时,它会录制视频,但在观看录制的视频时,它似乎处于快速转发状态&#34; -mode 。所以代码并不好,因为在编码视频时,覆盆子比强大的笔记本电脑(Windows 8.1)需要更多的时间。