【问题标题】:How to save video into a file using OpenCV and Java?如何使用 OpenCV 和 Java 将视频保存到文件中?
【发布时间】:2021-11-14 22:53:07
【问题描述】:

使用 OpenCV 和 Java,我可以使用 Java JFrame 应用程序实时流式传输来自摄像头的视频,这意味着访问摄像头并从摄像头捕获视频就像 好吧。

我想将视频保存到文件中,下面是我的代码:

import ...;

public final class Main {
   
    VideoCapture videoCapture;
    Size size;
    Mat matrix;
    VideoWriter videoWriter;

    public Main() throws SocketException, UnknownHostException, IOException {
        System.load( "C:\\opencv\\build\\java\\x64\\" + Core.NATIVE_LIBRARY_NAME + ".dll");
        System.load( "C:\\opencv\\build\\bin\\opencv_videoio_ffmpeg453_64.dll");

        videoCapture = new VideoCapture(CAMERA_ID, CV_CAP_DSHOW);

        if (videoCapture.isOpened()) {
            Mat m = new Mat();
            videoCapture.read(m);

            int fourcc = VideoWriter.fourcc('H','2','6','4');
            // int fourcc = VideoWriter.fourcc('x','2','6','4'); // Have tried, did not work.
            // int fource = (int) videoCapture.get(Videoio.CAP_PROP_FOURCC); // Have tried, did not work.
            // int fourcc = VideoWriter.fourcc('m','j','p','g'); // Have tried, did not work.
            // int fourcc = VideoWriter.fourcc('D', 'I', 'V', 'X'); // Have tried, did not work.

            double fps = videoCapture.get(Videoio.CAP_PROP_FPS);
            Size s =  new Size((int) videoCapture.get(Videoio.CAP_PROP_FRAME_WIDTH), (int) videoCapture.get(Videoio.CAP_PROP_FRAME_HEIGHT));
             videoWriter = new VideoWriter("C:\\Users\\oconnor\\Documents\\bbbbbbbbbbbbb_1000.h264", fourcc, fps, s, true);
            // Have tried, did not work
            // videoWriter = new VideoWriter("C:\\Users\\oconnor\\Documents\\bbbbbbbbbbbbb_1000.avi", fourcc, fps, s, true);
            // videoWriter = new VideoWriter("C:\\Users\\oconnor\\Documents\\bbbbbbbbbbbbb_1000.Mjpeg", fourcc, fps, s, true);
            // videoWriter = new VideoWriter("C:\\Users\\oconnor\\Documents\\bbbbbbbbbbbbb_1000.mjpeg", fourcc, fps, s, true);

            while (videoCapture.read(m)) {
                 videoWriter.write(m);
                 
                 // Have tried, did not work.
                 // int i = 0;
                 // Mat clonedMatrix = m.clone();
                 // Imgproc.putText(clonedMatrix, ("frame" + i), new Point(100,100), 1, 2, new Scalar(200,0,0), 3);
                 // videoWriter.write(clonedMatrix);
                 // i++;
            }
        }

        videoCapture.release();
        videoWriter.release();
    }
}

当我运行上述代码时,完全没有错误,并且文件bbbbbbbbbbbbb_1000.h264也已创建,但VLC Media Player和Windows Media Player无法播放视频。

我使用的是 Windows 10。以下是 OpenCV 4.5.3 构建信息。我没有自己从源代码构建库。

Video I/O:
DC1394:                      NO
FFMPEG:                      YES (prebuilt binaries)
  avcodec:                   YES (58.134.100)
  avformat:                  YES (58.76.100)
  avutil:                    YES (56.70.100)
  swscale:                   YES (5.9.100)
  avresample:                YES (4.0.0)
GStreamer:                   NO
DirectShow:                  YES
Media Foundation:            YES
  DXVA:                      NO

如何使用 OpenCV 和 Java 将视频保存到文件中。它可以在Mjpeg 或h264 或其他任何位置,只要我可以播放文件即可。

【问题讨论】:

  • 报告cv::getBuildInformation()的输出。 AVI 中的 MJPEG 始终有效,因为它内置于 OpenCV 中。任何其他格式都需要后端,这意味着第三方库。 OpenCV 通常(但不总是!)使用 ffmpeg 构建。
  • OpenCV 构建信息添加在上面的问题中。我可以在我的 Widows 10 上运行 ffmpeg -f dshow -i video="HP HD Camera" -f mpegts -flush_packets 0 udp://ipaddress:port?query_string 来测试通过 UDP 进行的实时流式传输,并且它可以工作。我需要什么才能将视频保存到 h264 文件中?

标签: java opencv video h.264 mjpeg


【解决方案1】:

根据getBuildInformation(),您的 OpenCV 是使用 FFMPEG 构建的,这很好。

问题在于您尝试使用的文件扩展名。

文件扩展名.h264 并不代表实际的容器格式。 .h264 是对 naked H.264 流的扩展,该流位于没有适当容器结构的文件中。

您需要为您的文件提供扩展名 .mp4 或其他一些合适的容器格式。 MKV 将是合适的。 MPEG 传输流 (.ts) 也适用。

此外,H264 可能不是有效的“fourcc”。 avc1 是一个有效的四cc。

OpenCV 内置支持 AVI 容器 (.avi) 和 MJPEG 视频编解码器 (MJPG)。这将永远有效。如果 OpenCV 是使用 ffmpeg 构建的,或者它可以使用操作系统的媒体 API,则可能会提供更多容器和编解码器。

这里有一些python,但是API用法是一样的:

import numpy as np
import cv2 as cv

# fourcc = cv.VideoWriter.fourcc(*"H264")# might not be supported
fourcc = cv.VideoWriter.fourcc(*"avc1") # that's the proper fourcc by standard
# calling with (*"avc1") is equivalent to calling with ('a', 'v', 'c', '1')

(width, height) = (640, 360)
vid = cv.VideoWriter("foo.mp4", fourcc=fourcc, fps=16, frameSize=(width, height), isColor=True)

assert vid.isOpened()

frame = np.zeros((height, width, 3), np.uint8)
for k in range(256):
    frame[:,:] = (0, k, 255) # BGR order
    vid.write(frame)

vid.release() # finalize the file (write headers and whatnot)

此视频将为 256 帧、16 fps、16 秒,并从红色渐变为黄色。

它也将是 MP4 和 H.264。

【讨论】:

  • 我可以用('a', 'v', 'c', '1')fourcc 将视频保存到.ts 文件中,但不能保存在.mp4 文件中。如何验证视频是否为 H264 格式?
  • 在命令行上使用 ffprobe。对于 Windows,有“mediainfo”,通常带有各种流行的编解码器包(k-lite,...)
  • 我对您的答案投了赞成票,因为它包含将视频保存在 H264 中的解决方案。但它是在 Python 中,而不是在 Java 中。
【解决方案2】:

刚刚开始创建 AVI 文件。要创建 AVI 文件,fourcc 必须如下。

int fourcc = VideoWriter.fourcc('M','J','P','G');

文件名必须以.avi 作为扩展名。

在某些操作系统中,videoCapture.get(Videoio.CAP_PROP_FPS) 可能会返回 0.0。如果videoCapture.get(Videoio.CAP_PROP_FPS) 返回0.0,则设置默认的每秒帧数。我已将其设置为25;

感谢@Chistoph Rackwitz 和他在 Python 中的回答,为了将视频保存在 H264 中,fourcc 可以如下:

int fourcc = VideoWriter.fourcc('a', 'v', 'c', '1');

文件扩展名可以是.ts。

【讨论】:

    猜你喜欢
    • 2012-11-21
    • 2011-03-24
    • 2021-08-16
    • 2020-09-10
    • 2016-11-18
    • 1970-01-01
    • 2016-05-06
    • 2020-04-01
    • 1970-01-01
    相关资源
    最近更新 更多