java 实现视频转换通用工具类:获取视频元数据信息(一)

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.获取视频音频的各项属性帮助类

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 "";
		}
	}



你可能感兴趣的:(项目经验谈,Java技术)