javacv 提取视频封面

2020/02/24 15:54
阅读数 932

1引入maven依赖

网上大多引入的是

<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.5.2</version>
</dependency>  

此依赖会下载所有jar 包括了android,linux,macosx、windows等平台,大概有400多M,所以需要对依赖进行精简

<dependency>
		  <groupId>org.bytedeco</groupId>
		  <artifactId>javacv</artifactId>
		  <version>1.4.2</version>
		  <exclusions>
			  <exclusion>
				  <groupId>org.bytedeco.javacpp-presets</groupId>
				  <artifactId>*</artifactId>
			  </exclusion>
		  </exclusions>
	  </dependency>
	  <dependency>
		  <groupId>org.bytedeco.javacpp-presets</groupId>
		  <artifactId>opencv</artifactId>
		  <version>3.4.2-1.4.2</version>
	  </dependency>
	  <dependency>
		  <groupId>org.bytedeco.javacpp-presets</groupId>
		  <artifactId>opencv</artifactId>
		  <version>3.4.2-1.4.2</version>
		<!--  <classifier>windows-x86_64</classifier>-->
		  <classifier>linux-x86_64</classifier>
	  </dependency>
	  <!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/ffmpeg -->
	  <dependency>
		  <groupId>org.bytedeco.javacpp-presets</groupId>
		  <artifactId>ffmpeg</artifactId>
		  <version>4.0.1-1.4.2</version>
	  </dependency>
	  <dependency>
		  <groupId>org.bytedeco.javacpp-presets</groupId>
		  <artifactId>ffmpeg</artifactId>
		  <version>4.0.1-1.4.2</version>
		  <!--<classifier>windows-x86_64</classifier>-->
		  <classifier>linux-x86_64</classifier>
	  </dependency>

 classifier 根据当前系统进行配置,windows 可使用 windows-x86_64。linux可根据实际情况选择

其他平台需要用可以在classifier里面修改成对应的

<javacpp.platform.android-arm>android-arm</javacpp.platform.android-arm>
    <javacpp.platform.android-arm64>android-arm64</javacpp.platform.android-arm64>
    <javacpp.platform.android-x86>android-x86</javacpp.platform.android-x86>
    <javacpp.platform.android-x86_64>android-x86_64</javacpp.platform.android-x86_64>
    <javacpp.platform.ios-arm>ios-arm</javacpp.platform.ios-arm>
    <javacpp.platform.ios-arm64>ios-arm64</javacpp.platform.ios-arm64>
    <javacpp.platform.ios-x86>ios-x86</javacpp.platform.ios-x86>
    <javacpp.platform.ios-x86_64>ios-x86_64</javacpp.platform.ios-x86_64>
    <javacpp.platform.linux-armhf>linux-armhf</javacpp.platform.linux-armhf>
    <javacpp.platform.linux-arm64>linux-arm64</javacpp.platform.linux-arm64>
    <javacpp.platform.linux-ppc64le>linux-ppc64le</javacpp.platform.linux-ppc64le>
    <javacpp.platform.linux-x86>linux-x86</javacpp.platform.linux-x86>
    <javacpp.platform.linux-x86_64>linux-x86_64</javacpp.platform.linux-x86_64>
    <javacpp.platform.macosx-x86_64>macosx-x86_64</javacpp.platform.macosx-x86_64>
    <javacpp.platform.windows-x86>windows-x86</javacpp.platform.windows-x86>
    <javacpp.platform.windows-x86_64>windows-x86_64</javacpp.platform.windows-x86_64>

Linux查看内核判断命令  : arch

 

 

 2、java 实现代码

package com.util;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * 视频处理工具类
 * @author admin
 */
public class VideoUtil {


    /**
     * 获取视频封面图
     * @param filePath 视频地址
     * @param mod 开始帧数
     * @return map
     * @throws Exception
     */
    public static Map<String, Object> getScreenshot(String filePath,int mod) throws Exception{
        filePath = filePath.replaceAll("\\\\","/");
        System.out.println("截取视频截图开始:"+ System.currentTimeMillis());
        Map<String, Object> result = new HashMap<>();
        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("."));


        grabber.start();
        //设置视频截取帧(建议从5帧开始,防止全是黑屏)
        Frame frame = null;
        for (int j = 0; j < mod; j++) {
            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", StringUtil.isEmpty(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));
    }

}

3、测试

public static void main(String[] args) throws IOException {
        String clientTime ="2020-02-20",startTime="2020-04-03 00:00:00";
        System.out.println(clientTime.length());
        System.out.println(startTime.length());
       /*int s1= DateUtil.compareTo(clientTime,startTime,DateUtil.NORM_DATETIME_PATTERN);
        System.out.println(s1);*/

        String filePath="D:/home/ddc761004d.mp4";

       try {
           Map<String, Object> map = VideoUtil.getScreenshot(filePath,25);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

  参考地址:

https://blog.csdn.net/lianzhang861/article/details/82014460

https://blog.csdn.net/huangwen123456/article/details/82492375

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部