首先个人感觉JAVACV这个库不好用,内部API基本上没有注释
FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(rtspUrl);
log.info("创建grabber成功");
grabber.setOption("rtsp_transport", "tcp");
grabber.setFrameRate(frameRate);
//设置获取的视频宽度
grabber.setImageWidth(frameWidth);
//设置获取的视频高度
grabber.setImageHeight(frameHeight);
//设置视频bit率
grabber.setVideoBitrate(2000000);
FFmpegLogCallback.set();
grabber.start();
log.info("grabber.start");
Java2DFrameConverter java2DFrameConverter = new Java2DFrameConverter();
while (true){
Frame frame = grabber.grabImage();
if (null == frame) {
continue;
}
BufferedImage bufferedImage = java2DFrameConverter.getBufferedImage(frame);
byte[] bytes = imageToBytes(bufferedImage, "jpg");
byte2image(bytes);
// 抓取延时2s
Thread.sleep(2000);
}
/**
* byte数组到图片
*
* @param data
*/
int num = 0;
public void byte2image(byte[] data) {
if (data.length < 3) {
return;
}
try (FileImageOutputStream imageOutput = new FileImageOutputStream(new File("D:\\excel\\" + num + ".png"))) {
num++;
imageOutput.write(data, 0, data.length);
log.info("图片保存成功" + num);
} catch (Exception ex) {
ex.printStackTrace();
}
}
使用FFmpegFrameGrabber.grabImage()进行抓帧的时候,如果设置Thread.sleep(2000),保存在D盘的图片并不是搁2s一张,是连续的帧,且抓取一段时间会出现Error: [h264 @ 00000181aa66e6c0] error while decoding MB 91 47, bytestream -5 错误
这边为了解决这个问题,代码改为下面的(因为本身要求只是个小demo,可能只是演示使用一次)
FFmpegFrameGrabber.tryLoad();
grabber = FFmpegFrameGrabber.createDefault(rtspUrl);
log.info("创建grabber成功");
grabber.setOption("rtsp_transport", "tcp");
// grabber.setFrameRate(frameRate);
// //设置获取的视频宽度
// grabber.setImageWidth(frameWidth);
// //设置获取的视频高度
// grabber.setImageHeight(frameHeight);
// //设置视频bit率
// grabber.setVideoBitrate(200000);
// grabber.setMaxDelay(2);
FFmpegLogCallback.set();
//不进行grabber.start()
//grabber.start();
log.info("grabber.start");
singleThreadExecutor.execute(() -> {
while (true) {
try {
Long end = System.currentTimeMillis();
//为了抓取最新的,每次进行grabber.start()
grabber.start();
log.info("grabber.start====>" + (System.currentTimeMillis()-end));
frame = grabber.grabImage();
log.info("grabber.grabImage====>" + (System.currentTimeMillis()-end));
if (frame != null) {
bufferedImage = java2DFrameConverter.getBufferedImage(frame);
if (bufferedImage != null) {
byteImage = PictureUtils.imageToBytes(bufferedImage, "jpg");
this.byte2image(byteImage);
}
}
log.info("数据转换====>" + (System.currentTimeMillis()-end));
//抓取完成,进行grabber.stop()
grabber.stop();
Long data = System.currentTimeMillis();
log.info("grabber.stop====>" + (data-end));
Thread.sleep(1000);
通过每次抓取去grabber.start() 和grabber.stop()去解决这个问题