视频处理工具类

业务需求:
根据传送来的服务器路径地址(至少一个,最多三个),将视频下载到本地指定路径,下载好后设置时间间隔,对视频进行图片截取并且按照指定的命名方式存到指定路径中。

包含的工具类有:

  • 视频下载工具类
  • 视频帧图片截取工具类
  • 文件夹内文件名重复处理工具类
  • 获得视频时长工具类

服务器上下载文件并保存到本地

import org.jboss.logging.Logger;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * 视频下载 工具类
 */
public class FileDownloadUtil {

    private static final Logger LOGGER = Logger.getLogger(FileDownloadUtil.class);

    /**
     * 下载文件到本地
     *
     * @功能 服务器上下载文件并保存到本地
     * @param filePath 文件将要保存的目录
     * @param url 请求的服务器路径
     * @return
     */
    public static File saveUrlAs(String url, String filePath){
        //System.out.println("fileName---->"+filePath);
        //创建不同的文件夹目录
        File file=new File(filePath);
        //判断文件夹是否存在
        if (!file.exists())
        {
            //如果文件夹不存在,则创建新的的文件夹
            file.mkdirs();
        }
        FileOutputStream fileOut = null;
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        try
        {
            // 建立链接
            URL httpUrl=new URL(url);
            conn=(HttpURLConnection) httpUrl.openConnection();
            //以Post方式提交表单,默认get方式
            conn.setRequestMethod("GET");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            // post方式不能使用缓存
            conn.setUseCaches(false);
            //连接指定的资源
            conn.connect();
            //获取网络输入流
            inputStream=conn.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(inputStream);
            //判断文件的保存路径后面是否以/结尾
            if (!filePath.endsWith("/")) {

                filePath += "/";

            }
            //写入到文件(注意文件保存路径的后面一定要加上文件的名称)
            fileOut = new FileOutputStream(filePath+new SimpleDateFormat("HHmmss").format(new Date())+".mp4");
            BufferedOutputStream bos = new BufferedOutputStream(fileOut);

            byte[] buf = new byte[4096];
            int length = bis.read(buf);
            //保存文件
            while(length != -1)
            {
                bos.write(buf, 0, length);
                length = bis.read(buf);
            }
            bos.close();
            bis.close();
            conn.disconnect();
        } catch (Exception e)
        {
            e.printStackTrace();
            System.out.println("抛出异常!!");
        }
        return file;
    }
}

视频取帧,可设置间隔秒数或获取所有帧数

import org.apache.commons.lang.StringUtils;
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.ArrayList;
import java.util.Collections;


/**
 * 视频取帧,可设置间隔秒数或获取所有帧数
 */
public class FetchVideoFrameUtil {

    /**
     * 获取指定视频的帧并保存为图片至指定目录
     * @param file    源视频文件
     * @param picPath 截取帧的图片存放路径
     * @throws Exception
     */
    public static void fetchPic(File file, String picPath) throws Exception {

        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); // 获取视频文件
        System.out.println("视频总长度 " + FetchVideoFrameUtil.getVideoTime(file)); // 显示视频长度(秒/s)
        if (FetchVideoFrameUtil.getVideoTime(file) == 0){
            System.out.println("该视频文件已经损毁,无法播放");
        }

        ff.start(); // 调用视频文件播放
        int length = ff.getLengthInAudioFrames(); //视频帧数长度
        int second = (int) ff.getFrameRate();
        System.out.println("视频帧数长度 " + ff.getFrameRate());

        int i = 0; // 图片帧数,如需跳过前几秒,则在下方过滤即可
        Frame frame = null;
//        int count = 0;
        int count = second;
        while (i < length) {
            frame = ff.grabImage(); // 获取该帧图片流
//            System.out.print(i + ",");
            if (i >= second && frame != null && frame.image != null) {
//                System.out.println(i);
                writeToFile(frame, picPath, count, second); // 生成帧图片
                count++;
            }
            i++;
        }
        ff.stop();
    }

    /**
     * 截取到的帧图片写入指定文件夹
     *
     * @param frame   // 视频文件对象
     * @param picPath // 图片存放路径
     * @param count   // 当前取到第几帧
     * @param second  // 每隔多少帧取一张,一般高清视频每秒 20-24 帧,根据情况配置,如果全部提取,则将second设为 0 即可
     */
    public static void writeToFile(Frame frame, String picPath, int count, int second) {

        //创建不同的文件夹目录
        File file = new File(picPath);

        //判断文件夹是否存在
        if (!file.exists()) {
            //如果文件夹不存在,则创建新的的文件夹
            file.mkdirs();
        }

        if (second == 0) {
            // 跳过间隔取帧判断
        } else if (count % second != 0) { // 提取倍数,如每秒取一张,则: second = 20
            return;
        }
        int num = FetchVideoFrameUtil.getFileName(file,count / second);
        String fileName = "1-" + num + ".jpg";//图片命名
        File targetFile = new File(picPath + fileName);

        String imgSuffix = "jpg";

        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage srcBi = converter.getBufferedImage(frame);
        int owidth = srcBi.getWidth();
        int oheight = srcBi.getHeight();
        // 对截取的帧进行等比例缩放
        int width = 800;
        int height = (int) (((double) width / owidth) * oheight);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
        try {
            ImageIO.write(bi, imgSuffix, targetFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取视频时长,单位为秒
     * @param file
     * @return 时长(s)
     */
    public static Long getVideoTime(File file) {
        Long times = 0L;
        try {
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
            ff.start();
            times = ff.getLengthInTime() / (1000 * 1000);
            ff.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return times;
    }

    /**
     * 存入图片名称重复处理 工具类
     * @param file
     * @return
     */
    public static Integer getFileName(File file,int num){
        // 获得该文件夹内的所有文件
        File[] array = file.listFiles();
        ArrayList<Integer> list = new ArrayList<>();
        for(int i=0;i<array.length;i++) {
            if(array[i].isFile())//如果是文件
            {       //截取视频命名中的数字字符串并转化成数字类型
                list.add(Integer.parseInt(StringUtils.substring(array[i].getName(),2,array[i].getName().indexOf('.'))));
            }
        }
        //对list集合倒叙排序
        Collections.sort(list, Collections.reverseOrder());
        for (int i = 0; i < list.size(); i++){
            if(num == list.get(i)){
                num =  list.get(0) +1;
            }
        }
        return num;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YD_1989

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值