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.视频截图

思路:

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

  1. <!-- ################配置系统用到的转换工具相关参数   开始....-->  
  2.       
  3.         <!-- ##ffmpeg.so文件路径 -->  
  4.         <param name="ffmpegPath" value="D:converffmpeg-win.exe" />  
  5.           
  6.         <!-- ##memcoder.so文件路径 -->  
  7.         <param name="mencoderPath" value="D:convermencoder.exe" />  
  8.           
  9.         <!-- ##给视频加水印的shell脚本路径 -->  
  10.         <param name="shellPath" value="D:convercoverVideo.bat" />  
  11.           
  12.         <!-- ##定义MP4Box工具路径 -->  
  13.         <param name="mp4BoxPath" value="D:converMP4Box" />  
  14.           
  15.         <!-- ##定义图片转换工具路径 -->  
  16.         <param name="imgConverPath" value="C:/Program Files/ImageMagick-6.3.9-Q16/convert.exe" />  
  17.           
  18.     <!-- ################配置系统用到的转换工具相关参数   结束-->  

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

  1. import java.io.BufferedReader;  
  2. import java.io.InputStreamReader;  
  3. import java.util.List;  
  4.   
  5. import org.apache.commons.lang.StringUtils;  
  6. import org.apache.log4j.Logger;  
  7. import org.apache.oro.text.regex.MalformedPatternException;  
  8. import org.apache.oro.text.regex.MatchResult;  
  9. import org.apache.oro.text.regex.Pattern;  
  10. import org.apache.oro.text.regex.PatternCompiler;  
  11. import org.apache.oro.text.regex.PatternMatcher;  
  12. import org.apache.oro.text.regex.Perl5Compiler;  
  13. import org.apache.oro.text.regex.Perl5Matcher;  
  14. import com.brainsoon.bsrcm.common.utils.BaseCommonUtil;  
  15. import com.brainsoon.bsrcm.system.support.CacConver;  
  16.   
  17. /** 
  18.  * 获取视频音频的各项属性帮助类 
  19.  * 如果需要修改或者添加属性,只要扩展下面的二维数组和修改下面getVideoInfo()方法 
  20.  * @author tanghui 
  21.  * 
  22.  */  
  23. public class VideoInfoHelps {  
  24.       
  25.     protected static final Logger logger = Logger.getLogger(VideoInfoHelps.class);  
  26.       
  27.      public static final String ffmpegPath; // ffmpeg.exe的目录    
  28.           
  29.      static{  
  30.             ffmpegPath = BaseCommonUtil.getProRealPath("ffmpegPath");  
  31.         }  
  32.   
  33.        
  34.   /** 
  35.    * 根据属性获取视频信息 
  36.    * @param videoPath 
  37.    * @return 
  38.    */  
  39.   public static VideoInfo getVideoInfo(String videoPath) {  
  40.       VideoInfo videoInfo  = new VideoInfo();  
  41.       if(CacConver.exitFile(videoPath)){  
  42.          String videoType = videoPath.substring(videoPath.lastIndexOf(".")+1, videoPath.length());  
  43.          if(CacConver.isNeedVideoFormat(videoType)){  
  44.             String result =   processVideo(videoPath);   
  45.             if(StringUtils.isNotEmpty(result)){  
  46.                   PatternCompiler compiler =new Perl5Compiler();    
  47.                     try {    
  48.                            String regexDuration ="Duration: (.*?), start: (.*?), bitrate: (\d*) kb\/s";    
  49.                            String regexVideo ="Video: (.*?), (.*?), (.*?)[,\s]";    
  50.                            String regexAudio ="Audio: (\w*), (\d*) Hz";    
  51.                            
  52.                             Pattern patternDuration = compiler.compile(regexDuration,Perl5Compiler.CASE_INSENSITIVE_MASK);    
  53.                             PatternMatcher matcherDuration = new Perl5Matcher();    
  54.                             if(matcherDuration.contains(result, patternDuration)){    
  55.                                 MatchResult re = matcherDuration.getMatch();    
  56.                                   
  57.                                 videoInfo.setPlayingAllTime( re.group(1));  
  58.                                   
  59.                                 videoInfo.setPlayingStartTime( re.group(2));  
  60.                                   
  61.                                 videoInfo.setBitrateSize( re.group(3));  
  62.                             }    
  63.                                
  64.                             Pattern patternVideo = compiler.compile(regexVideo,Perl5Compiler.CASE_INSENSITIVE_MASK);    
  65.                             PatternMatcher matcherVideo = new Perl5Matcher();    
  66.                                
  67.                             if(matcherVideo.contains(result, patternVideo)){    
  68.                                 MatchResult re = matcherVideo.getMatch();    
  69.                                  
  70.                                 videoInfo.setCodeFormat( re.group(1));  
  71.                                   
  72.                                 videoInfo.setVideoFormat( re.group(2));  
  73.                                   
  74.                                 videoInfo.setResolution( re.group(3));  
  75.                             }    
  76.                                
  77.                             Pattern patternAudio = compiler.compile(regexAudio,Perl5Compiler.CASE_INSENSITIVE_MASK);    
  78.                             PatternMatcher matcherAudio = new Perl5Matcher();    
  79.                                
  80.                             if(matcherAudio.contains(result, patternAudio)){    
  81.                                 MatchResult re = matcherAudio.getMatch();    
  82.                                   
  83.                                 videoInfo.setAudioCoding(re.group(1));  
  84.                                   
  85.                                 videoInfo.setAudioFrequency( re.group(2));  
  86.                               }  
  87.                         } catch (MalformedPatternException e) {    
  88.                             logger.error("获取【" + videoPath +"】视频信息失败!");  
  89.                         }   
  90.                       
  91.                         logger.info("获取【" + videoPath +"】视频信息成功!");  
  92.                  }else{  
  93.                      logger.info("执行成功!但未获取到【" + videoPath +"】视频信息!");  
  94.                  }  
  95.             }else{  
  96.                  logger.debug("【" + videoPath + "】文件格式不支持!");  
  97.             }  
  98.         }  
  99.           
  100.         return videoInfo ;  
  101.    }  
  102.                
  103.             
  104.            /** 
  105.             *  ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)   
  106.             * @param inputPath 
  107.             * @return 
  108.             */  
  109.        private static String processVideo(String filePath) {     
  110.                 List<String> commend=new java.util.ArrayList<String>();    
  111.                 commend.add(ffmpegPath);//可以设置环境变量从而省去这行    
  112.                 commend.add("-i");    
  113.                 commend.add(filePath);    
  114.                 try {    
  115.                     ProcessBuilder builder = new ProcessBuilder();    
  116.                     builder.command(commend);    
  117.                     builder.redirectErrorStream(true);    
  118.                     Process p= builder.start();    
  119.                     BufferedReader buf = null// 保存ffmpeg的输出结果流    
  120.                     String line = null;    
  121.                     buf = new BufferedReader(new InputStreamReader(p.getInputStream()));    
  122.                     StringBuffer sb= new StringBuffer();    
  123.                     while ((line = buf.readLine()) != null) {    
  124.                          sb.append(line);    
  125.                          continue;    
  126.                     }    
  127.                     p.waitFor();//这里线程阻塞,将等待外部转换进程运行成功运行结束后,才往下执行    
  128.                     return sb.toString();    
  129.                 } catch (Exception e) {   
  130.                     logger.error("ffmpeg解析视频文件【" + filePath +"】失败!");  
  131.                     return null;    
  132.                 }    
  133.             }   
  134.               
  135. }  

3.其他的工具类

    1. /** 
    2.     * 等待进程处理 
    3.     * @param p 
    4.     * @return 
    5.     */  
    6. @SuppressWarnings("unused")  
    7. public static int doWaitFor(Process p) {    
    8.        InputStream in = null;    
    9.        InputStream err = null;    
    10.        int exitValue = -1// returned to caller when p is finished    
    11.        try {    
    12.            in = p.getInputStream();    
    13.            err = p.getErrorStream();    
    14.            boolean finished = false// Set to true when p is finished    
    15.            while (!finished) {    
    16.                try {    
    17.                    while (in.available() > 0) {    
    18.                        Character c = new Character((char) in.read());    
    19.                    }    
    20.                    while (err.available() > 0) {    
    21.                        Character c = new Character((char) err.read());    
    22.                    }    
    23.                    exitValue = p.exitValue();    
    24.                    finished = true;    
    25.                } catch (IllegalThreadStateException e) {    
    26.                    Thread.currentThread();  
    27.                 Thread.sleep(500);    
    28.                }    
    29.            }    
    30.   
    31.        } catch (Exception e) {    
    32.         logger.error("doWaitFor();: unexpected exception - "   
    33.                    + e.getMessage());  
    34.        } finally {    
    35.            try {    
    36.                if (in != null) {    
    37.                    in.close();    
    38.                }    
    39.            } catch (IOException e) {    
    40.                logger.error("等待进程处理错误");  
    41.            }    
    42.            if (err != null) {    
    43.                try {    
    44.                    err.close();    
    45.                } catch (IOException e) {    
    46.                 logger.error("等待进程处理错误");    
    47.                }    
    48.            }    
    49.        }    
    50.        return exitValue;    
    51.    }    
    52.   
    53.      
    54.   /** 
    55.    * 删除文件 
    56.    * @param filepath 
    57.    */  
    58.    public static void deleteFile(String filepath) {    
    59.        File file = new File(filepath);    
    60.        if (file.exists()) {    
    61.            if (file.delete()) {    
    62.             logger.info("文件【" + filepath + "】已删除");  
    63.            }    
    64.        }   
    65.    }    
    66.   
    67.      
    68.   
    69. /** 
    70.  * 根据时间返回总秒数 形如:(00:12:12) 
    71.  * @param timeStr 
    72.  * @return 
    73.  */  
    74. public static String getSplitStr(String timeStr){  
    75.     String secStr="0";//返回秒  
    76.     if(timeStr != null && !timeStr.equals("") ){  
    77.         String[] str = timeStr.split(":");  
    78.             int subInt0 = Integer.parseInt(str[0]);  
    79.             int subInt1 = Integer.parseInt(str[1]);  
    80.             String str2s = "";  
    81.             if(str[2].length() >2&&str[2].indexOf(".")>0){  
    82.                 str2s = str[2].substring(0,str[2].indexOf("."));  
    83.             }else{  
    84.                 str2s =  str[2];  
    85.             }  
    86.             int subInt2 = Integer.parseInt(str2s);  
    87.             Long countNum = subInt0 * 3600L + subInt1 * 60 + subInt2;  
    88.             secStr = countNum + "";  
    89.         }  
    90.     return secStr;  
    91. }  
    92.   
    93.   
    94. /** 
    95.  * 计算两个字符串时间相减 如:("00:22:22") 
    96.  *  
    97.  * @param time1 
    98.  * @param time2 
    99.  * @return 
    100.  */  
    101.    public static String calTime(String time1, String time2){  
    102.     Long time1Long = Long.parseLong(time1);  
    103.     Long time2Long = Long.parseLong(time2);  
    104.     Long timeLong = time2Long-time1Long;  
    105.     StringBuffer sbuffer = null;  
    106.     if(timeLong > 0){  
    107.         int hour = (int) (timeLong/3600);  
    108.         int minute = (int) ((timeLong-hour*3600)/60);  
    109.         int second =(int) ((timeLong-hour*3600-minute*60)%60);  
    110.         sbuffer = new StringBuffer();  
    111.         if(hour<10){  
    112.             sbuffer.append("0");  
    113.         }  
    114.         sbuffer.append(Integer.toString(hour));  
    115.         sbuffer.append(":");  
    116.         if(minute<10){  
    117.             sbuffer.append("0");  
    118.         }  
    119.         sbuffer.append(Integer.toString(minute));  
    120.         sbuffer.append(":");  
    121.         if(second<10){  
    122.             sbuffer.append("0");  
    123.         }  
    124.         sbuffer.append(Integer.toString(second));  
    125.         return sbuffer.toString();  
    126.     }else{  
    127.         logger.error("时间不能为负数!可能原因是传入的时间位置不对!");  
    128.         return "";  
    129.     }  
    130. }  
原文地址:https://www.cnblogs.com/zhwl/p/3645589.html