• 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
  • 相关阅读:
    项目管理之代码合并
    C#判断操作系统的位数
    年初离职潮的思考
    线上系统问题的紧急处理案例(一)
    [六、页面跳转]8通过PresentationMode实现导航的后退
    [六、页面跳转]12使用@ObervedObject监听实例对象二
    [六、页面跳转]13使用@StateObject实现简单的购物车功能
    [六、页面跳转]4在导航栏添加一些功能按钮
    [六、页面跳转]5在导航栏视图的底部放置一排工具栏
    [六、页面跳转]7实现导航页面的自定义后退
  • 原文地址:https://www.cnblogs.com/xmqa/p/10253850.html
Copyright © 2020-2023  润新知