Java 是否可以仅使用Xuggle Xuggler将视频从网络摄像头录制到文件?

Java 是否可以仅使用Xuggle Xuggler将视频从网络摄像头录制到文件?,java,raspberry-pi,webcam,video-capture,Java,Raspberry Pi,Webcam,Video Capture,在过去的两周里,我尝试了从一个网络摄像头到另一个文件的录制,但我一直无法在我的Raspberry Pi model B+上使用网络摄像头捕获API 应用程序启动,但在最后冻结,没有任何控制台错误 它从网络摄像头录制,但最后会冻结,并保留100%的CPU使用率,直到使用ctrl+c终止 Xuggle Xuggler似乎工作正常,但甚至可以只使用Xuggle Xuggler录制视频吗 我已经找到了Xuggle Xuggler的演示,但没有一个是来自网络摄像头的记录文件 那么,使用xuggle xu

在过去的两周里,我尝试了从一个网络摄像头到另一个文件的录制,但我一直无法在我的Raspberry Pi model B+上使用网络摄像头捕获API

应用程序启动,但在最后冻结,没有任何控制台错误

它从网络摄像头录制,但最后会冻结,并保留100%的CPU使用率,直到使用ctrl+c终止

Xuggle Xuggler似乎工作正常,但甚至可以只使用Xuggle Xuggler录制视频吗

我已经找到了Xuggle Xuggler的演示,但没有一个是来自网络摄像头的记录文件


那么,使用xuggle xuggler和java库录制视频是可能的,还是只是再次浪费时间?

看起来这不仅仅是浪费时间

下面的源代码将仅使用Xuggle Xuggler和Java库将视频捕获到文件中。源代码在仅使用分辨率为320x240或更高时可以工作,这是因为xuggle xugglers

我仍然在等待更好更快的解决方案,等待我的原始问题被接受为答案

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());
    }
}
package网络摄像头;
导入com.xuggle.mediatool.IMediaWriter;
导入com.xuggle.mediatool.ToolFactory;
导入com.xuggle.xuggler.ICodec;
导入com.xuggle.xuggler.IContainer;
导入com.xuggle.xuggler.IContainerFormat;
导入com.xuggle.xuggler.IError;
导入com.xuggle.xuggler.IMetaData;
导入com.xuggle.xuggler.IPacket;
导入com.xuggle.xuggler.IPixelFormat;
导入com.xuggle.xuggler.IStream;
导入com.xuggle.xuggler.IStreamCoder;
导入com.xuggle.xuggler.IVideoPicture;
导入com.xuggle.xuggler.IVideoResampler;
导入com.xuggle.xuggler.Utils;
导入com.xuggle.xuggler.video.ConverterFactory;
导入com.xuggle.xuggler.video.IConverter;
导入java.awt.image.buffereImage;
导入java.io.File;
公共类Uusi{
@抑制警告(“弃用”)
公共静态void main(字符串[]args)抛出可丢弃的{
File File=新文件(“output.h264”);
IMediaWriter=ToolFactory.makeWriter(file.getName());
writer.addVideoStream(0,0,ICodec.ID.CODEC_ID_h264320240);
String driverName=“vfwcap”;
字符串deviceName=“0”;
//让我们确保我们可以真正转换视频像素格式。
如果(!IVideoResampler.isSupported(IVideoResampler.Feature.Feature\u colorspace转换)){
抛出新的RuntimeException(“您必须安装Xuggler的GPL版本(支持IVideResampler),此演示才能正常工作”);
}
//创建一个Xuggler容器对象
IContainer容器=IContainer.make();
//告诉Xugler有关设备格式的信息
IContainerFormat=IContainerFormat.make();
if(format.setInputFormat(driverName)<0){
抛出新的IllegalArgumentException(“无法打开网络摄像头设备:“+driverName”);
}
//与大多数文件不同,设备需要按顺序设置参数
//为了让Xugler知道如何配置它们,对于网络摄像头,这些
//参数有意义
IMetaData params=IMetaData.make();
参数设置值(“帧率”,“30/1”);
参数设置值(“视频大小”,“320x240”);
//打开容器
int retval=container.open(deviceName、IContainer.Type.READ、format、,
false、true、params、null);
如果(返回值<0){
//这个小技巧将不友好的整数返回值转换为
//一个稍微友好一点的对象,用于获取人类可读的错误名称
IError error=IError.make(retval);
抛出新的IllegalArgumentException(“无法打开文件:+deviceName+”,错误:+Error.getDescription());
}
//查询要打开的调用找到了多少流
int numStreams=container.getNumStreams();
//并遍历这些流以找到第一个视频流
int videoStreamId=-1;
IStreamCoder videoCoder=null;
for(int i=0;i=0&&i<100){
/*
*现在我们有了一个数据包,让我们看看它是否属于我们的视频流
*/
if(packet.getStreamIndex()==videoStreamId){
/*
*我们分配一个n