You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用OpenCV和Java将摄像头采集的视频保存为可正常播放的文件

解决方案

核心问题原因

你生成的视频无法播放是由以下几个常见错误共同导致的:

  • 未校验VideoWriter是否成功初始化,编码器和文件后缀不匹配时仍然写入内容会生成损坏文件
  • 直接读取摄像头的CAP_PROP_FPS参数,大部分USB摄像头该参数返回值为0或者无效值,错误的帧率会导致编码器输出异常
  • 未设置正常的录制停止逻辑,强制终止程序会导致VideoWriter没有写入视频文件的尾部索引,最终生成的文件无法被播放器识别
  • 编码器和文件后缀不匹配,比如直接写裸H264流没有封装,大部分普通播放器无法直接解析裸流文件

可直接运行的修复代码

优先使用MJPEG编码+AVI封装的组合,这个是Windows下预编译OpenCV默认支持最好的方案,不需要额外安装任何编码器:

import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.VideoWriter;
import org.opencv.videoio.Videoio;

public final class Main {
    // 摄像头ID,默认0是第一个摄像头
    private static final int CAMERA_ID = 0;
    // 录制时长,单位毫秒,这里设10秒自动停止,你可以自行修改为按键触发停止
    private static final int RECORD_DURATION = 10000;

    public static void main(String[] args) {
        // 加载OpenCV本地库
        System.load( "C:\\opencv\\build\\java\\x64\\" + Core.NATIVE_LIBRARY_NAME + ".dll");
        System.load( "C:\\opencv\\build\\bin\\opencv_videoio_ffmpeg453_64.dll");

        VideoCapture videoCapture = new VideoCapture(CAMERA_ID, Videoio.CV_CAP_DSHOW);
        VideoWriter videoWriter = null;

        if (!videoCapture.isOpened()) {
            System.out.println("摄像头打开失败");
            return;
        }

        try {
            // 获取帧尺寸
            int frameWidth = (int) videoCapture.get(Videoio.CAP_PROP_FRAME_WIDTH);
            int frameHeight = (int) videoCapture.get(Videoio.CAP_PROP_FRAME_HEIGHT);
            Size frameSize = new Size(frameWidth, frameHeight);

            // 修复帧率:如果读取到的帧率无效,默认用25帧
            double fps = videoCapture.get(Videoio.CAP_PROP_FPS);
            if (fps <= 0 || fps > 60) {
                fps = 25;
            }

            // MJPEG编码 + AVI封装,兼容性最好
            int fourcc = VideoWriter.fourcc('M','J','P','G');
            String outputPath = "C:\\Users\\oconnor\\Documents\\test_output.avi";
            videoWriter = new VideoWriter(outputPath, fourcc, fps, frameSize, true);

            // 必须校验VideoWriter是否打开成功
            if (!videoWriter.isOpened()) {
                System.out.println("视频写入器初始化失败,请检查参数和路径权限");
                return;
            }

            Mat frame = new Mat();
            long startTime = System.currentTimeMillis();

            // 录制逻辑,到时间自动停止,按Q键可提前停止
            while (System.currentTimeMillis() - startTime < RECORD_DURATION) {
                if (videoCapture.read(frame)) {
                    videoWriter.write(frame);
                    // 可选:显示实时画面
                    HighGui.imshow("录制中", frame);
                    // 必须加waitKey,否则画面不会刷新,按键监听也不生效
                    int key = HighGui.waitKey(1);
                    if (key == 'q' || key == 'Q') {
                        break;
                    }
                } else {
                    break;
                }
            }
            System.out.println("录制完成,文件保存至:" + outputPath);
        } finally {
            // 释放资源,一定要执行,否则视频文件会损坏
            if (videoWriter != null) {
                videoWriter.release();
            }
            videoCapture.release();
            HighGui.destroyAllWindows();
        }
    }
}

其他格式可选方案

如果需要H264编码的MP4文件,只需要修改编码器和输出文件后缀即可:

// H264编码 + MP4封装
int fourcc = VideoWriter.fourcc('a','v','c','1');
String outputPath = "C:\\Users\\oconnor\\Documents\\test_output.mp4";

注意事项

  • 输出路径要确保有写入权限,不要使用中文或者特殊字符
  • 不要直接强制结束程序,必须通过正常停止逻辑走到release方法,否则视频文件会缺失尾部索引无法播放
  • 如果还是初始化失败,可以尝试去掉CV_CAP_DSHOW参数,使用默认的摄像头采集后端

内容的提问来源于stack exchange,提问作者O Connor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 10:27:04