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/

主要实现:

1.获取视频元数据信息

2.视频相互转换

3.视频加文字及图片水印

4.视频截图

思路:

配置文件中定义各转换工具的路径:(相关工具去官网下载)

2.获取视频音频的各项属性帮助类

importjava.io.BufferedReader;

importjava.io.InputStreamReader;

importjava.util.List;

importorg.apache.commons.lang.StringUtils;

importorg.apache.log4j.Logger;

importorg.apache.oro.text.regex.MalformedPatternException;

importorg.apache.oro.text.regex.MatchResult;

importorg.apache.oro.text.regex.Pattern;

importorg.apache.oro.text.regex.PatternCompiler;

importorg.apache.oro.text.regex.PatternMatcher;

importorg.apache.oro.text.regex.Perl5Compiler;

importorg.apache.oro.text.regex.Perl5Matcher;

importcom.brainsoon.bsrcm.common.utils.BaseCommonUtil;

importcom.brainsoon.bsrcm.system.support.CacConver;

/**

* 获取视频音频的各项属性帮助类

* 如果需要修改或者添加属性,只要扩展下面的二维数组和修改下面getVideoInfo()方法

* @author tanghui

*

*/

publicclassVideoInfoHelps {

protectedstaticfinalLogger logger = Logger.getLogger(VideoInfoHelps.class);

publicstaticfinalString ffmpegPath;// ffmpeg.exe的目录

static{

ffmpegPath = BaseCommonUtil.getProRealPath("ffmpegPath");

}

/**

* 根据属性获取视频信息

* @param videoPath

* @return

*/

publicstaticVideoInfo getVideoInfo(String videoPath) {

VideoInfo videoInfo  = newVideoInfo();

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 =newPerl5Compiler();

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 = newPerl5Matcher();

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 = newPerl5Matcher();

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 = newPerl5Matcher();

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 +"】文件格式不支持!");

}

}

returnvideoInfo ;

}

/**

*  ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)

* @param inputPath

* @return

*/

privatestaticString processVideo(String filePath) {

List commend=newjava.util.ArrayList();

commend.add(ffmpegPath);//可以设置环境变量从而省去这行

commend.add("-i");

commend.add(filePath);

try{

ProcessBuilder builder = newProcessBuilder();

builder.command(commend);

builder.redirectErrorStream(true);

Process p= builder.start();

BufferedReader buf = null;// 保存ffmpeg的输出结果流

String line = null;

buf = newBufferedReader(newInputStreamReader(p.getInputStream()));

StringBuffer sb= newStringBuffer();

while((line = buf.readLine()) !=null) {

sb.append(line);

continue;

}

p.waitFor();//这里线程阻塞,将等待外部转换进程运行成功运行结束后,才往下执行

returnsb.toString();

} catch(Exception e) {

logger.error("ffmpeg解析视频文件【"+ filePath +"】失败!");

returnnull;

}

}

}

3.其他的工具类

/**

* 等待进程处理

* @param p

* @return

*/

@SuppressWarnings("unused")

publicstaticintdoWaitFor(Process p) {

InputStream in = null;

InputStream err = null;

intexitValue = -1;// returned to caller when p is finished

try{

in = p.getInputStream();

err = p.getErrorStream();

booleanfinished =false;// Set to true when p is finished

while(!finished) {

try{

while(in.available() >0) {

Character c = newCharacter((char) in.read());

}

while(err.available() >0) {

Character c = newCharacter((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("等待进程处理错误");

}

}

}

returnexitValue;

}

/**

* 删除文件

* @param filepath

*/

publicstaticvoiddeleteFile(String filepath) {

File file = newFile(filepath);

if(file.exists()) {

if(file.delete()) {

logger.info("文件【"+ filepath +"】已删除");

}

}

}

/**

* 根据时间返回总秒数 形如:(00:12:12)

* @param timeStr

* @return

*/

publicstaticString getSplitStr(String timeStr){

String secStr="0";//返回秒

if(timeStr !=null&& !timeStr.equals("") ){

String[] str = timeStr.split(":");

intsubInt0 = Integer.parseInt(str[0]);

intsubInt1 = 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];

}

intsubInt2 = Integer.parseInt(str2s);

Long countNum = subInt0 * 3600L + subInt1 * 60+ subInt2;

secStr = countNum + "";

}

returnsecStr;

}

/**

* 计算两个字符串时间相减 如:("00:22:22")

*

* @param time1

* @param time2

* @return

*/

publicstaticString 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){

inthour = (int) (timeLong/3600);

intminute = (int) ((timeLong-hour*3600)/60);

intsecond =(int) ((timeLong-hour*3600-minute*60)%60);

sbuffer = newStringBuffer();

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));

returnsbuffer.toString();

}else{

logger.error("时间不能为负数!可能原因是传入的时间位置不对!");

return"";

}

}

原文:http://www.cnblogs.com/zhwl/p/3645589.html

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐