java 做视频转换主要用到开源的ffmpeg或者mencoder,还要有MP4Box。
注:由于平时都没有时间写博客,所以思路我就不写了,有问题问我,不一定马上回复。
详细介绍:
ffmpeg:http://www.ffmpeg.org/
mencoder:http://en.wikipedia.org/wiki/MEncoder
MP4Box:http://gpac.wp.mines-telecom.fr/mp4box/mp4box-documentation/
主要实现:
思路:
配置文件中定义各转换工具的路径:(相关工具去官网下载)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.MatchResult;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternCompiler;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import com.brainsoon.bsrcm.common.utils.BaseCommonUtil;
import com.brainsoon.bsrcm.system.support.CacConver;
/**
* 获取视频音频的各项属性帮助类
* 如果需要修改或者添加属性,只要扩展下面的二维数组和修改下面getVideoInfo()方法
* @author tanghui
*
*/
public class VideoInfoHelps {
protected static final Logger logger = Logger.getLogger(VideoInfoHelps.class);
public static final String ffmpegPath; // ffmpeg.exe的目录
static{
ffmpegPath = BaseCommonUtil.getProRealPath("ffmpegPath");
}
/**
* 根据属性获取视频信息
* @param videoPath
* @return
*/
public static VideoInfo getVideoInfo(String videoPath) {
VideoInfo videoInfo = new VideoInfo();
if(CacConver.exitFile(videoPath)){
String videoType = videoPath.substring(videoPath.lastIndexOf(".")+1, videoPath.length());
if(CacConver.isNeedVideoFormat(videoType)){
String result = processVideo(videoPath);
if(StringUtils.isNotEmpty(result)){
PatternCompiler compiler =new Perl5Compiler();
try {
String regexDuration ="Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
String regexVideo ="Video: (.*?), (.*?), (.*?)[,\\s]";
String regexAudio ="Audio: (\\w*), (\\d*) Hz";
Pattern patternDuration = compiler.compile(regexDuration,Perl5Compiler.CASE_INSENSITIVE_MASK);
PatternMatcher matcherDuration = new Perl5Matcher();
if(matcherDuration.contains(result, patternDuration)){
MatchResult re = matcherDuration.getMatch();
videoInfo.setPlayingAllTime( re.group(1));
videoInfo.setPlayingStartTime( re.group(2));
videoInfo.setBitrateSize( re.group(3));
}
Pattern patternVideo = compiler.compile(regexVideo,Perl5Compiler.CASE_INSENSITIVE_MASK);
PatternMatcher matcherVideo = new Perl5Matcher();
if(matcherVideo.contains(result, patternVideo)){
MatchResult re = matcherVideo.getMatch();
videoInfo.setCodeFormat( re.group(1));
videoInfo.setVideoFormat( re.group(2));
videoInfo.setResolution( re.group(3));
}
Pattern patternAudio = compiler.compile(regexAudio,Perl5Compiler.CASE_INSENSITIVE_MASK);
PatternMatcher matcherAudio = new Perl5Matcher();
if(matcherAudio.contains(result, patternAudio)){
MatchResult re = matcherAudio.getMatch();
videoInfo.setAudioCoding(re.group(1));
videoInfo.setAudioFrequency( re.group(2));
}
} catch (MalformedPatternException e) {
logger.error("获取【" + videoPath +"】视频信息失败!");
}
logger.info("获取【" + videoPath +"】视频信息成功!");
}else{
logger.info("执行成功!但未获取到【" + videoPath +"】视频信息!");
}
}else{
logger.debug("【" + videoPath + "】文件格式不支持!");
}
}
return videoInfo ;
}
/**
* ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
* @param inputPath
* @return
*/
private static String processVideo(String filePath) {
List commend=new java.util.ArrayList();
commend.add(ffmpegPath);//可以设置环境变量从而省去这行
commend.add("-i");
commend.add(filePath);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
builder.redirectErrorStream(true);
Process p= builder.start();
BufferedReader buf = null; // 保存ffmpeg的输出结果流
String line = null;
buf = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuffer sb= new StringBuffer();
while ((line = buf.readLine()) != null) {
sb.append(line);
continue;
}
p.waitFor();//这里线程阻塞,将等待外部转换进程运行成功运行结束后,才往下执行
return sb.toString();
} catch (Exception e) {
logger.error("ffmpeg解析视频文件【" + filePath +"】失败!");
return null;
}
}
}
3.其他的工具类
/**
* 等待进程处理
* @param p
* @return
*/
@SuppressWarnings("unused")
public static int doWaitFor(Process p) {
InputStream in = null;
InputStream err = null;
int exitValue = -1; // returned to caller when p is finished
try {
in = p.getInputStream();
err = p.getErrorStream();
boolean finished = false; // Set to true when p is finished
while (!finished) {
try {
while (in.available() > 0) {
Character c = new Character((char) in.read());
}
while (err.available() > 0) {
Character c = new Character((char) err.read());
}
exitValue = p.exitValue();
finished = true;
} catch (IllegalThreadStateException e) {
Thread.currentThread();
Thread.sleep(500);
}
}
} catch (Exception e) {
logger.error("doWaitFor();: unexpected exception - "
+ e.getMessage());
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
logger.error("等待进程处理错误");
}
if (err != null) {
try {
err.close();
} catch (IOException e) {
logger.error("等待进程处理错误");
}
}
}
return exitValue;
}
/**
* 删除文件
* @param filepath
*/
public static void deleteFile(String filepath) {
File file = new File(filepath);
if (file.exists()) {
if (file.delete()) {
logger.info("文件【" + filepath + "】已删除");
}
}
}
/**
* 根据时间返回总秒数 形如:(00:12:12)
* @param timeStr
* @return
*/
public static String getSplitStr(String timeStr){
String secStr="0";//返回秒
if(timeStr != null && !timeStr.equals("") ){
String[] str = timeStr.split(":");
int subInt0 = Integer.parseInt(str[0]);
int subInt1 = Integer.parseInt(str[1]);
String str2s = "";
if(str[2].length() >2&&str[2].indexOf(".")>0){
str2s = str[2].substring(0,str[2].indexOf("."));
}else{
str2s = str[2];
}
int subInt2 = Integer.parseInt(str2s);
Long countNum = subInt0 * 3600L + subInt1 * 60 + subInt2;
secStr = countNum + "";
}
return secStr;
}
/**
* 计算两个字符串时间相减 如:("00:22:22")
*
* @param time1
* @param time2
* @return
*/
public static String calTime(String time1, String time2){
Long time1Long = Long.parseLong(time1);
Long time2Long = Long.parseLong(time2);
Long timeLong = time2Long-time1Long;
StringBuffer sbuffer = null;
if(timeLong > 0){
int hour = (int) (timeLong/3600);
int minute = (int) ((timeLong-hour*3600)/60);
int second =(int) ((timeLong-hour*3600-minute*60)%60);
sbuffer = new StringBuffer();
if(hour<10){
sbuffer.append("0");
}
sbuffer.append(Integer.toString(hour));
sbuffer.append(":");
if(minute<10){
sbuffer.append("0");
}
sbuffer.append(Integer.toString(minute));
sbuffer.append(":");
if(second<10){
sbuffer.append("0");
}
sbuffer.append(Integer.toString(second));
return sbuffer.toString();
}else{
logger.error("时间不能为负数!可能原因是传入的时间位置不对!");
return "";
}
}