一.ffmpeg
1.简介
FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。
FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows、Mac OS X等。
多媒体视频处理工具FFmpeg有非常强大的功能,包括视频采集功能、视频格式转换、视频抓图、给视频加水印等。
ffmpeg在windows下的视频采集
在windows下关于ffmpeg视频采集的资料非常少,但是ffmpeg还是支持windows下视频采集的。ffmpeg支持windows下video for windows(VFW)设备的视频采集,不过VFW设备已经过时,正在被WDM的视频设备所取代,但是ffmpeg还没有支持WDM的计划,不过好像有将WDM转为VFW的工具,因此ffmpeg还是可以在windows下进行视频采集的。
视频格式转换功能
ffmpeg视频转换功能。视频格式转换,比如可以将多种视频格式转换为flv格式,可不是视频信号转换 。
ffmpeg可以轻易地实现多种视频格式之间的相互转换(wma,rm,avi,mod等),例如可以将摄录下的视频avi等转成现在视频网站所采用的flv格式。
视频截图功能
对于选定的视频,截取指定时间的缩略图。视频抓图,获取静态图和动态图,不提倡抓gif文件;因为抓出的gif文件大而播放不流畅
给视频加水印功能
使用ffmpeg 视频添加水印(logo)。
2.mac下安装ffmpeg
(2)先安装Homebrew
终端下直接输入以下命令即可:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
(2)安装ffmpeg
终端下直接输入以下命令即可:
brew install ffmpeg
安装后输入ffmpeg命令
3.ffmpeg常用命令
将视频 MP4 转化为 GIF
ffmpeg -i small.mp4 small.gif
转化视频中的一部分为 GIF
ffmpeg -t 3 -ss 00:00:02 -i small.webm small-clip.gif
从视频中第二秒开始,截取时长为3秒的片段转化为 gif
转化高质量 GIF
默认转化是中等质量模式,若要转化出高质量的 gif,可以修改比特率
视频属性调整
ffmpeg -i small.mp4 -b 2048k small.gif
缩放视频尺寸
ffmpeg -i big.mov -vf scale=360:-1 small.mov
注意 sacle 值必须是偶数,这里的 -1 表示保持长宽比,根据宽度值自适应高度。
如果要求压缩出来的视频尺寸长宽都保持为偶数,可以使用 -2
加倍速播放视频
ffmpeg -i input.mov -filter:v "setpts=0.5*PTS" output.mov
定义帧率 16fps
ffmpeg -i input.mov -r 16 -filter:v "setpts=0.125*PTS" -an output.mov
慢倍速播放视频
ffmpeg -i input.mov -filter:v "setpts=2.0*PTS" output.mov
静音视频(移除视频中的音频)
ffmpeg -i input.mov -an mute-output.mov
-an 就是禁止音频输出
将 GIF 转化为 MP4
ffmpeg -f gif -i animation.gif animation.mp4
也可以将 gif 转为其他视频格式
ffmpeg -f gif -i animation.gif animation.mpeg
ffmpeg -f gif -i animation.gif animation.webm
将视频中的音频换成另一个音频
ffmpeg -i odd.mp4 -i bgm.mp3 -t 7 -y new.mp4
将odd.mp4中的音频换成bgm.mp3,视频长度为7秒,保存为一个新文件new.mp4
获取 GIF 的第一帧图片
使用 ImageMagick 可以方便第提取 gif 图片的第 N 帧图像。
安装 ImageMagick
brew install imagemagick
提取第一帧
convert 'animation.gif[0]' animation-first-frame.gif
通过 [0] 就可以提取出 gif 的第一帧图像。
二.java操作ffmpeg处理视频
由于使用ffmpeg需要在cmd或者终端中执行shell命令,java的JDK里面提供了一个类ProcessBuilder,来帮助我们去执行指定的shell脚本,达到对应的目的。
1.ProcessBuilder介绍
通过Java执行系统命令,与cmd中或者终端上一样执行shell命令,最典型的用法就是使用Runtime.getRuntime().exec(command)或者new ProcessBuilder(cmdArray).start()。从JDK1.5开始,官方提供并推荐使用ProcessBuilder类进行shell命令操作。
使用ProcessBuilder很简单,只需要通过Arrays.asList()构建一个List的参数集合,然后在ProcessBuilder的构造函数传入参数,即可 start()方法执行
2.java操作ffmpeg代码示例
public class MergeVideoMp3 {
private String ffmpegEXE;
public MergeVideoMp3(String ffmpegEXE) {
super();
this.ffmpegEXE = ffmpegEXE;
}
/**
* 将视频中的音频替换为指定音频
*
* @param videoInputPath
* @param mp3InputPath
* @param seconds
* @param videoOutputPath
* @throws Exception
*/
public void convertor(String videoInputPath, String mp3InputPath,
double seconds, String videoOutputPath) throws Exception {
// ffmpeg.exe -i odd.mp4 -i bgm.mp3 -t 7 -y new.mp4
List<String> command = new ArrayList<>();
command.add(ffmpegEXE);
command.add("-i");
command.add(videoInputPath);
command.add("-i");
command.add(mp3InputPath);
command.add("-t");
command.add(String.valueOf(seconds));
command.add("-y");
command.add(videoOutputPath);
InputStream errorStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader br = null;
try {
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.start();
errorStream = process.getErrorStream();
inputStreamReader = new InputStreamReader(errorStream);
br = new BufferedReader(inputStreamReader);
while (br.readLine() != null) {
}
} finally {
if (br != null) {
br.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (errorStream != null) {
errorStream.close();
}
}
}
public static void main(String[] args) {
//参数为ffmpeg启动命令的路径。在bin目录中
MergeVideoMp3 ffmpeg = new MergeVideoMp3("/usr/local/Cellar/ffmpeg/4.1.4/bin/ffmpeg");
try {
ffmpeg.convertor("/Users/apple/workspace//video-file/180425CFA4RB6T0H/video/test.mp4", "/Users/apple/workspace//video-file/bgm/11796.mp3", 7.1, "/Users/apple/workspace//video-file/180425CFA4RB6T0H/video/test222.mp4");
} catch (Exception e) {
e.printStackTrace();
}
}
}