首页 > 编程语言 >音视频处理工具FFmpeg与Java结合的简单使用

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

时间:2023-06-26 17:02:09浏览次数:44  
标签:视频 Java ffmpeg mp4 音视频 String add command FFmpeg

一、什么是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安装包为例进行演示。解压后的目录结构如下图所示:

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

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

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

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


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


4.2、视频格式转换


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

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

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


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


ffmpeg.exe -i test1.mp4 newVideo.avi

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


具体效果如下图所示:

音视频处理工具FFmpeg与Java结合的简单使用_文件路径_04

以上是使用命令行进行操作,也可在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的简单使用,如果有更为复杂的需求,直接参考官方文档进行使用即可。

标签:视频,Java,ffmpeg,mp4,音视频,String,add,command,FFmpeg
From: https://blog.51cto.com/u_16159766/6555961

相关文章

  • FFmpeg混流及录制rtmp直播流
    1、什么是混流?混流就是把多路音视频流合成单流。准确的说,混流应该叫做混音(音频流)混画面(视频流)混流的过程包括解码、混流、编码和推流四个部分。混流这个环节包括做抖动缓冲,目的是把多路流进行画面对齐和音画同步,同时通过缓冲对抗网络抖动,以便混合成一路流以后能够达到良好的效果。......
  • JavaScript进阶13笔记
    数字和日期数字在JavaScript里面,数字均为双精度浮点类型,即一个介于±2^−1023和±2^+1024之间的数字,或约为±10^−308到±10^+308,数字精度为53位。整数数值仅在±(2^53-1)的范围内可以表示准确。即一个介于±2^−1023和±2^+1024之间的数字,或约为±10^−30......
  • JavaScript进阶15笔记
    正则表达式正则表达式是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象。这些模式被用于RegExp的exec和test方法,以及String的match、matchAll、replace、search和split方法。本章介绍JavaScript正则表达式。 创建一个正则表达式你可以使......
  • JavaScript进阶14笔记.md
    文本格式化字符串JavaScript中的String类型用于表示文本型的数据。它是由无符号整数值(16bit)作为元素而组成的集合。字符串中的每个元素在字符串中占据一个位置。第一个元素的index值是0,下一个元素的index值是1,以此类推。字符串的长度就是字符串中所含的元素个数。你可......
  • JavaScript进阶17笔记
    带键的集合这一章介绍由key值标记的数据容器;Map和Set对象承载的数据元素可以按照插入时的顺序被迭代遍历。 映射Map对象ECMAScript2015引入了一个新的数据结构来将一个值映射到另一个值。一个Map对象就是一个简单的键值对映射集合,可以按照数据插入时的顺序遍历所有的......
  • JavaScript进阶16笔记
    集合类JavaScript中没有明确的数组数据类型。但是,你可以使用预定义的Array对象及其方法来处理应用程序中的数组。Array对象具有以各种方式操作数组的方法,例如连接、反转和排序。它有一个用于确定数组长度的属性和用于正则表达式的其他属性。 创建数组以下语句创建了等效......
  • JavaScript进阶19笔记
    使用PromisePromise是一个对象,它代表了一个异步操作的最终完成或者失败。本质上Promise是一个函数返回的对象,我们可以在它上面绑定回调函数,这样我们就不需要在一开始把回调函数作为参数传入这个函数了。假设现在有一个名为createAudioFileAsync()的函数,它接收一些配置和两......
  • JavaScript进阶18笔记.md
    使用对象JavaScript的设计是一个简单的基于对象的范式。一个对象就是一系列属性的集合,一个属性包含一个名和一个值。一个属性的值可以是函数,这种情况下属性也被称为方法。除了浏览器里面预定义的那些对象之外,你也可以定义你自己的对象。本章节讲述了怎么使用对象、属性、函数和......
  • ffmpeg开发程序的实例代码
    以下是一个使用ffmpeg库解码视频文件并输出每个帧的示例代码:```c++includeincludeincludeifdef__cplusplusextern"C"{endifinclude<libavcodec/avcodec.h>include<libavformat/avformat.h>include<libswscale/swscale.h>ifdef__cplusplus}endifusingn......
  • JavaScript基础第06天笔记
    1-内置对象1.1内置对象JavaScript中的对象分为3种:自定义对象、内置对象、浏览器对象​前面两种对象是JS基础内容,属于ECMAScript;第三个浏览器对象属于JS独有的,JSAPI讲解内置对象就是指JS语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基......