java-FFmpeg(一) 实现视频的转码和截图功能

时间:2021-12-02 20:09:21

  FFmpeg是一个开源免费跨平台的视频和音频流方案,属于*软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行。

  在java开发中,FFmpeg也常被调用用来进行视频的转码,录播和直播,总的来说,FFmpeg是一款非常强大的,而且做与视频相关的业务平台开发人员必须要学会的工具,那具体怎么实习呢,第一章我们先从分别windows和linux下调用FFmpeg进行视频的转码,和对视频的截图做出说明解释。

ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等),而对于ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),我们在下面采用了mencoder工具,先将视频转换成AVI格式再用ffmpeg进行转码;

windows下:

1.首先需要FFmpeg和mencoder的工具。一共五个文件,点此下载,将他解压放在你的D盘FFmpeg文件夹下。

    java-FFmpeg(一) 实现视频的转码和截图功能

  linux下:

依次执行下面的指令
1.下载yasm-1.3.0.tar.gz这个版本:
yasm是一个完全重写的NASM汇编。目前,它支持x86和AMD64指令集,接受NASM和气体汇编语法,产出二进制, ELF32 , ELF64 , COFF , Mach - O的( 32和64 ) , RDOFF2 ,的Win32和Win64对象的格式,并生成STABS 调试信息的来源,DWARF 2 ,CodeView 8格式。之所以在FFmpeg中用这个,主要是支持编译ffmpeg-x264.
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
tar xzvf yasm-1.3.0.tar.gz
cd yasm-1.3.0
./configure
make
make install
2.下载3.1.3 release ffmpeg
wget http://ffmpeg.org/releases/ffmpeg-3.1.3.tar.gz
tar -zxvf ffmpeg-3.1.3.tar.gz
cd ffmpeg-3.1.3
./configure
make
make install
第二步的时间可能会有点长,耐心等待~!安装完成之后输入  ffmpeg -version 可以看到版本说明安装成功
下面直接上代码,都写好注释的,很清楚。
package wordtopdf;

import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List; public class ConvertVideo {
private final static String PATH = "【需要转码的视频路径】"; public static void main(String[] args) {
if (!checkfile(PATH)) { //判断路径是不是一个文件
System.out.println(PATH + " is not file");
return;
}
if (process()) { //执行转码任务
System.out.println("ok");
}
} private static boolean checkfile(String path) {
File file = new File(path);
if (!file.isFile()) {
return false;
}
return true;
} private static boolean process() {
// 判断视频的类型
int type = checkContentType();
boolean status = false;
//如果是ffmpeg可以转换的类型直接转码,否则先用mencoder转码成AVI
if (type == 0) {
System.out.println("直接将文件转为flv文件");
status = processFLV(PATH);// 直接将文件转为flv文件
} else if (type == 1) {
String avifilepath = processAVI(type);
if (avifilepath == null)
return false;// avi文件没有得到
status = processFLV(avifilepath);// 将avi转为flv
}
return status;
} private static int checkContentType() {
String type = PATH.substring(PATH.lastIndexOf(".") + 1, PATH.length())
.toLowerCase();
// ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
if (type.equals("avi")) {
return 0;
} else if (type.equals("mpg")) {
return 0;
} else if (type.equals("wmv")) {
return 0;
} else if (type.equals("3gp")) {
return 0;
} else if (type.equals("mov")) {
return 0;
} else if (type.equals("mp4")) {
return 0;
} else if (type.equals("asf")) {
return 0;
} else if (type.equals("asx")) {
return 0;
} else if (type.equals("flv")) {
return 0;
}
// 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),
// 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
else if (type.equals("wmv9")) {
return 1;
} else if (type.equals("rm")) {
return 1;
} else if (type.equals("rmvb")) {
return 1;
}
return 9;
} // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
private static String processAVI(int type) {
List<String> commend = new ArrayList<String>();
commend.add("D:\\ffmpeg\\mencoder");
commend.add(PATH);
commend.add("-oac");
commend.add("lavc");
commend.add("-lavcopts");
commend.add("acodec=mp3:abitrate=64");
commend.add("-ovc");
commend.add("xvid");
commend.add("-xvidencopts");
commend.add("bitrate=600");
commend.add("-of");
commend.add("avi");
commend.add("-o");
commend.add("【存放转码后视频的路径,记住一定是.avi后缀的文件名】");
try {
//调用线程命令启动转码
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
builder.start();
return "【存放转码后视频的路径,记住一定是.avi后缀的文件名】";
} catch (Exception e) {
e.printStackTrace();
return null;
}
} // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
private static boolean processFLV(String oldfilepath) { if (!checkfile(PATH)) {
System.out.println(oldfilepath + " is not file");
return false;
} // 文件命名
Calendar c = Calendar.getInstance();
String savename = String.valueOf(c.getTimeInMillis())+ Math.round(Math.random() * 100000);
List<String> commend = new ArrayList<String>();
commend.add("D:\\ffmpeg\\ffmpeg");
commend.add("-i");
commend.add(oldfilepath);
commend.add("-ab");
commend.add("56");
commend.add("-ar");
commend.add("22050");
commend.add("-qscale");
commend.add("8");
commend.add("-r");
commend.add("15");
commend.add("-s");
commend.add("600x500");
commend.add("【存放转码后视频的路径,记住一定是.flv后缀的文件名】"); try {
Runtime runtime = Runtime.getRuntime();
Process proce = null;
//视频截图命令,封面图。 8是代表第8秒的时候截图
String cmd = "";
String cut = " c:\\ffmpeg\\ffmpeg.exe -i "
+ oldfilepath
+ " -y -f image2 -ss 8 -t 0.001 -s 600x500 c:\\ffmpeg\\output\\"
+ "a.jpg";
String cutCmd = cmd + cut;
proce = runtime.exec(cutCmd);
//调用线程命令进行转码
ProcessBuilder builder = new ProcessBuilder(commend);
builder.command(commend);
builder.start(); return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
 注:ffmpeg的功能十分强大,但是命令也非常多,转换每种格式的命令都不相同!需要转换其他格式的,请写对命令。

命令格式:

    普通转码:
    ffmpeg -i [输入文件名] [参数选项] -f [格式] [输出文件]
    比如:MP4转avi c:\ffmpeg\ffmpeg -i c:\ffmpeg\input\c.mp4 -f avi c:\ffmpeg\output\a.avi

    参数:-an 去掉音频
    -b 1000K 压缩码率为1000K
    -s 800*500 压缩尺寸为800*500
    -aspect 宽高比,格式 16:9 或 1.778
    (当源尺寸是16:9,要压缩成非16:9的,一方面要设定 -s,另一方面要给出 -aspect)
    -ss 开始时间​
    -t 持续时长