[视频] 使用 JavaCV 来显示和保存来自摄像头的视频
JavaCV
javacv开发包是用于支持java多媒体开发的一套开发包,可以适用于本地多媒体(音视频)调用以及音视频,图片等文件后期操作(图片修改,音视频解码剪辑等等功能)。
https://github.com/bytedeco/javacv
本文默认音视频处理使用ffmpeg,图像处理使用opencv,摄像头抓取使用opencv
Maven依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.4</version>
</dependency>
上面的是全平台的,国内经常有下载不完整的问题,可以用下面这个
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.4</version>
</dependency>
Gradle依赖
dependencies {
implementation group: 'org.bytedeco', name: 'javacv-platform', version: '1.5.4'
}
从javacv0.8开始,已经不需要本地安装opencv,直接通过引用opencv对应的系统平台的引用包即可。
预览本机摄像头视频图像的简单实现
public static void main(String[] args) throws Exception {
SpringApplication.run(VideoApplication.class, args);
//新建opencv抓取器,一般的电脑和移动端设备中摄像头默认序号是0,不排除其他情况
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
grabber.start();//开始获取摄像头数据
//新建一个预览窗口
CanvasFrame canvas = new CanvasFrame("摄像头预览");
canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//窗口是否关闭
while(canvas.isDisplayable()){
/*获取摄像头图像并在窗口中显示,这里Frame frame=grabber.grab()得到是解码后的视频图像*/
canvas.showImage(grabber.grab());
}
grabber.close();//停止抓取
}
需要如图配置
预览的同时,保存为FLV文件
public static void main(String[] args) {
SpringApplication.run(VideoApplication.class, args);
recordCamera("C:\\FFOutput\\output.flv",25);
}
public static void recordCamera(String outputFile, double frameRate) {
FrameGrabber grabber = FrameGrabber.createDefault(0);//本机摄像头默认0
grabber.start();//开启抓取器
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();//转换器
// 抓取一帧视频并将其转换为图像,至于用这个图像用来做什么?加水印,人脸识别等等自行添加
IplImage grabbedImage = converter.convert(grabber.grab());
int width = grabbedImage.width();
int height = grabbedImage.height();
FrameRecorder recorder = FrameRecorder.createDefault(outputFile, width, height);
recorder.setVideoCodec(AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264,编码
recorder.setFormat("flv");//封装格式,如果是推送到rtmp就必须是flv封装格式
recorder.setFrameRate(frameRate);
recorder.start();//开启录制器
long startTime=0;
long videoTS=0;
CanvasFrame frame = new CanvasFrame("camera", CanvasFrame.getDefaultGamma() / grabber.getGamma());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
Frame rotatedFrame=converter.convert(grabbedImage);//不知道为什么这里不做转换就不能推到rtmp
while (frame.isVisible() && (grabbedImage = converter.convert(grabber.grab())) != null) {
rotatedFrame = converter.convert(grabbedImage);
frame.showImage(rotatedFrame);
if (startTime == 0) {
startTime = System.currentTimeMillis();
}
videoTS = 1000 * (System.currentTimeMillis() - startTime);
recorder.setTimestamp(videoTS);
recorder.record(rotatedFrame);
Thread.sleep(40);
}
frame.dispose();//关闭窗口
recorder.close();//关闭推流录制器,close包含release和stop操作
grabber.close();//关闭抓取器
}
附记:在茫茫的信息海洋中,遇到就是有缘,期待回复交流,为缘分留下痕迹……