最近用到了ffmpeg,写一篇东西压压惊
借鉴了一些大爷的博客
重构了整个代码,解耦,添加若干注释
本类:
package videoformat;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import videoformat.utils.getProperties;
/**
* 把各種視頻文件轉換為flv 有參構造,傳入文件源路徑,文件輸出路徑,文件名 無參構造通過配置文件讀取,但需要文件名,並且存在文件路徑中。
*
* @author woshihuzios123
* @version 0.3
*/
public class ConV2 {
private Properties prop = getProperties.getPropertie();// 获取配置文件里存储的值
private String filePath;// 这里传入文件路径
private String outFilePath;// 输出文件存放路径
private String fileName;// 文件名
private String filePathandName;// 文件路径+文件名
/**
* 无参构造读取配置文件中的配置,但fileName还需要设置,不然无法转码
*/
public ConV2() {
super();
filePath = prop.getProperty("inputFilePath");
outFilePath = prop.getProperty("outputFilePath");
}
/**
*
* @param filePath
* 文件所在路径
* @param outFilePath
* 文件转码后输出的路径
* @param fileName
* 当前文件名
*/
public ConV2(String filePath, String outFilePath, String fileName) {
super();
this.filePath = filePath;
this.outFilePath = outFilePath;
this.fileName = fileName;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFilePath() {
return filePath;
}
public String getOutFilePath() {
return outFilePath;
}
public String getFilePathandName() {
return filePathandName;
}
/**
* 如果encoderForFlv输出为false,则表示文件名可能输错,转码参数错误,文件类型不支持等
*
* @return
*/
public boolean encoderForFLV() {
// 调用这个唯一的方法后才会拼接字符串,防止出现问题
filePathandName = filePath + fileName;
// 判断文件是否是文件
if (!checkfile(filePathandName)) {
return false;
}
if (proccess()) {
return true;
}
return false;
}
private boolean checkfile(String path) {
// 没有权限读取或者不是一个正常的文件会返回false
File file = new File(path);
if (!file.isFile()) {
return false;
}
return true;
}
private boolean proccess() {
int type = checkContentType();
boolean status = false;
if (type == 0) {
status = processFLV();
}
return status;
}
private int checkContentType() {
// 截取后缀
String type = filePathandName.substring(
filePathandName.lastIndexOf(".") + 1, filePathandName.length())
.toLowerCase();
// 后台判断能否转换,前台需要确定上传文件类型。
if (type.equals(prop.getProperty("avi"))
|| type.equals(prop.getProperty("mpg"))
|| type.equals(prop.getProperty("wmv"))
|| type.equals(prop.getProperty("3gp"))
|| type.equals(prop.getProperty("mov"))
|| type.equals(prop.getProperty("mp4"))
|| type.equals(prop.getProperty("asf"))
|| type.equals(prop.getProperty("asx"))
|| type.equals(prop.getProperty("flv"))
|| type.equals(prop.getProperty("vob"))) {
return 0;
}
System.out.println(999);
return 9;
}
private boolean processFLV() {
if (!checkfile(filePathandName)) {
return false;
}
fileName = fileNameHexToFLV(fileName);// 在这里包装 fileName,增加UUID,使用.分割
List<String> commend = new ArrayList<String>();
commend.add(prop.getProperty("encoderPath2"));
commend.add(prop.getProperty("y"));// 覆盖输出文件,即如果已存在就覆盖而不提示
commend.add(prop.getProperty("i"));// 指定输入目录
commend.add(filePathandName);// 从这个目录读取文件
commend.add(prop.getProperty("ab"));// 音频数据流 ,64kb
commend.add(prop.getProperty("ar"));// 音频采样率 24000hz
commend.add(prop.getProperty("b"));// 动态码率,可以改成例如"-b 1500" 来指定码率
commend.add(prop.getProperty("r"));// 帧数 24
commend.add(prop.getProperty("s"));// 输出分辨率 480*272
commend.add(prop.getProperty("threads"));// 多线程, 可选项,指定2~4
commend.add(outFilePath + fileName);// 输出路径+修改后的文件名
// 使用图片生成的返回值来判断是否继续
processJPG();
String s = commandTo(commend);
boolean b = getRuntime(s);// 封装,在命令行下运行
return b;
}
private String fileNameHexToFLV(String filename) {
// 截取後綴,然後添加flv
filename = "flv";
// 文件頭添加uuid
String u = UUID.randomUUID().toString().replace("-", "")
+ prop.getProperty("fenge") + filename;
// 返回u
return u;
}
private boolean processJPG() {
List<String> list = new ArrayList<String>();
list.add(prop.getProperty("encoderPath2"));// 转码器路径
list.add(prop.getProperty("i"));// 指定输入目录
list.add(filePathandName);// 输入目录的路径和文件
list.add(prop.getProperty("y"));// 覆盖输出文件,即如果已存在就覆盖而不提示
list.add(prop.getProperty("f"));// 强制采用格式
list.add(prop.getProperty("image2"));// image2
list.add(prop.getProperty("s"));// 输出分辨率 480*272
list.add(prop.getProperty("t"));// 设置记录时间
list.add(outFilePath + fileName + prop.getProperty("jpg"));// 添加文件路径加文件名再追加.jpg
String s = commandTo(list);
boolean b = getRuntime(s);
return b;
}
private String commandTo(List<String> list) {
StringBuilder sb = new StringBuilder();
ArrayList<String> arrayList = (ArrayList<String>) list;
Iterator<String> its = arrayList.iterator();
while (its.hasNext()) {
sb.append(its.next());
sb.append(" ");
}
System.out.println(sb.toString().replace(",", ""));
return sb.toString().replace(",", "");
}
// 执行程序
private boolean getRuntime(String arguments) {
try {
Process p = Runtime.getRuntime().exec(arguments);
// 输出流,防止出现流堵塞导致死锁
outStream(p.getErrorStream());
outStream(p.getInputStream());
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
// 可能出现线程异常,打印到控制台,ffmpeg日志,可以使用log4j打印成日志
private void outStream(InputStream p) {
// 用一个读输出流类去读
BufferedReader br = new BufferedReader(new InputStreamReader(p));
String line = null;
// 逐行读取输出到控制台
try {
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
配置文件:
inputFilePath=c\:\\\\ffmpeg\\\\input\\\\
outputFilePath=c\:\\\\ffmpeg\\\\output\\\\
encoderPath2=c\:\\ffmpeg\\ffmpeg.exe
mpg=mpg
wmv=wmv
3gp=3gp
avi=avi
asf=asf
asx=asx
mp4=mp4
flv=flv
mov=mov
y=-y
qscale=-qscale 4
r=-r 24
s=-s 1600x900
b=-b 1500
ar=-ar 22050
i=-i
ab=-ab 56
image2=image2
ss=-ss 8
t=-t 0.001
jpg=.jpg
f=-f
fenge=.
threads=-threads 2
工具类:
package videoformat.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
//获取配置文件
public class getProperties {
static InputStream is = Object.class
.getResourceAsStream("/decoder.properties");
// 相对路径
public static Properties getPropertie() {
Properties prop = new Properties();
try {
prop.load(is);
return prop;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
单元测试:
package videoformat.test;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import org.junit.Test;
import videoformat.ConV2;
public class junitTest {
<span style="white-space:pre"> </span>// 能使用多线程创建。
<span style="white-space:pre"> </span>@Test
<span style="white-space:pre"> </span>public void fun1() {
<span style="white-space:pre"> </span>String s = "C:\\ffmpeg\\input\\";
<span style="white-space:pre"> </span>String s2 = "C:\\ffmpeg\\output\\";
<span style="white-space:pre"> </span>String s3 = "a.avi";
<span style="white-space:pre"> </span>ConV2 conV2 = new ConV2(s, s2, s3);
<span style="white-space:pre"> </span>boolean b = conV2.encoderForFLV();
<span style="white-space:pre"> </span>System.out.println(b);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@Test
<span style="white-space:pre"> </span>public void fun2() {
<span style="white-space:pre"> </span>// 生成所有ffmpeg的参数
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>Process p = Runtime.getRuntime().exec(
<span style="white-space:pre"> </span>"c:\\ffmpeg\\ffmpeg.exe -h full");
<span style="white-space:pre"> </span>// outStream(p.getErrorStream());
<span style="white-space:pre"> </span>outStream(p.getInputStream());
<span style="white-space:pre"> </span>} catch (IOException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>// 把流中内容写入到文件
<span style="white-space:pre"> </span>private void outStream(InputStream p) {
<span style="white-space:pre"> </span>// 用一个读输出流类去读
<span style="white-space:pre"> </span>BufferedReader br = new BufferedReader(new InputStreamReader(p));
<span style="white-space:pre"> </span>String line = null;
<span style="white-space:pre"> </span>// 逐行读取输出到控制台
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>String file = "f:/1.txt";
<span style="white-space:pre"> </span>OutputStreamWriter pw = new OutputStreamWriter(
<span style="white-space:pre"> </span>new FileOutputStream(file));
<span style="white-space:pre"> </span>while ((line = br.readLine()) != null) {
<span style="white-space:pre"> </span>System.out.println(line);
<span style="white-space:pre"> </span>// 写入到文件
<span style="white-space:pre"> </span>pw.write(line);
<span style="white-space:pre"> </span>pw.write("\r\n");
<span style="white-space:pre"> </span>pw.flush();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>pw.close();
<span style="white-space:pre"> </span>br.close();
<span style="white-space:pre"> </span>} catch (IOException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
}