音视频处理工具FFmpeg与Java结合的简单使用

createh54个月前 (01-10)技术教程32

一、什么是FFmpeg

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。项目的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward"。 -- 引用自百度百科


二、项目组成

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

libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能;

libavcodec:用于各种类型声音/图像编解码;

libavutil:包含一些公共的工具函数;

libswscale:用于视频场景比例缩放、色彩映射转换;

libpostproc:用于后期效果处理;

ffmpeg:该项目提供的一个工具,可用于格式转换、解码或电视卡即时编码等;

ffsever:一个 HTTP 多媒体即时广播串流服务器;

ffplay:是一个简单的播放器,使用ffmpeg 库解析和解码,通过SDL显示;


三、FFmpeg使用场景

3.1、以下列举几个开发中常用的功能:

  • ffmpeg在Linux下和windows下的视频采集;
  • 视频格式转换;
  • 视频截图功能;
  • 音视频合成功能;
  • 视频添加水印功能;

3.2、谁在使用:

  • 使用FFmpeg作为内核视频播放器:Mplayer,ffplay,射手播放器,暴风影音,KMPlayer,QQ影音等
  • 使用FFmpeg作为内核的Directshow Filter:ffdshow,lav filters等
  • 使用FFmpeg作为内核的转码工具:ffmpeg,格式工厂等

四、如何使用

4.1、FFmpeg如何下载和安装

FFmpeg可以在Linux、windows以及Mac系统中使用,官网提供了各种系统的安装包,下载安装包请移步FFmpeg官网:FFmpeg

安装包下载完成后,对其进行解压,由于我的开发环境为Windows系统,就已Windows安装包为例进行演示。解压后的目录结构如下图所示:

以上目录中,我们使用最多的就是bin目录下的ffmpeg.exe文件了,官网给出了一个简单的例子,我们先来看一下:

转换视频和音频从未如此简单。

图中的命令是Linux下进行操作的,Windows下并无差异,下面我们分别来使用命令行以及Java代码来进行演示视频格式转换、音视频合并以及视频按帧截图功能。

相关学习资料推荐,点击下方链接免费报名,先码住不迷路~】

音视频免费学习地址:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发

【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~


4.2、视频格式转换

首先我们要来到FFmpeg的解压目录,进入到bin目录中,在此目录中打开cmd工具。如下图所示:

注:在地址栏中输入“cmd”,按回车,即可在此目录直接打开cmd工具。此处我准备了一个视频文件以及一个音频文件用于下面功能演示。

在cmd工具中键入以下命令即可完成视频格式的转换:

ffmpeg.exe -i test1.mp4 newVideo.avi

具体使用请参考官方文档:ffmpeg Documentation

具体效果如下图所示:

以上是使用命令行进行操作,也可在Java中进行操作:

视频格式转换代码:

/**
 * 简易视频处理 -- (cmd(windows): ffmpeg.exe -i test1.mp4 newVideo.avi)
 *
 * @param ffmpegPath      ffmpeg.exe文件路径,可在rest或者admin中进行配置,使用配置文件进行读取
 * @param videoInputPath  视频文件路径(输入)
 * @param videoOutputPath 转换完成的文件路径(输出)
 * @throws IOException
 */
public static void videoConvert(String ffmpegPath, String videoInputPath, String videoOutputPath) throws IOException {
	// 构建命令
	List<String> command = Lists.newArrayList();
	command.add(ffmpegPath);
	command.add("-i");
	command.add(videoInputPath);
	command.add(videoOutputPath);
	// 执行操作
	ProcessBuilder builder = new ProcessBuilder(command);
	Process process = builder.start();
	InputStream errorStream = process.getErrorStream();
	InputStreamReader isr = new InputStreamReader(errorStream);
	BufferedReader br = new BufferedReader(isr);
	String line = "";
	while ((line = br.readLine()) != null) {
	}
	if (br != null) {
		br.close();
	}
	if (isr != null) {
		isr.close();
	}
	if (errorStream != null) {
		errorStream.close();
	}
}

测试代码:

@Test
public void testVideoConvert() {
	FfmpegProperties ffmpegProperties = SpringContextHolder.getBean(FfmpegProperties.class);
	try {
		FfmpegUtil.videoConvert(ffmpegProperties.getFfmpegFile(), "D:\\tools\\ffmpeg\\bin\\test1.mp4", "D:\\tools\\ffmpeg\\bin\\newVideo.avi");
	} catch (IOException e) {
		e.printStackTrace();
	}
}

由于使用的是SpringBoot,ffmpeg.exe文件路径配置在了appliction.yml中,所以使用了自定义的FfmpegProperties对其进行读取,下述所有例子均使用相同配置,如下所示:

ffmpeg:
  ffmpegFile: D:/tools/ffmpeg/bin/ffmpeg.exe #ffmpeg可执行文件路径
  outputVideoSuffix: .mp4 #输出视频的后缀名
  outputCoverSuffix: .jpg #输出缩略图的后缀名

4.3、音视频合并

音视频合并会使用到两个输入资源,一个音频资源和一个视频资源,此处的例子为一个10s的视频与一个20s的音频,我要达到的效果是视频播放完毕,便退出播放,剩余音频不再进行播放。

ffmpeg.exe -i test2.mp3 -i test1.mp4 -t 10 -y newVideo.mp4

此处:-t代表的是视频的时间,而-y代表覆盖输出文件,直接在cmd工具中执行命令即可

注:在编写命令是,音频文件一定要在视频文件的前面,否则合成出来的视频是有问题的,你会发现音频并没有合成进来。

以上是使用命令行进行操作,也可在Java中进行操作:

/**
 * 音视频合并,视频结束,音频结束 -- (cmd(windows): ffmpeg.exe -i test2.mp3 -i test1.mp4 -t 10 -y newVideo.mp4)
 *
 * @param ffmpegPath      ffmpeg.exe文件路径,可在rest或者admin中进行配置,使用配置文件进行读取
 * @param audioInputPath  音频文件路径(输入)
 * @param videoInputPath  视频文件路径(输入)
 * @param time            文件时长
 * @param videoOutputPath 转换完成的文件路径(输出)
 * @throws IOException
 */
public static void audioVideoMerge(String ffmpegPath, String audioInputPath, String videoInputPath, double time, String videoOutputPath) throws IOException {
	// 构建命令
	List<String> command = Lists.newArrayList();
	command.add(ffmpegPath);
	command.add("-i");
	command.add(audioInputPath);
	command.add("-i");
	command.add(videoInputPath);
	command.add("-t");
	command.add(String.valueOf(time));
	command.add("-y");
	command.add(videoOutputPath);
	// 执行操作
	ProcessBuilder builder = new ProcessBuilder(command);
	Process process = builder.start();
	InputStream errorStream = process.getErrorStream();
	InputStreamReader isr = new InputStreamReader(errorStream);
	BufferedReader br = new BufferedReader(isr);
	String line = "";
	while ((line = br.readLine()) != null) {
	}
	if (br != null) {
		br.close();
	}
	if (isr != null) {
		isr.close();
	}
	if (errorStream != null) {
		errorStream.close();
	}
}

测试代码:

@Test
public void testAudioVideoMerge() {
	FfmpegProperties ffmpegProperties = SpringContextHolder.getBean(FfmpegProperties.class);
	try {
		FfmpegUtil.audioVideoMerge(ffmpegProperties.getFfmpegFile(), "D:\\tools\\ffmpeg\\bin\\test2.mp3", "D:\\tools\\ffmpeg\\bin\\test1.mp4", 10, "D:\\tools\\ffmpeg\\bin\\newVideo.mp4");
	} catch (IOException e) {
		e.printStackTrace();
	}
}

4.4、视频按帧截图

这个功能没什么好说的,主要用于用户手动截图或者上传视频生成缩略图。

ffmpeg.exe -ss 00:00:01 -y -i test1.mp4 -vframes 1 new.jpg

此处:-ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持,-vframes 设置转换多少桢(frame)的视频,此命令是获取第一秒第一帧的截图。

注:生成的截图最好使用jpg格式,占用空间较小,如果需要使用其他格式,根据业务需求自行设置即可。

以上是使用命令行进行操作,也可在Java中进行操作:

/**
 * 获取第一秒第一帧的缩略图 -- (cmd(windows): ffmpeg.exe -ss 00:00:01 -y -i test1.mp4 -vframes 1 new.jpg)
 *
 * @param ffmpegPath      ffmpeg.exe文件路径,可在rest或者admin中进行配置,使用配置文件进行读取
 * @param videoInputPath  视频文件路径(输入)
 * @param coverOutputPath 缩略图输出路径
 * @throws IOException
 */
public static void getVideoCover(String ffmpegPath, String videoInputPath, String coverOutputPath) throws IOException {
	// 构建命令
	List<String> command = Lists.newArrayList();
	command.add(ffmpegPath);
	command.add("-ss");
	command.add("00:00:01");
	command.add("-y");
	command.add("-i");
	command.add(videoInputPath);
	command.add("-vframes");
	command.add("1");
	command.add(coverOutputPath);
	// 执行操作
	ProcessBuilder builder = new ProcessBuilder(command);
	Process process = builder.start();
	InputStream errorStream = process.getErrorStream();
	InputStreamReader isr = new InputStreamReader(errorStream);
	BufferedReader br = new BufferedReader(isr);
	String line = "";
	while ((line = br.readLine()) != null) {
	}
	if (br != null) {
		br.close();
	}
	if (isr != null) {
		isr.close();
	}
	if (errorStream != null) {
		errorStream.close();
	}
}

测试代码:

@Test
public void testGetVideoCover() {
	FfmpegProperties ffmpegProperties = SpringContextHolder.getBean(FfmpegProperties.class);
	try {
		FfmpegUtil.getVideoCover(ffmpegProperties.getFfmpegFile(), "D:\\tools\\ffmpeg\\bin\\test1.mp4", "D:\\tools\\ffmpeg\\bin\\new.jpg");
	} catch (IOException e) {
		e.printStackTrace();
	}
}

以上就是FFmpeg的简单使用,如果有更为复杂的需求,直接参考官方文档进行使用即可。

原文 https://zhuanlan.zhihu.com/p/38961122

相关文章

第十五章:Java测试和调试(完结)

在软件开发的过程中,测试和调试是不可或缺的环节。测试是用于验证程序的正确性和稳定性,而调试则是用于排查和修复程序中的错误。本章将介绍Java中的测试和调试相关的概念、方法、工具和技巧。15.1 Jav...

Java First Hello World 程序

1.先决条件要编写您的第一个程序,您需要:Java SE 开发工具包 8 (JDK 8)您现在可以下载 Windows 版本。(确保您下载的是 JDK,而不是 JRE。)请参阅安装说明。文本编辑器在此...

Java环境变量配置

Java环境变量配置文章目录Java环境变量配置1.下载jdk2.安装jdk2.1 单击exe文件安装(一路下一步)2.2安装成功3.配置环境变量3.1找到环境变量配置页面3.2点击环境变量进行如下设...

Java9模块化出来这么久了,你了解过没(入门使用指南)

1.概述Java9在包之上引入了一个新的抽象级别,正式名称为 Java 平台模块系统(JavaPlatform Module System,JPMS) ,简称模块。接下来,这篇文章将会介绍模块化的基本...

6 款 Java 8 自带工具,轻松分析定位 JVM 问题

这篇文章中介绍下如何使用 JDK 自带工具来分析和定位 Java 程序的问题。使用 JDK 自带工具查看 JVM 情况JDK 自带了很多命令行甚至是图形界面工具,帮助我们查看 JVM 的一些信息。比如...

JAVA代审-RuoYi4.6.0

项目介绍一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,C...