使用java实现ffmpeg的各种操作

以实现如下功能

  • 1、支持音频文件转mp3;
  • 2、支持视频文件转mp4;
  • 3、支持视频提取音频;
  • 4、支持视频中提取缩略图;
  • 5、支持按时长拆分音频文件;

1、工具类

由于部分原因,没有将FfmpegUtil中的静态的命令行与Type枚举类结合使用。


import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/***
 *
 * @author xuancg
 * 要求系统内置ffmpeg工具环境
 * @date 2024/9/23
 */
@Slf4j
public class FfmpegUtil {

    private static final String CONVERT_MP3 = "ffmpeg -i %s -y %s";

    private static final String CONVERT_MP4 = "ffmpeg -i %s -c:v libx264 -c:a copy -y %s";

    private static final String EXTRACT_MP3 = "ffmpeg -i %s -q:a 0 -map a -y %s";

    private static final String EXTRACT_ICON = "ffmpeg -i %s -ss 0.5 -vframes 1 -r 1 -ac 2 -ab 128k   -y -f mjpeg %s";

    private static final String SPLIT_AUDIO_BY_SIZE = "ffmpeg -i %s  -f segment -segment_time  %d  -c copy -y  %s";


    private static final Set<String> MP3_TYPE = new HashSet<>(Arrays.asList("mp3", "wav", "aac", "flac"));

    private static final Set<String> MP4_TYPE = new HashSet<>(Arrays.asList("mp4", "avi", "flv", "mpeg", "wmv"));


    /***
     * 音视频文件格式化,如果存在目标文件会强制覆盖
     * 1、支持音频文件转mp3;
     * 2、支持视频文件转mp4;
     * 3、支持视频提取音频;
     * 4、支持视频中提取缩略图;
     * 5、支持按时长拆分音频文件;
     */
    public static boolean convertMedia(MediaConvertBo convertBo) {
        File src = convertBo.getSrc();
        File dest = convertBo.getDest();
        if (null == src || !src.isFile()) {
            log.error("原始文件不存在");
            return false;
        }
        if (null != dest && dest.isFile()) {
            log.info("目标文件已存在");
        }
        long start = System.currentTimeMillis();
        Process process = null;
        BufferedReader reader = null;
        try {
            String cmd = createCmd(convertBo);
            if(null == cmd){
                return false;
            }
            log.info("ffmpeg执行命令=" + cmd);
            // 执行命令
            process = Runtime.getRuntime().exec(cmd);
            // 获取命令输出结果
            reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                log.debug(line);
            }
            // 明确自己的命令需要执行多长时间,否则可以一直等待
            int timeout = convertBo.getTimeout();
            if (timeout <= 0) {
                process.waitFor();
            } else {
                process.waitFor(timeout, TimeUnit.SECONDS);
            }
            return dest.isFile() && dest.length() > 10;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            log.error("剪裁视频超时source=" + src.getAbsolutePath());
        } finally {
            if (null != process) {
                process.destroy();
            }
            if (null != reader) {
                try {
                    reader.close();
                } catch (IOException e) {
                    log.error("关闭流失败" + e.getMessage());
                }
            }
            log.info("耗时ms=" + (System.currentTimeMillis() - start));
        }
        return false;

    }


    public static boolean isMp4File(File file){
        String name = file.getName();
        String suffix = name.substring(name.lastIndexOf(".") + 1);
        return MP4_TYPE.contains(suffix);
    }

    public static boolean isMp3File(File file){
        String name = file.getName();
        String suffix = name.substring(name.lastIndexOf(".") + 1);
        return MP3_TYPE.contains(suffix);
    }


    private static final String createCmd(MediaConvertBo bo) {
        File src = bo.getSrc();
        String srcPath = src.getAbsolutePath().replace("\\", "/");
        String destPath = bo.getDest().getAbsolutePath().replace("\\", "/");;
        if (bo.isConvertMp3()) {
            if(!isMp3File(src)){
                log.error("错误的mp3格式");
                return null;
            }
            return String.format(CONVERT_MP3, srcPath, destPath);
        } else if (bo.isConvertMp4()) {
            if(!isMp4File(src)){
                log.error("错误的mp4格式");
                return null;
            }
            return String.format(CONVERT_MP4, srcPath, destPath);
        } else if(bo.getType() == MediaConvertBo.Type.EXTRACT_MP3){
            if(!isMp4File(src)){
                log.error("错误的mp4格式");
                return null;
            }
            return String.format(EXTRACT_MP3, srcPath, destPath);
        } else if(bo.getType() == MediaConvertBo.Type.EXTRACT_ICON) {
            if(!isMp4File(src)){
                log.error("错误的mp4格式");
                return null;
            }
            return String.format(EXTRACT_ICON, srcPath , destPath);

        } else if(bo.getType() == MediaConvertBo.Type.SPLIT_AUDIO_BY_SIZE){
            bo.getDest().mkdirs();
            String name = src.getName();
            String suffix = name.substring(name.lastIndexOf(".") + 1);
            // 保持输入输出一致性
            return String.format(SPLIT_AUDIO_BY_SIZE, srcPath, bo.getSplitSize(), destPath + "/output_%03d." + suffix);
        }

        log.error("错误的type");
        return null;
    }

}

2、入参对象


import lombok.Data;

import java.io.File;

/***
 *
 * @author xuancg
 * @date 2024/9/23
 */
@Data
public class MediaConvertBo {


    private File src;
    private File dest;

    /**0表示持续等待,单位秒*/
    private int timeout = 0;

    /** 拆分时长,单位秒*/
    private int splitSize = 60;

    /**处理类型,必传*/
    private Type type;


    public boolean isConvertMp3(){
        return null != type && type == Type.CONVERT_MP3;
    }

    public boolean isConvertMp4(){
        return null != type && type == Type.CONVERT_MP4;
    }

    public enum Type {
        /**将视频转码成mp4*/
        CONVERT_MP4,
        /**将音频转码成mp3*/
        CONVERT_MP3,
        /**从视频中提取音频*/
        EXTRACT_MP3,
        /**从视频中提取缩略图*/
        EXTRACT_ICON,
        /**按时长拆分音频文件*/
        SPLIT_AUDIO_BY_SIZE,
        ;
    }


}

3、junit测试


import org.junit.Test;

import java.io.File;

/***
 *
 * @author xuancg
 * @date 2024/9/23
 */
public class ConvertTest {

    /**
     * 1分10秒的wav2M大小=转成mp3耗时858ms,200kb大小
     */
    @Test
    public void convertmp3(){
        File src = new File("C:\\Users\\Desktop\\音视频素材\\example.wav");
        File dest = new File("C:\\Users\\Desktop\\音视频素材\\example.mp3");

        MediaConvertBo bo = new MediaConvertBo();
        bo.setType(MediaConvertBo.Type.CONVERT_MP3);
        bo.setSrc(src);
        bo.setDest(dest);

        System.out.println(FfmpegUtil.convertMedia(bo));
    }


    /**
     * 4分13秒视频50M大小=提取音频耗时7秒,4M大小
     */
    @Test
    public void extractMp3(){
        File src = new File("C:\\User\\Desktop\\音视频素材\\202002041032546186.mp4");
        File dest = new File("C:\\User\\Desktop\\音视频素材\\202002041032546186.mp3");

        MediaConvertBo bo = new MediaConvertBo();
        bo.setType(MediaConvertBo.Type.EXTRACT_MP3);
        bo.setSrc(src);
        bo.setDest(dest);
        System.out.println(FfmpegUtil.convertMedia(bo));
    }

    /**
     * 耗时500ms,保持原始视频尺寸
     */
    @Test
    public void extractIcon(){
        File src = new File("C:\\Users\\Desktop\\音视频素材\\202002041032546186.mp4");
        File dest = new File("C:\\Users\\Desktop\\音视频素材\\202002041032546186.jpg");

        MediaConvertBo bo = new MediaConvertBo();
        bo.setType(MediaConvertBo.Type.EXTRACT_ICON);
        bo.setSrc(src);
        bo.setDest(dest);
        System.out.println(FfmpegUtil.convertMedia(bo));
    }


    /**
     * 1分钟2秒
     */
    @Test
    public void splitAudio(){
        File src = new File("C:\\Users\\Desktop\\音视频素材\\example.wav");
        File dest = new File("C:\\Users\\Desktop\\音视频素材\\example");

        MediaConvertBo bo = new MediaConvertBo();
        bo.setType(MediaConvertBo.Type.SPLIT_AUDIO_BY_SIZE);
        bo.setSrc(src);
        bo.setDest(dest);
        bo.setSplitSize(60);
        System.out.println(FfmpegUtil.convertMedia(bo));
    }

}

5、maven依赖

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version> <!-- 版本号可替换为最新版本 -->
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv</artifactId>
    <version>1.5.8</version>
</dependency>

<!-- 此版本中主要兼容linux和windows系统,如需兼容其他系统平台,请引入对应依赖即可 -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>opencv</artifactId>
    <version>4.6.0-1.5.8</version>
    <classifier>linux-x86_64</classifier>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>opencv</artifactId>
    <version>4.6.0-1.5.8</version>
    <classifier>windows-x86_64</classifier>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>openblas</artifactId>
    <version>0.3.21-1.5.8</version>
    <classifier>linux-x86_64</classifier>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>openblas</artifactId>
    <version>0.3.21-1.5.8</version>
    <classifier>windows-x86_64</classifier>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg</artifactId>
    <version>5.1.2-1.5.8</version>
    <classifier>linux-x86_64</classifier>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg</artifactId>
    <version>5.1.2-1.5.8</version>
    <classifier>windows-x86_64</classifier>
</dependency>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/882862.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝队技能-应急响应篇Web内存马查杀JVM分析Class提取诊断反编译日志定性

知识点&#xff1a; 1、应急响应-Web内存马-定性&排查 2、应急响应-Web内存马-分析&日志 注&#xff1a;传统WEB类型的内存马只要网站重启后就清除了。 演示案例-蓝队技能-JAVA Web内存马-JVM分析&日志URL&内存查杀 0、环境搭建 参考地址&#xff1a;http…

常见统计量与其抽样分布

什么是统计量 我们首先给出统计量的定义:设 X 1 , X 2 , ⋯ , X n X_1,X_2,\cdots,X_n X1​,X2​,⋯,Xn​ 为来自于总体X的一个样本&#xff0c; g ( X 1 , X 2 , ⋯ , X n ) g(X_1,X_2,\cdots,X_n) g(X1​,X2​,⋯,Xn​) 为关于 X 1 , X 2 , ⋯ , X n X_1,X_2,\cdots,X_n X…

Python | Leetcode Python题解之第434题字符串中的单词数

题目&#xff1a; 题解&#xff1a; class Solution:def countSegments(self, s):segment_count 0for i in range(len(s)):if (i 0 or s[i - 1] ) and s[i] ! :segment_count 1return segment_count

【JS】严格模式/非严格模式的区别

JS的严格模式和非严格模式 js运行有两种模式&#xff1a;一种是普通模式&#xff1b;一种是严格模式。 严格模式是ES5添加的&#xff0c;是比普通模式多一部分的js规则。如果在ES5之前js解析引擎&#xff0c;会忽略严格模式。 js一般默认是普通模式&#xff0c;ES6的模块和Cla…

数据结构 ——— 数组 nums 包含了从 0 到 n 的所有整数,但是其中缺失了一个,请编写代码找出缺失的整数,并且在O(N)时间内完成

目录 题目要求 代码实现 方法1&#xff08;异或法&#xff09;&#xff1a; 异或算法的时间复杂度&#xff1a; 方法2&#xff08;等差数列公式&#xff09;&#xff1a; 等差数列公式的时间复杂度&#xff1a; 题目要求 整型数组 nums 包含了从 0 到 n 的所有整数&…

VPN概述

目录 定义&#xff1a; VPN的分类 VPN的主要应用场景 GRE VPN概念 GRE VPN的优缺点 GRE VPN应用场景和配置 GRE VPN配置流程 Router A&#xff1a; Router B&#xff1a; 定义&#xff1a; 虚拟专用网络(VPN)是一种通过公用网络线路建立私有网络&#xff0c;用于传输私…

UE学习篇ContentExample解读------Blueprint_Communication-上

文章目录 总览描述批次阅览1.1 Basic communication with a target blueprint1.2 Basic communication via actor casting1.3 Blueprint communication via actor casting to child Blueprint1.4 Communicating with all actors of a specific class 概念总结致谢&#xff1a; …

VulnHub-Narak靶机笔记

Narak靶机笔记 概述 Narak是一台Vulnhub的靶机&#xff0c;其中有简单的tftp和webdav的利用&#xff0c;以及motd文件的一些知识 靶机地址&#xff1a; https://pan.baidu.com/s/1PbPrGJQHxsvGYrAN1k1New?pwda7kv 提取码: a7kv 当然你也可以去Vulnhub官网下载 一、nmap扫…

【专题】2024年中国白酒行业数字化转型研究报告合集PDF分享(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p37755 消费人群趋于年轻化&#xff0c;消费需求迈向健康化&#xff0c;消费场景与渠道走向多元化&#xff0c;这些因素共同驱动企业凭借数据能力来适应市场的变化。从消费市场来看&#xff0c;消费群体、需求、场景及渠道皆展现出与…

PhpStudy | PHP 版本切换流程

关注这个软件的其他相关笔记&#xff1a;PhpStudy —— README-CSDN博客 在使用多样化的 PHP Web 应用程序时&#xff0c;选择合适的 PHP 版本至关重要。例如&#xff0c;一些老旧的应用程序可能是基于早期版本的 PHP 开发的&#xff0c;如果使用最新版本的 PHP 来运行&#xf…

【YOLO学习】YOLOv1详解

文章目录 1. 概述2. 算法流程3. 网络结构4. 损失函数 1. 概述 1. YOLO 的全称是 You Only Look Once: Unified, Real-Time Object Detection。YOLOv1 的核心思想就是利用整张图作为网络的输入&#xff0c;直接在输出层回归 bounding box 的位置和 bounding box 所属的类别。简单…

执行网络攻击模拟的 7 个步骤

在进攻和防守策略方面&#xff0c;我们可以从足球队和美式足球队身上学到很多东西。球员们会分析对方球队的策略&#xff0c;找出弱点&#xff0c;相应地调整进攻策略&#xff0c;最重要的是&#xff0c;练习、练习、再练习。作为最低要求&#xff0c;网络安全部门也应该这样做…

论文笔记(四十六)RobotGPT: Robot Manipulation Learning From ChatGPT

xx RobotGPT: Robot Manipulation Learning From ChatGPT 文章概括摘要I. 介绍II. 相关工作III. 方法论A. ChatGPT 提示机器人操作B. 机器人学习 IV. 实验A. 衡量标准B. 实验设置C. 模拟实验D. 真实机器人实验E. AB测试 V. 结论 文章概括 引用&#xff1a; article{jin2024r…

gateway--网关

在微服务架构中&#xff0c;Gateway&#xff08;网关&#xff09;是一个至关重要的组件&#xff0c;它扮演着多种关键角色&#xff0c;包括路由、负载均衡、安全控制、监控和日志记录等。 Gateway网关的作用 统一访问入口&#xff1a; Gateway作为微服务的统一入口&#xff0c…

Qt窗口——QMenuBar

文章目录 QMenuBar示例演示给菜单栏设置快捷键给菜单项设置快捷键添加子菜单添加分割线添加图标 QMenuBar Qt中采用QMenuBar来创建菜单栏&#xff0c;一个主窗口&#xff0c;只允许有一个菜单栏&#xff0c;位于主窗口的顶部、主窗口标题栏下面&#xff1b;一个菜单栏里面有多…

【Linux实践】实验三:LINUX系统的文件操作命令

【Linux实践】实验三&#xff1a;LINUX系统的文件操作命令 实验目的实验内容实验步骤及结果1. 切换和查看目录2. 显示目录下的文件3. 创建和删除目录① mkdir② rm③ rmdir 4. 输出和重定向① 输出② 重定向 > 和 >> 5. 查看文件内容① cat② head 6. 权限7. 复制8. 排…

科大讯飞智能体Python SDK接入流程

第一步&#xff1a;注册账号​ 进入https://passport.xfyun.cn/login&#xff0c;根据提示注册或登陆账号。 ​ 第二步&#xff1a;创建智能体 进入这个网页创建智能体&#xff0c;填好信息&#xff1a; https://xinghuo.xfyun.cn/botcenter/createbot?createtrue&qu…

【GeekBand】C++设计模式笔记4_Strategy_策略模式

1. “组件协作”模式 现代软件专业分工之后的第一个结果是“框架与应用程序的划分”&#xff0c;“组件协作”模式通过晚期绑定&#xff0c;来实现框架与应用程序之间的松耦合&#xff0c;是二者之间协作时常用的模式。典型模式 Template MethodStrategyObserver / Event 2.…

Webpack 介绍

Webpack 介绍 Date: August 29, 2024 全文概要 Webpack概念&#xff1a; Webpack是一个静态的模块化的打包工具&#xff0c;可以为现代的 JavaSript 应用程序进行打包。 1-静态&#xff1a;Webpack可以将代码打包成最终的静态资源 2-模块化&#xff1a;webpack支持各种模块…

408选择题笔记|自用|随笔记录

文章目录 B树&#xff1a;访问节点建堆&#xff01;将结点插入空堆广义指令求每个子网可容纳的主机数量虚拟内存的实现方式文件目录项FCB和文件安全性管理级别索引文件三种存取方式及适用器件成组分解访问磁盘次数 C语言标识符 最小帧长物理传输层介质 局域网&广域网考点总…