【问题标题】:Capture video using webcam in Java在 Java 中使用网络摄像头捕获视频
【发布时间】:2016-07-05 12:05:27
【问题描述】:

我正在尝试从 Java 应用程序捕获视频屏幕截图。我已经下载了 sarxos/webcam-capture 库。我已将可执行 jar 添加到我的项目中。有点乱。我想从我创建的简单 javafx 界面捕获视频。问题是在安装了 lib 和 slf4 之后,还需要安装 xuggle。我在路径中添加了xuggle,我的代码如下:

File file = new File("output.ts");

IMediaWriter writer = ToolFactory.makeWriter(file.getName());
Dimension size = WebcamResolution.QVGA.getSize();

writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, size.width, size.height);

Webcam webcam = Webcam.getDefault();
webcam.setViewSize(size);
webcam.open(true);

long start = System.currentTimeMillis();

for (int i = 0; i < 50; i++) {

    System.out.println("Capture frame " + i);

    BufferedImage image = ConverterFactory.convertToType(webcam.getImage(), 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);

    // 10 FPS
    Thread.sleep(100);
}

writer.close();

System.out.println("Video recorded in file: " + file.getAbsolutePath());

但是我收到以下信息:

Caused by: java.lang.UnsatisfiedLinkError: no xuggle-ferry in java.library.path

EDIT2 我也尝试了 jxcapture 库。我在我的项目中添加了所有必要的库我运行以下代码:enter link description here,代码运行良好我设法存储视频,但最后我收到以下错误:

8614 [JNIWrapper.ShutdownHook] 错误 com.jniwrapper.NativeResourceCollector - com.jniwrapper.FunctionExecutionException:回调参数类型或其计数不正确 在 com.jniwrapper.Function.invokeVirtualFunc(Native Method)

知道这个错误是关于什么的吗?什么是 JNIWrapper.ShutdownHook?我在 3 台不同的机器上尝试了代码,这仅发生在其中一台机器上?我该如何处理这个异常?

EDIT3:我尝试了@whitesite 提案EDIT3。 gui 启动了,我有两个按钮启动和停止启动按钮打开相机,当我试图停止时,我收到以下信息:

java.lang.NullPointerException:参数 0 的指针地址为 NULL。 在 org.bytedeco.javacpp.opencv_videoio$VideoWriter.write(本机方法) 在 org.bytedeco.javacv.OpenCVFrameRecorder.record(OpenCVFrameRecorder.java:105) 在 Test1.lambda$0(Test1.java:52) 在 java.lang.Thread.run(Unknown Source)

【问题讨论】:

  • “我在路径中添加 xuggle”是什么意思?据我了解,它有自己的依赖项,需要一些预编译的二进制文件,如果你不使用 maven 或其他东西,你必须手动提供。
  • 我添加到我的 Eclipse 项目 webcam-capture 然后是 xuggle_3.4 然后是 slf4j 和 bridj-0.6.2。我不知道我还应该添加什么。
  • 基本上,UnsatisfiedLinkError 表示 xuggle 找不到所需的库。如果您阅读xuggle download instructions,您会发现您需要提供其所有依赖项和预编译的二进制文件。使用 maven 会容易得多。
  • 另一件事是我无法下载 xuggle 的更新版本。我在 5.2 或 5.4 中无处可去。
  • 似乎他们很久以前就停止支持它了。你想达到什么目的?如果您只需要快照,它看起来就像普通的 sarxos 网络摄像头一样能够做到这一点。如果您需要更高级的视频解码/流/压缩功能,则可能需要一些额外的工具,比如 ffmpeg。

标签: java javafx webcam video-capture


【解决方案1】:

您的类路径中缺少 slf4-api-ver.jar。但是,仅添加 api 是不够的,您还需要像 slf4j-simple-ver.jar 这样的提供程序。可用的最新版本是 1.7.21,可以从这里下载 http://www.slf4j.org/download.html

【讨论】:

【解决方案2】:

好的,这就是我使用 JavaCV library 及其示例得到的结果:

public class Test extends Application {

public void start(Stage primaryStage) throws Exception {

    OpenCVFrameGrabber capture = OpenCVFrameGrabber.createDefault(0);
    capture.start();

    OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
    Java2DFrameConverter javaConverter = new Java2DFrameConverter();

    VBox root = new VBox();
    Canvas canvas = new Canvas();
    canvas.setHeight(capture.getImageHeight());
    canvas.setWidth(capture.getImageWidth());
    root.getChildren().add(canvas);
    Scene scene = new Scene(root, capture.getImageWidth(), capture.getImageHeight());

    primaryStage.setTitle("Live video");
    primaryStage.setScene(scene);
    primaryStage.show();

    Thread videoProcessor = new Thread(() -> {
        File output = new File("C:/Work/test.avi");
        OpenCVFrameRecorder recorder = new OpenCVFrameRecorder(output, capture.getImageWidth(), capture.getImageHeight());
        try {
            recorder.setVideoCodec(opencv_videoio.CV_FOURCC((byte) 'M', (byte) 'J', (byte) 'P', (byte) 'G'));
            recorder.start();
            while (true) {
                if(Thread.currentThread().isInterrupted()){
                    break;
                }
                Frame frame = capture.grab();
                Platform.runLater(()->{
                    BufferedImage image = javaConverter.getBufferedImage(frame, 1.0, false, null);
                    canvas.getGraphicsContext2D().drawImage(SwingFXUtils.toFXImage(image, null),0,0);
                });
                recorder.record(frame);
            }
            recorder.stop();
            capture.release();
            recorder.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    });

    primaryStage.setOnCloseRequest(e->{
        videoProcessor.interrupt();
    });

    videoProcessor.start();

}

public static void main(String[] args) throws Exception {
    launch(args);
}

}

它从网络摄像头捕获视频并实时翻译,同时写入文件。您需要使用 maven 或手动安装将他们的库以及二进制 zip 存档中的所有 jar 包含在类路径中。也许你不需要所有这些,但我没有深入挖掘。
您可以使用设置并调查示例和来源。据我所知,它是一个非常强大的库。
编辑
只是视频处理部分:

Thread videoProcessor = new Thread(() -> {
        OpenCVFrameGrabber capture = null;
        FrameRecorder recorder = null;
        try {

            File output = new File("C:/Work/test2.avi");
            capture = OpenCVFrameGrabber.createDefault(0);
            capture.start();
            recorder = FrameRecorder.createDefault(output, capture.getImageWidth(), capture.getImageHeight());
            recorder.setFrameRate(8);
            recorder.setVideoCodec(opencv_videoio.CV_FOURCC((byte) 'M', (byte) 'J', (byte) 'P', (byte) 'G'));
            recorder.start();
            long l = System.currentTimeMillis();
            while (true) {
                if(Thread.currentThread().isInterrupted()){
                    break;
                }
                recorder.record(capture.grab());

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                recorder.stop();
                capture.release();
                recorder.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

您需要在某处启动进程videoProcessor.start(),然后中断它以停止录制videoProcessor.interrupt()。您可能还需要设置适当的录像机帧速率以将其调整为您的相机 fps。
编辑 2
输出可用设备的代码:

int n = org.bytedeco.javacpp.videoInputLib.videoInput.listDevices();
for (int i = 0; i < n; i++) {
    System.out.println(i + " = " + org.bytedeco.javacpp.videoInputLib.videoInput.getDeviceName(i));
}  

编辑 3
如果网络摄像头捕获有效,那么您可以使用它来捕获图像并使用 javaCV 将这些图像记录到视频文件中(非常像您问题中的示例,只是 javaCV 而不是 xuggler)。这是一个小型 javafx 应用程序,它有两个按钮:“开始”启动 videoProcessing 线程以捕获视频,“停止”中断该线程:

import com.github.sarxos.webcam.Webcam;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.bytedeco.javacpp.opencv_videoio;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameRecorder;


import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;

public class Test1 extends Application {

public void start(Stage primaryStage) throws Exception {

    final double FPS = 25;
    final int WIDTH = 640;
    final int HEIGHT = 480;
    Webcam webcam = Webcam.getDefault();
    webcam.setViewSize(new Dimension(WIDTH, HEIGHT));

    Java2DFrameConverter javaConverter = new Java2DFrameConverter();

    VBox root = new VBox();
    Button b1 = new Button("Start");
    Button b2 = new Button("Stop");

    root.getChildren().addAll(b1, b2);
    Scene scene = new Scene(root, 300,200);
    primaryStage.setTitle("Test");
    primaryStage.setScene(scene);

    Runnable r = () -> {
        File output = new File("C:/Work/test.avi");
        OpenCVFrameRecorder recorder = new OpenCVFrameRecorder(output, WIDTH, HEIGHT);
        recorder.setFrameRate(FPS);
        try {
            recorder.setVideoCodec(opencv_videoio.CV_FOURCC((byte) 'M', (byte) 'J', (byte) 'P', (byte) 'G'));
            recorder.start();
            webcam.open();
            while (true) {
                if(Thread.currentThread().isInterrupted()){
                    break;
                }
                BufferedImage image = webcam.getImage();
                recorder.record(javaConverter.getFrame(image));
                try {
                    Thread.sleep(1000 / (long)FPS);
                } catch (InterruptedException ie) {
                    break;
                }
            }
            recorder.stop();
            recorder.release();
            webcam.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    };

    b1.setOnAction(e->{
        Thread t = new Thread(r);
        t.start();
        b2.setOnAction(e2->t.interrupt());
    });

    primaryStage.show();
}

public static void main(String[] args) throws Exception {
    launch(args);
}

}

【讨论】:

  • 我怎样才能只捕获视频,我对所有这些代码有点困惑。我只想将视频存储到我的硬盘中。
  • @JoseRamon 仅使用视频处理部分。查看编辑。
  • 我试过代码。当我在线程中有代码时根本不起作用。如果我只使用没有线程的代码,我的相机只打开一帧,然后在没有存储视频的情况下关闭。
  • 过了一会儿我收到以下消息:org.bytedeco.javacv.FrameGrabber$Exception: read() 错误:无法读取 start() 中的帧。在 org.bytedeco.javacv.OpenCVFrameGrabber.start(OpenCVFrameGrabber.java:211)
  • 似乎 openCV 无法从您的网络摄像头读取帧 要么找不到设备,要么不受支持。尝试从第二次编辑运行它以查看可用设备的列表和数量。
猜你喜欢
  • 2017-04-27
  • 1970-01-01
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多