项目里遇到视频发布的一个功能,没接触过,百度了一些方法总结了一下写了现在的方法。
做了一些视频格式的效验,只保留了一些主流视频格式,压缩率一般,80%左右。
最开始用的Runtime运行,不过弹的那个小黑窗有点反感,改用ProcessBuilder了,顺便加了获取ffmpeg输出的方法(缩略图方法没有加上,几秒钟的事情,意义不大)。
项目里用的swfupload上传组件,结合这个返回值的话后续能做一个转换进度(理论上,过程应该比较麻烦),如果不需要的话自行取舍吧。
需要注意的是如果不在Tomcat(我的项目是这个)输出返回值的话转码和JAVA方法不是同步完成的,转码毕竟是需要较长时间的。
转码的进程和Tomcat没什么冲突,各忙各的,JAVA方法完成之后就能忙别的了,转码会自己执行直到转码结束。多进程还没试过,应该问题不大,只要服务器顶的住的话。
如果转码和缩略图都需要执行的话建议先取缩略图,再执行转码。
ffmpeg参数解释:http://hi.baidu.com/ruixueue0117/blog/item/d44747fbdca8f17e034f56c3.html
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
public class ConvertVideo {
private static HashMap<String, String> fileType;
static {
fileType = new HashMap<String, String>();
fileType.put("avi", "true");
fileType.put("mpg", "true");
fileType.put("wmv", "true");
fileType.put("3gp", "true");
fileType.put("mov", "true");
fileType.put("mp4", "true");
fileType.put("asf", "true");
fileType.put("asx", "true");
//fileType.put("flv", "true");
}
public static boolean processFlv(String INPUT_PATH,String OUTPUT_PATH) {
System.out.println("OUTPUT_PATH="+OUTPUT_PATH);
//效验文件是否存在,自行取舍
if(new File(OUTPUT_PATH).exists()) return true;
List<String> commend = new java.util.ArrayList<String>();
//ffmpeg地址,不需要带.exe后缀
commend.add("d:\\video\\ffmpeg\\ffmpeg");
commend.add("-i");
commend.add(INPUT_PATH);
commend.add("-y");
commend.add("-s");
commend.add("480*360");
commend.add("-b");
commend.add("1000");
commend.add("-qscale");
commend.add("4");
commend.add(OUTPUT_PATH);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
builder.redirectErrorStream(true);
//builder.start();
Process process = builder.start();
InputStream in = process.getInputStream();
byte[] re = new byte[1024];
while (in.read(re)!= -1) {
System.out.println(new String(re));
}
in.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static boolean processImg(String INPUT_PATH,String IMG_PATH) {
System.out.println("IMG_PATH="+IMG_PATH);
if(new File(IMG_PATH).exists()) return true;
List<String> commend = new java.util.ArrayList<String>();
commend.add("d:\\video\\ffmpeg\\ffmpeg");
commend.add("-i");
commend.add(INPUT_PATH);
commend.add("-y");
commend.add("-f");
commend.add("image2");
commend.add("-ss");
commend.add("10");
commend.add("-t");
commend.add("0.001");
commend.add("-s");
commend.add("320x240");
commend.add(IMG_PATH);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
builder.start();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean checkContentType(String INPUT_PATH) {
String type = INPUT_PATH.substring(INPUT_PATH.lastIndexOf(".") + 1, INPUT_PATH.length()).toLowerCase();
// ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
return "true".equals(fileType.get(type));
}
public static void convertToFLV(String INPUT_PATH) {
String FILE_PATH = INPUT_PATH.substring(0,INPUT_PATH.lastIndexOf("."));
String OUTPUT_PATH = FILE_PATH + ".flv";
String IMG_PATH = FILE_PATH + ".jpg";
System.out.println("INPUT_PATH="+INPUT_PATH);
processImg(INPUT_PATH,IMG_PATH);
if (checkContentType(INPUT_PATH)){
processFlv(INPUT_PATH,OUTPUT_PATH);
}
}
public static void main(String[] args){
convertToFLV("D:\\video\\a1.avi");
}
}