分享一下字节面试被问的一个问题,
Java
使用FFmpeg
处理视频文件的相关内容
能进大厂真的香,你先搞定这些问题。
今天给大家带来用Java + FFmpeg
实现对视频文件的信息提取、码率压缩、分辨率转换等功能;在网上转了一大圈用Java
使用FFmpeg
处理音视频的文章,没有我特别满意的回答,于是自己上手来一篇。希望你们看到这些后能完美避坑!
Fmpeg
是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL
或GPL
许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec
里很多code
都是从头开发的。
提醒一下,更多详情可以去百度了解一下
在使用Java
调用FFmpeg
处理音视频之前,需要先安装FFmpeg
,安装方法分为两种:
FFmpeg
的开源框架FFmpeg
JAVE.jar是一个封装了FFmpeg
的Java
框架,在项目中能直接调用它的API来处理音视频文件;
优点:使用方便,直接在项目中引入JAVE.jar
即可处理媒体文件,且开发完成后可以随工程一起打包发布,不需要在目标运行环境内手动安装FFmpeg
相关的类库
缺点:JAVE.jar
最后一次更新是2009年,其封装的FFmpeg
版本是09年或更早前的版本,比较老旧,无法使用一些新特性 (当然也可以看看有没有其他比较新的封装了FFmpeg
在这里插入代码片的框架) Maven
坐标如下:
<dependency>
<groupId>org.ffmpeg</groupId>
<artifactId>sdk</artifactId>
<version>1.0.2</version>
</dependency>
在运行环境中手动安装FFmpeg
稍微有一些麻烦,可以百度 windows/mac
安装FFmpeg
这样的关键字,根据网上的安装教程将FFmpeg
安装到系统中;
## **懒人安装链接可找我要哒**
优点:可以直接调用FFmpeg
的相关API
处理音视频,FFmpeg
版本可控
缺点:手动安装较为麻烦,开发环境与目标运行环境都需要先安装好FFmpeg
使用JAVE.jar
进行开发与直接使用FFmpeg
开发的代码有一些不同,这里以直接使用FFmpeg
进行开发的代码进行讲解(开发环境MacOS
);(使用JAVE
的代码、、直接使用FFmpeg
的代码都会附在文末供大家下载参考) 通过MediaUtil.java
类及其依赖的类,你将可以实现:
- 解析源视频的基本信息,包括视频格式、时长、码率等;
- 解析音频、图片的基本信息;
- 将源视频转换成不同分辨率、不同码率、带或不带音频的新视频;
- 抽取源视频中指定时间点的帧画面,来生成一张静态图;
- 抽取源视视频中指定时间段的帧画面,来生成一个GIF动态图
- 截取源视频中的一段来形成一个新视频;
- 抽取源视频中的音频信息,生成单独的MP3文件;
- 对音视频等媒体文件执行自定义的FFmpeg命令;
MediaUtil.java
是整个解析程序中的核心类,封装了各种常用的解析方法供外部调用;MetaInfo.java
定义了多媒体数据共有的一些属性.VideoMetaInfo.java
MusicMetaInfo
ImageMetaInfo.java
都继承自MetaInfo.java
,分别定义了视频、音频、图片数据相关的一些属性;AnimatedGifEncoder.java
LZWEncoder.java
NeuQuant.java
在抽取视频帧数、制作GIF动态图的时候会使用到;CrfValueEnum.java 定义了三种常用的FFmpeg压缩视频时使用到的crf值,PresetVauleEnum.java定义了FFmpeg压缩视频时常用的几种压缩速率值;
1、指定正确的FFmpeg
程序执行路径
MacOS
安装好FFmpeg
后,可以在控制台中通过which ffmpeg
命令获取FFmpeg
程序的执行路径,在调用MediaUtil.java
前先通过其 setFFmpegPath
() 方法设置好FFmpeg
程序在系统中的执行路径,然后才能顺利调用到FFmpeg
去解析音视频;
Windows系统下该路径理论上应设置为:FFmpeg
可执行程序在系统中的绝对路径(实际情况有待大家补充)
2、指定解析音视频信息时需要的正则表达式
因项目需要解析后缀格式为 .MP4
.WMV
.AAC
的视频和音频文件,所以我研究了JAVE.jar
底层调用FFmpeg
时的解析逻辑后,在MediaUtil.java
中设置好了匹配这三种格式的正则表
注意:如果你需要解析其他后缀格式如 .MKV
.MP3
这样的媒体文件时,你很可能需要根据实际情况修改durationRegex videoStreamRegex musicStreamRegex
这三个正则表达式的值,否则可能无法解析出正确的信息;
3、程序中的很多默认值你可以根据实际需要修改,比如视频帧抽取的默认宽度或高度值、时长等等;
3.2.2 MediaUtil.java代码
卖个关子,不会吧真有人看到这里了,是不是卡住了,不用担心,自己做一遍,源码可call me我发现尽管我一顿卡卡卡没有用,你得真正接收到我的信号才行。咱们接着
1、在Linux等服务器上部署Java程序进行视频压缩时,多注意一下运行账号的权限问题,有时候可能是由于运行程序没有足够的文件操作权限,导致压缩过程失败;
2、第一版程序上线后,偶尔会出现这样的问题:
MediaUtil.java
进行视频压缩过程中,整个程序突然“卡住”,后台也没有日志再打印出来,此时整个压缩过程还没有完成,像是线程突然阻塞住了;Java
调用FFmpeg
时,实际是在JVM
里产生一个子进程来执行压缩过程,这个子进程与JVM
建立三个通道链接(包括标准输入、标准输出、标准错误流),在压缩过程中,实际会不停地向标准输输出和错误流中写入信息;MediaUtil.java
中的executeCommand
() 方法中的 errorStream
这下可以去面试了吧,字节等你
想要更清晰的源码可以告诉我
整理不易,记得三连