【Java Web开发学习】使用Javacv截取视频图片
转载:https://www.cnblogs.com/yangchongxing/p/9482935.html
github地址:https://github.com/bytedeco/javacv
Java不擅长处理视频和图片。使用场景是上传上来的视屏需要一个封面,所以就用java实现了。
javacv文档很少,参考网上的代码稍作修改而成,仅供参考,有好的方式欢迎留言。
网上有好多没有解决截屏图片被旋转过的问题,使用String rotate = grabber.getVideoMetadata("rotate");获取视频有没有旋转,没有返回null,有返回度数,90,180,270等。把图片做对象旋转,图片就正了。
示例代码:select截取第20帧的图片
public static void main(String[] args) throws IOException { // 截第20帧 int select = 20; FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("E:/wx/下.mp4"); grabber.start(); int length = grabber.getLengthInFrames(); int index = 1; Frame frame = null; while (index <= length) { frame = grabber.grab(); if (index >= select) { break; } index++; } String rotate = grabber.getVideoMetadata("rotate"); Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage bi = converter.getBufferedImage(frame); if (rotate != null) { //旋转图片 bi = rotate(bi, Integer.parseInt(rotate)); } ImageIO.write(bi, "jpg", new File("E:/wx/" + System.currentTimeMillis() + ".jpg")); grabber.stop(); } 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; } 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)); }
下面是一个上传截取第一帧做图片
import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Java2DFrameConverter; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.commons.CommonsMultipartFile; import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest; @RequestMapping("/upload") @Controller public class UploadController extends BaseController { // 图片上传 @RequestMapping(value="/image", method=RequestMethod.POST, produces="application/json;charset=UTF-8") @ResponseBody public String uploadImage(@RequestParam(value = "imageFile", required = false) CommonsMultipartFile imageFile, HttpServletRequest request) throws IOException { if (imageFile == null || imageFile.getSize() == 0) { DefaultMultipartHttpServletRequest multipartRequest = (DefaultMultipartHttpServletRequest)request; imageFile = (CommonsMultipartFile) multipartRequest.getFile("Filedata"); if (imageFile == null || imageFile.getSize() == 0) { Result result = new Result(); result.setStatus(Result.STATUS_FAILURE); result.setMessage(Result.STATUS_FAILURE); return result.toJson(); } } //文件名 String fileName = Utils.fileName() + Utils.suffix(imageFile.getOriginalFilename()); //日期目录 String path = "/uploads/images" + new SimpleDateFormat("/yyyy/MM/dd/").format(new Date()); //服务器图片文件存放目录 String serverPath = request.getServletContext().getRealPath(path); File serverPathFile = new File(serverPath); //目录不存在则创建 if (!serverPathFile.exists()) { serverPathFile.mkdirs(); } String imageUrl = path + fileName; String serverFilePath = serverPath + fileName; //移动文件 imageFile.transferTo(new File(serverFilePath));return imageUrl; } // 视频上传 @SuppressWarnings("resource") @RequestMapping(value="/video", method=RequestMethod.POST, produces="application/json;charset=UTF-8") @ResponseBody public String uploadVideo(@RequestParam(value = "videoFile", required = false) CommonsMultipartFile imageFile, HttpServletRequest request) throws IOException { if (imageFile == null || imageFile.getSize() == 0) { Result result = new Result(); result.setStatus(Result.STATUS_FAILURE); result.setMessage("文件不存在"); return result.toJson(); } //文件名 String fileName = Utils.fileName() + Utils.suffix(imageFile.getOriginalFilename()); //日期目录 String path = "/uploads/videos" + new SimpleDateFormat("/yyyy/MM/dd/").format(new Date()); //服务器图片文件存放目录 String serverPath = request.getServletContext().getRealPath(path); File serverPathFile = new File(serverPath); //目录不存在则创建 if (!serverPathFile.exists()) { serverPathFile.mkdirs(); } String serverFilePath = serverPath + fileName; //移动文件 imageFile.transferTo(new File(serverFilePath)); //视频截屏 FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(serverFilePath); grabber.start(); Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage bi = converter.convert(grabber.grab()); String rotate = grabber.getVideoMetadata("rotate"); if (rotate != null) { bi = rotate(bi, Integer.parseInt(rotate)); } fileName += ".v.jpg"; serverFilePath = serverPath + fileName; String imageUrl = path + fileName; ImageIO.write(bi, "jpg", new File(serverFilePath)); grabber.stop(); // 返回截取封面
return imageUrl; } 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; } 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)); } }