zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    CodeForces 706C Hard problem
    CodeForces 706A Beru-taxi
    CodeForces 706B Interesting drink
    CodeForces 706E Working routine
    CodeForces 706D Vasiliy's Multiset
    CodeForces 703B Mishka and trip
    CodeForces 703C Chris and Road
    POJ 1835 宇航员
    HDU 4907 Task schedule
    HDU 4911 Inversion
  • 原文地址:https://www.cnblogs.com/xmqa/p/10253850.html
Copyright © 2011-2022 走看看