Java获取视频信息以及截取封面(通过Javacv的方式)

本文介绍了一种改进的Java视频处理方法,通过引入javacv-platform库,解决了FFmpeg在处理手机拍摄视频时的问题,如宽高识别错误和前置摄像头镜面效果。文章详细描述了如何使用该库获取视频信息、截图并调整图片旋转角度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于上一篇文章使用 FFmpeg  的方式获取视频信息以及截取封面遇到多数问题。

例如:手机拍摄视频宽高获取错误(因为手机拍摄的视频中存在 rotate(即旋转度的原因),导致FFmpeg识别错误),使用前置摄像头拍照后使截取出来的图片出现镜面/颠倒效果。

为此特地寻找到一种与之类似的方法进行解决:

  1. 该方式相对于 FFmpeg 方式,更加的方便,只需要导入依赖包即可获取到视频信息以及截图。
  2. 对不同环境/系统更具有兼容性。

首先导入Maven依赖包:(导入时注意导入的版本)

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.3.1</version>
</dependency>

Java方法

/**
* @Description: 获取视频截图
* @throws IOException  void
*/
public static Map<String, Object> getScreenshot(String filePath) throws Exception{
	
	System.out.println("截取视频截图开始:"+ System.currentTimeMillis());
	Map<String, Object> result = new HashMap<String, Object>();
	FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(filePath);
	
	// 第一帧图片存储位置
	String targerFilePath = filePath.substring(0, filePath.lastIndexOf("\\"));
	// 视频文件名
	String fileName = filePath.substring(filePath.lastIndexOf("\\") + 1);
	// 图片名称
	String targetFileName = fileName.substring(0, fileName.lastIndexOf("."));
	System.out.println("视频路径是:" + targerFilePath);
	System.out.println("视频文件名:" + fileName);
	System.out.println("图片名称是:" + targetFileName);
	
	grabber.start();
	//设置视频截取帧(默认取第一帧)
	Frame frame = grabber.grabImage();
	//视频旋转度
	String rotate = grabber.getVideoMetadata("rotate");
	Java2DFrameConverter converter = new Java2DFrameConverter();
	//绘制图片
	BufferedImage bi = converter.getBufferedImage(frame);
	if (rotate != null) {
		// 旋转图片
		bi = rotate(bi, Integer.parseInt(rotate));
	}
	//图片的类型
	String imageMat = "jpg";
	//图片的完整路径
	String imagePath = targerFilePath + File.separator + targetFileName + "." + imageMat;
	//创建文件
	File output = new File(imagePath);
	ImageIO.write(bi, imageMat, output);
	
	//拼接Map信息
	result.put("videoWide", bi.getWidth());
	result.put("videoHigh", bi.getHeight());
	long duration = grabber.getLengthInTime() / (1000 * 1000);
	result.put("rotate", StringUtils.isBlank(rotate)? "0" : rotate);
	result.put("format", grabber.getFormat());
	result.put("imgPath", output.getPath());
	System.out.println("视频的宽:" + bi.getWidth());
	System.out.println("视频的高:" + bi.getHeight());
	System.out.println("视频的旋转度:" + rotate);
	System.out.println("视频的格式:" + grabber.getFormat());
	System.out.println("此视频时长(s/秒):" + duration);
	grabber.stop();
	System.out.println("截取视频截图结束:"+ System.currentTimeMillis());
	return result;
}

/**
* @Description: 根据视频旋转度来调整图片
* @param src	
* @param angel	视频旋转度
* @return  BufferedImage
*/
public static BufferedImage rotate(BufferedImage src, int angel) {
	int src_width = src.getWidth(null);
	int src_height = src.getHeight(null);
	int type = src.getColorModel().getTransparency();
	Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
	BufferedImage bi = new BufferedImage(rect_des.width, rect_des.height, type);
	Graphics2D g2 = bi.createGraphics();
	g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
	g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
	g2.drawImage(src, 0, 0, null);
	g2.dispose();
	return bi;
}


/**
* @Description: 计算图片旋转大小
* @param src
* @param angel
* @return  Rectangle
*/
public static Rectangle calcRotatedSize(Rectangle src, int angel) {
	if (angel >= 90) {
		if (angel / 90 % 2 == 1) {
			int temp = src.height;
			src.height = src.width;
			src.width = temp;
		}
		angel = angel % 90;
	}
	double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
	double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
	double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
	double angel_dalta_width = Math.atan((double) src.height / src.width);
	double angel_dalta_height = Math.atan((double) src.width / src.height);
	int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
	int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
	int des_width = src.width + len_dalta_width * 2;
	int des_height = src.height + len_dalta_height * 2;
	return new java.awt.Rectangle(new Dimension(des_width, des_height));
}

上一篇:Java获取视频信息以及截取封面(FFmpeg方式)

125分50秒---162.81M---LabView01---第10章数据的显示.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView01-第10章数据的显示.wmv 92分2秒---143.46M---LabView02---第11章文件的IO及保存.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView02-第11章文件的IO及保存.wmv 37分22秒---58.09M---LabView03---第12章LabVIEW的通信.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView03-第12章LabVIEW的通信.wmv 9分58秒---21.2M---LabView04---第13章LabVIEW与其它软件的连接.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView04-第13章LabVIEW与其它软件的连接.wmv 4分45秒---9.99M---LabView05---第14章LabVIEW中子VI的设置及调用.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView05-第14章LabVIEW中子VI的设置及调用.wmv 34分30秒---61.03M---LabView06---第15章其它高级技巧.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView06-第15章其它高级技巧.wmv 9分41秒---11.37M---LabView07---第2章第一个LabVIEW例子.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView07-第2章第一个LabVIEW例子.wmv 86分58秒---140.25M---LabView08---第3章基本元素.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView08-第3章基本元素.wmv 76分48秒---143.72M---LabView09---第4章程序结构.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView09-第4章程序结构.wmv 5分46秒---14.67M---LabView10---第5章数据采集.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView10-第5章数据采集.wmv 12分50秒---18.35M---LabView11---第6章数据传输及电脑接口.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView11-第6章数据传输及电脑接口.wmv 59分57秒---87.83M---LabView12---第7章数据的分析及处理.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView12-第7章数据的分析及处理.wmv 42分4秒---61.02M---LabView13---第8章LabVIEW的信号调理.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView13-第8章LabVIEW的信号调理.wmv 132分19秒---178.86M---LabView14---第9章分析处理中数学计算.wmv---F:/Resource/video/硬件/AltiumDesigner/LabView14-第9章分析处理中数学计算.wmv
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值