基于FFmpeg的Java视频Mp4转GIF初探

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

背景

       在一些业务场景中会有如下的一些要求比如有用户需要将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等。

  1. libavformat用于各种音视频封装格式的生成和解析包括获取解码所需信息以生成解码上下文结构
  2. 和读取音视频帧等功能
  3. libavcodec用于各种类型声音/图像编解码
  4. libavutil包含一些公共的工具函数
  5. libswscale用于视频场景比例缩放、色彩映射转换
  6. libpostproc用于后期效果处理
  7. ffmpeg该项目提供的一个工具可用于格式转换、解码
  8. ffsever一个 HTTP 多媒体即时广播串流服务器
  9. 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具体使用如果在工作中有这种需要不妨采用这种方式。希望本文对您有所帮助欢迎指导交流。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java