zoukankan      html  css  js  c++  java
  • 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. }  
  • 相关阅读:
    ASP.NET 高级编程基础第十一篇—WebForm和Page类成员
    ASP.NET 高级编程基础第十三篇—验证控件
    C#委托和事件详解第二篇
    C#委托事件详解第三篇
    点击一个Button,来看Duwamish7的总体层次
    ELMAHError Logging Modules And Handlers
    [实例研究Duwamish]SystemFramework和Common命名空间
    关于Blog的一些周边资源
    .NET框架程序设计Globally Deployment Assembly全局部署程序集
    合并2个DataSet
  • 原文地址:https://www.cnblogs.com/zhwl/p/3645589.html
Copyright © 2011-2022 走看看