Java 调用ffmpeg 实现视频编辑

  • Post author:
  • Post category:java




1. 前言

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。



2.1 实现格式转换功能

该方法就设置了一个入参,即文件路径。参数ffmpegPath是@value引入的yml配置,如下图

在这里插入图片描述

指向的路径下放入FFmpeg的.exe文件即可。

在这里插入图片描述

    @Value("${ffmpeg.path}")
    String ffmpegPath;

public  String transCoding(String path) throws IOException {
        String ffmpegExePath = new ClassPathResource(ffmpegPath+"/ffmpeg.exe").getAbsolutePath();
        ArrayList<String> command = new ArrayList<>();
        command.add(ffmpegExePath);
        command.add("-i");
        command.add(path);
        command.add("-vcodec");
        command.add("copy");
        command.add("-f");
        command.add("mpegts");
        String s = "E:\\data\\split\\" + IdUtil.simpleUUID() + ".mp4";
        command.add(s);
        // 执行操作
        ProcessBuilder builder = new ProcessBuilder();
        builder.command(command);
        builder.redirectErrorStream(true);
        Process process = builder.start();
        return s;
    }



2.2 实现视频剪辑

 public String videoSpit(String path, String startTime, String duration) throws IOException {
        int i = Integer.parseInt(startTime) / 1000;
        int i1 = Integer.parseInt(duration) / 1000;
        String ffmpegExePath = new ClassPathResource(ffmpegPath +"/ffmpeg.exe").getAbsolutePath();
        List<String> command = new ArrayList<>();
        command.add(ffmpegExePath);
        command.add("-ss");
        command.add(String.valueOf(i));
        command.add("-t");
        command.add(String.valueOf(i1));
        command.add("-accurate_seek");
        command.add("-i");
        if (!FileUtil.file(path).isFile()) {
            return "文件不存在,请检查!!";
        }
        command.add(path);
        command.add("-codec");
        command.add("copy");
        command.add("-avoid_negative_ts");
        command.add("1");
        String s = IdUtil.simpleUUID();
        //本地开发写死路径
        String substring = path.substring(path.lastIndexOf("."));
        String e1 = "E:\\data\\split\\" + s + path.substring(path.lastIndexOf("."));
        StringBuilder stringBuffer = new StringBuilder();
        //业务需求,判断是否为mp4,如不需要可以去掉
        if (!"mp4".equals(substring)) {
            String s1 = transCoding(e1);
            command.add(s1);
            stringBuffer.append(s1);
        }else {
            command.add(e1);
            stringBuffer.append(e1);
        }
        try {
            System.out.println(command);
            ProcessBuilder builder = new ProcessBuilder();

            builder.command(command);
            //正常信息和错误信息合并输出

            builder.redirectErrorStream(true);

            //开始执行命令

            Process process = builder.start();
            //如果你想获取到执行完后的信息,那么下面的代码也是需要的

            StringBuilder sbf = new StringBuilder();

            String line;

            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));

            while ((line = br.readLine()) != null) {

                sbf.append(line);

                sbf.append(" ");

            }

            String resultInfo = sbf.toString();

            System.out.println(resultInfo);
            System.out.println(stringBuffer);
            return stringBuffer.toString();
        } catch (IOException e) {
            e.printStackTrace();

        }
        return "操作失败";
    }

path 是文件路径,startTime是开始时间,duration是持续时间,我这里传入的时间是ms,所以先转换成s。方便FFmpeg处理



2.3 实现对指定区域的裁剪并切割

public void spit(String filePath, Integer startTime, String location, String continuous, Integer number) throws IOException {
        ArrayList<String> command = new ArrayList<>();
        DecimalFormat df = new DecimalFormat("0.00");
        StringBuilder stringBuffer = new StringBuilder();
        for (int i = 0; i < number; i++) {
            command.add("E:\\data\\ffmpeg.exe");
            command.add("-ss");
            String format = df.format((float) i / number + startTime);
            System.out.println("开始时间" + format);
            command.add(String.valueOf(format));
            command.add("-i");
            command.add(filePath);
            command.add("-strict");
            command.add("-2");
            command.add("-vf");
            command.add(location);
            command.add("-t");
            command.add(continuous);
            String s = "E:\\data\\spit-test\\2s\\" + format + ".mp4";
            System.out.println(s);
            command.add(s);
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(command);
            System.out.println(command);
            builder.redirectErrorStream(true);
            Process process = builder.start();
            command.removeAll(command);
            StringBuilder sbf = new StringBuilder();

            String line;

            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));

            while ((line = br.readLine()) != null) {

                sbf.append(line);

                sbf.append(" ");

            }

            String resultInfo = sbf.toString();

            System.out.println(resultInfo);
            System.out.println(stringBuffer);
        }
    }


filePath 文件路径

startTime 开始时间(单位/s)

location 裁剪的位置,格式如:crop=w=100:h=100:x=12:y=34 ,其中w和h指的是裁剪完的帧宽度和帧高度,x和y指裁剪的坐标点,裁剪时会按照该点坐标往右下裁剪。

continuous 持续时间

number 颗粒度 该参数是业务为需求定制,因为我需要按照业务会把视频以0.1s、0.01s切片,则此参数影响for循环次数,根据具体业务修改

截取前:

在这里插入图片描述

截取后:

在这里插入图片描述



版权声明:本文为qq_34252622原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。