Java截取视频首帧并旋转正向
package test; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TreeSet; import javax.imageio.ImageIO; import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Java2DFrameConverter; public class VideoTest { public static String image_type="jpg"; public static String file_type="mp4"; public static void main(String[] args) { String videofile="C:/xmqtest/test视频.mp4";//或网络视频地址 String framefileDir="C:/xmqtest/"; String targetFilePath=fetchFrame(videofile,framefileDir); } /** * 获取指定视频的帧并保存为图片至指定目录 * @param videofile 源视频文件路径 * @param framefile 截取帧的图片存放路径 * @throws Exception */ public static String fetchFrame(String videofile, String framefileDir){ try{ int startIndex=videofile.lastIndexOf('/'); String fileName; if(startIndex==-1){ fileName=videofile.substring(videofile.lastIndexOf('\\')+1, videofile.lastIndexOf('.')); }else{ fileName=videofile.substring(startIndex+1, videofile.lastIndexOf('.')+1); } String targetFileName=framefileDir+fileName+image_type; File targetFile=createFile(targetFileName); FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile); ff.start(); String rotate_old=ff.getVideoMetadata("rotate");//视频旋转角度,可能是null int length = ff.getLengthInFrames(); int i = 0; Frame f = null; while (i < length) { // 过滤前5帧,避免出现全黑的图片,依自己情况而定 f = ff.grabFrame(); if ((i > 5) && (f.image != null)) { break; } i++; } // IplImage img = f.image; int owidth = f.imageWidth; int oheight = f.imageHeight; // 对截取的帧进行等比例缩放 int width = 300;//生成图片宽度为300px int height = (int) (((double) width / owidth) * oheight); Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage fecthedImage = converter.getBufferedImage(f); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); bi.getGraphics().drawImage(fecthedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); ImageIO.write(bi, image_type, targetFile); ff.stop(); //有需要旋转 if(rotate_old!=null && !rotate_old.isEmpty()){ int rotate=Integer.parseInt(rotate_old); rotatePhonePhoto(targetFileName,rotate); } return targetFileName; }catch(Exception e){ e.printStackTrace(); } return null; }/*** * 创建文件,目录不存在则先创建目录在创建文件 * @param destFileName * @return */ public static File createFile(String destFileName) { try { File file = new File(destFileName); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } file.createNewFile(); return file; } catch (IOException e) { e.printStackTrace(); return null; } } /** * 删除单个文件 */ public static void deleteFile(String sPath) { File file = new File(sPath); if (file.isFile() && file.exists()) { file.delete(); } } /** * 旋转照片 * * @return */ public static String rotatePhonePhoto(String fullPath, int angel) { BufferedImage src; try { src = ImageIO.read(new File(fullPath)); int src_width = src.getWidth(null); int src_height = src.getHeight(null); int swidth = src_width; int sheight = src_height; if (angel == 90 || angel == 270) { swidth = src_height; sheight = src_width; } Rectangle rect_des = new Rectangle(new Dimension(swidth, sheight)); BufferedImage res = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = res.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, null, null); ImageIO.write(res,image_type, new File(fullPath)); } catch (Exception e) { e.printStackTrace(); } return fullPath; } }
说明点:
1、加入依赖,经测试两个依赖在windows环境,linux环境下正常使用。如果本地windows环境正常但是在linux下失败,请使用以下依赖。
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.0.2-1.4.3</version>
</dependency>
2、针对iphone手机视频等需要进行首帧图片旋转,否则出现首帧图片横着的情况。如代码部分:
String rotate_old=ff.getVideoMetadata("rotate");//视频旋转角度,可能是null
3、后续发现视频只有1秒截取不到首帧。
4、创建的图片,在linux机器上可能会403错误,打开bin/catalina.sh文件,将0027改改为UMASK="0022",重启tomcat,上传访问的问题解决。