如何使用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
相关产品推荐
相关产品推荐

