Java基于FFmpeg实现Mp4视频转GIF

 更新时间:2022年11月21日 11:46:15   作者:yelangking1  
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。本文主要介绍了在Java中如何基于FFmpeg进行Mp4视频到Gif动图的转换,感兴趣的小伙伴可以了解一下

背景

在一些业务场景中,会有如下的一些要求:比如有用户需要将Mp4视频转为Gif动图。当然有一些小伙伴说可以使用系统截图,然后使用之前提到过的技术:GIF图像动态生成-JAVA后台生成。需要处理的素材比较少,就一两个视频,确实可以通过这种方式来处理。试想一下,如果需要处理上百个,做处理的小伙伴是不是就抓狂了,这完全是实打实的工作量。那有没有直接从Mp4转成gif动态图的技术呢?运营的小伙伴就能按时下班了。

经过一番查询,找到一些思路,Mp4视频的组成也是一帧一帧的图像组成的。如果有什么技术可以去动态获取这些数据,通过动态截取每一帧,最后再合成图片。不久解决了吗?FFmpeg变进入技术选型的视野。本文主要讲解如何在Java中,使用FFmpeg进行视频的帧读取,并最终合并成Gif动态图。

一、FFmpeg是什么

1、简介

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows、Max Os等。这个项目最早由Fabrice Bellard发起,2004年至2015年间由Michael Niedermayer主要负责维护。许多FFmpeg的开发人员都来自项目MPlayer,而且当前FFmpeg也是放在MPlayer项目组的服务器上。

2、FFmpeg功能列表

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它包括了领先的音/视频编码库libavcodec等。

  • libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能;
  • libavcodec:用于各种类型声音/图像编解码;
  • libavutil:包含一些公共的工具函数;
  • libswscale:用于视频场景比例缩放、色彩映射转换;
  • libpostproc:用于后期效果处理;
  • ffmpeg:该项目提供的一个工具,可用于格式转换、解码;
  • ffsever:一个 HTTP 多媒体即时广播串流服务器;
  • ffplay:是一个简单的播放器,使用ffmpeg 库解析和解码,通过SDL显示;

二、Java集成JavaCV调用FFmpeg

1、JavaCv引入

JavaCv是基于openCv的一个非常强大的库,关于javaCv以后计划做几次讲解,这里不深入,有兴趣的小伙伴可以先行学习。在工程中新建一个Maven工程,在Pom.xml中引入支持,需要注意的是,这里为了演示简单,引入了完整的JavaCv的包,在实际项目中不需要如此,按需引入即可。

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.yelang</groupId>
    <artifactId>mp42gif</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.madgag/animated-gif-lib -->
        <dependency>
            <groupId>com.madgag</groupId>
            <artifactId>animated-gif-lib</artifactId>
            <version>1.4</version>
        </dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        
        <!-- lombok 代码自动生成组件 add by wuzuhu on 2022-11-01 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

2、视频转换读取

public static void main(String[] args) {
    // 将指定目录的 MP4 文件生成同名的 gif 文件
    File videoDir = new File("E:/testv");
    for (File file : videoDir.listFiles()) {
        String videoPath = file.getPath();
        if (videoPath.endsWith(".mp4")) {
            String gifPath = videoPath.substring(0, videoPath.lastIndexOf(".")) + ".gif";
            try {
                video2Gif(videoPath, gifPath);
                System.out.println("转换完成");
            } catch (Exception e) {
                System.out.println("文件 [" + videoPath + "] 处理异常!");
                e.printStackTrace();
            }
        }
    }
}

上面定义了一个main函数调用,只是一个简单的示例,实际项目需要自己扩展。核心的视频转换函数如下:

private static void video2Gif(String videoPath, String gifPath) throws Exception {
    try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoPath);
            FileOutputStream targetFile = new FileOutputStream(gifPath)) {
        grabber.start();
        int frames = grabber.getLengthInFrames();
        System.out.println(frames);
        AnimatedGifEncoder encoder = new AnimatedGifEncoder();
        encoder.setFrameRate(frames);
        encoder.start(targetFile);
        Java2DFrameConverter converter = new Java2DFrameConverter();
        for (int i = 0; i < frames; i += 8) {// 8帧合成1帧?(反正越大动图越小、越快)
            encoder.setDelay((int) grabber.getDelayedTime());
            encoder.addFrame(converter.convert(grabber.grabImage()));
            grabber.setFrameNumber(i);
        }
            
        encoder.finish();
    }
}

通过FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoPath);获取视频信息,同时调用grabber.start();进行视频读取(这一步必须要设置,否则会影响后面的结果)。通过int frames = grabber.getLengthInFrames();获取Mp4视频的帧数,再循环帧,即可。上述的代码中不是读取每一帧,这样生成的结果会非常大,建议不要全部读取。

for (int i = 0; i < frames; i += 8) {// 8帧合成1帧)
    encoder.setDelay((int) grabber.getDelayedTime());
    encoder.addFrame(converter.convert(grabber.grabImage()));
    grabber.setFrameNumber(i);
}

3、运行结果

使用一段视频来测试相应的功能能否正常生效,在E盘新建一个mp4视频文件。

使用上述视频来验证代码是否正确运行,通过Debug来观察程序的运行。

最后在测试的目录中,发现已经成功生成对应的gif图片,拖到浏览器中可以正常展示。

三、总结

本文主要简单介绍了在Java中如何基于FFmpeg进行Mp4视频到Gif动图的转换。首先简单讲解FFmpeg的定义,常用的方法,然后重点介绍JavaCv中FFmpeg具体使用,如果在工作中有这种需要,不妨采用这种方式。

以上就是Java基于FFmpeg实现Mp4视频转GIF的详细内容,更多关于Java FFmpeg Mp4转GIF的资料请关注脚本之家其它相关文章!

相关文章

  • Java中特殊运算符及其应用详解

    Java中特殊运算符及其应用详解

    当涉及位操作和位级运算时,Java 提供了一组特殊的运算符,即左移(<<)和右移(>>)运算符,下面小编就带大家深入了解一下它们的具体应用吧
    2023-08-08
  • Mybatis动态SQL之IF语句详解

    Mybatis动态SQL之IF语句详解

    这篇文章主要给大家介绍了关于Mybatis动态SQL之IF语句的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • Java函数式编程(三):列表的转化

    Java函数式编程(三):列表的转化

    这篇文章主要介绍了Java函数式编程(二):列表的转化,lambda表达式不仅能帮助我们遍历集合,并且可以进行集合的转化,需要的朋友可以参考下
    2014-09-09
  • Spring中BeanFactory和ApplicationContext的作用和区别(推荐)

    Spring中BeanFactory和ApplicationContext的作用和区别(推荐)

    这篇文章主要介绍了Spring中BeanFactory和ApplicationContext的作用和区别,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • Java实现经典大富翁游戏的示例详解

    Java实现经典大富翁游戏的示例详解

    大富翁,又名地产大亨。是一种多人策略图版游戏。参与者分得游戏金钱,凭运气(掷骰子)及交易策略,买地、建楼以赚取租金。本文将通过Java实现这一经典游戏,感兴趣的可以跟随小编一起学习一下
    2022-02-02
  • SpringBoot 调用外部接口的三种实现方法

    SpringBoot 调用外部接口的三种实现方法

    Spring Boot调用外部接口的方式有多种,常见的有以下三种方式:RestTemplate、Feign 和 WebClient,本文就详细介绍一下,感兴趣的可以了解一下
    2023-08-08
  • Java使用poi做加自定义注解实现对象与Excel相互转换

    Java使用poi做加自定义注解实现对象与Excel相互转换

    这篇文章主要介绍了Java使用poi做加自定义注解实现对象与Excel相互转换,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • 详解Spring Boot 项目部署到heroku爬坑

    详解Spring Boot 项目部署到heroku爬坑

    这篇文章主要介绍了详解Spring Boot 项目部署到heroku爬坑,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • java配置dbcp连接池(数据库连接池)示例分享

    java配置dbcp连接池(数据库连接池)示例分享

    java配置dbcp连接池示例分享,大家参考使用吧
    2013-12-12
  • JAVA装饰者模式(从现实生活角度理解代码原理)

    JAVA装饰者模式(从现实生活角度理解代码原理)

    装饰者模式可以动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。这篇文章主要介绍了JAVA装饰者模式的相关资料,需要的朋友可以参考下
    2016-12-12

最新评论