`

线程池多线程视频转码(完整版)

阅读更多
很艰辛很痛苦...几次几乎被玩死...代码贴出来...对自己是留念...对别人是引玉...
开始...
首先是视频转码, 多种视频格式都转换成.flv格式. ConvertVideo.java
package com.enorth.lichen.transcode;

import java.io.File;
import java.util.List;

public class ConvertVideo {

  //原始文件
  private String videoPath;
  //目标文件
  private String targetPath;
    
  public ConvertVideo(String videoPath , String targetPath){
    this.videoPath=videoPath;
    this.targetPath=targetPath;
   }
    
  public synchronized void process() {
    int type = checkContentType();
    if (type == 0) {
      this.ffmpegTransVideo();
      this.ffmpegTransImage();
     } else if (type == 1) {
      this.mencoderTransVideo();
     }
   }

  public synchronized int checkContentType() {
     String type = videoPath.substring(videoPath.lastIndexOf(".") + 1, videoPath.length())
         .toLowerCase();
    // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
    if (type.equals("avi")) {
      return 0;
     } else if (type.equals("mpg")) {
      return 0;
     } else if (type.equals("wmv")) {
      return 0;
     } else if (type.equals("3gp")) {
      return 0;
     } else if (type.equals("mov")) {
      return 0;
     } else if (type.equals("mp4")) {
      return 0;
     } else if (type.equals("asf")) {
      return 0;
     } else if (type.equals("asx")) {
      return 0;
     } else if (type.equals("flv")) {
      return 0;
     }
    // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),
    // 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
    else if (type.equals("wmv9")) {
      return 1;
     } else if (type.equals("rm")) {
      return 1;
     } else if (type.equals("rmvb")) {
      return 1;
     }
    return 9;
   }

  public synchronized static boolean checkfile(String path) {
     File file = new File(path);
    if (!file.isFile()) {
      return false;
     }
    return true;
   }
    
  /**
     * 使用mencoder转码
     * @param videoPath 源路径 -- 要转换的视频文件
     * @param targetPath 目标路径 -- 转换后的视频flv
     * @return 返回目标路径
     */

  public synchronized     String mencoderTransVideo() {
     List<String> commend = new java.util.ArrayList<String>();
     commend.add("d:\\flv\\MediaCoder\\codecs\\mencoder.exe");    
     commend.add(videoPath);
    //音频采用mp3编码
     commend.add("-oac");
     commend.add("mp3lame");
    //采用高质DivX视频编码,视频码率为112kbps
     commend.add("-ovc");
     commend.add("lavc");
     commend.add("-lavcopts");
     commend.add("vcodec=flv:vbitrate=500:mbd=2:mv0:trell:v4mv:cbp:last_pred=3:dia=-1:cmp=3:vb_strategy=1");
     commend.add("-lameopts");
     commend.add("abr:br=56");
    //声音采样频率设置,现为22K    
     commend.add("-srate");
     commend.add("22050");
    //-sws就是用来设置品质的,默认值为2
     commend.add("-sws");
     commend.add("3");
    //宽度为208,高度自动调整保持比例;
    //-vf scale=-3:176宽度自动调整保持比例,高度为176;如果想保持原来的大小可以不要这个参数    
     commend.add("-vf");
     commend.add("scale=512:-3");
    // 帧速率设置
     commend.add("-ofps");
     commend.add("18");
    /*
     * mode=3:cbr:br=24单声道
     * 音频码率为24kbps;-lameopts mode=0:cbr:br=24立体声,音频码率为24kbps;    
     * 还可设置音量,-lameopts mode=3:cbr:br=32:vol=1,设置范置为1~10,但不宜设得太高
     */

     commend.add("-lameopts");
     commend.add("vbr=3:br=128");
     commend.add("-o");
     commend.add(targetPath);
    //控制台显示执行的命令
    //System.out.println(commend);
    try {
       ProcessBuilder builder = new ProcessBuilder();
       builder.command(commend);
       builder.start();
      return targetPath;
     } catch (Exception e) {
       e.printStackTrace();
      return null;
     }
   }
    
    
    
  public synchronized String ffmpegTransVideo() {
//     if (!checkfile(videoPath)) {
//       System.out.println(videoPath + " is not file aaa");
//       return false;
//     }
     List<String> commend = new java.util.ArrayList<String>();
     commend.add("d:\\flv\\MediaCoder\\codecs\\ffmpeg.exe");    
     commend.add("-i");
     commend.add(videoPath);
     commend.add("-ab");
     commend.add("64");
//     commend.add(" -acodec ");
//     commend.add("codec");
     commend.add("-ac");
     commend.add("2");
     commend.add("-ar");
     commend.add("22050");
    //清晰度     -qscale 4 为最好可是文件大, -qscale 6就可以了
     commend.add("-qscale");
     commend.add("6");
//     commend.add("-b");
//     commend.add("768");
//     commend.add("230");
//     commend.add("-s");
//     commend.add("352x240");
//     commend.add("-r");
//     commend.add("29.97");
     commend.add("-y");
     commend.add(targetPath);
     System.out.println(commend);
    try {
       ProcessBuilder builder = new ProcessBuilder();
       builder.command(commend);
       builder.start();
      return targetPath;
     } catch (Exception e) {
       e.printStackTrace();
      return null;
     }
   }
// 生成图片 参数String newfilename, String newimg
  public synchronized boolean ffmpegTransImage() {
     List<String> commend = new java.util.ArrayList<String>();
     commend.add("d:\\flv\\MediaCoder\\codecs\\ffmpeg.exe");
     commend.add("-i");
     commend.add("d:\\test\\a.mpg");
     commend.add("-y");
     commend.add("-f");
     commend.add("image2");
     commend.add("-ss");
     commend.add("38");
     commend.add("-t");
     commend.add("0.001");
     commend.add("-s");
     commend.add("320x240");
     commend.add("d:\\test\\b.jpg");
    try {
       ProcessBuilder builder = new ProcessBuilder();
       builder.command(commend);
       builder.start();
      return true;
     } catch (Exception e) {
       e.printStackTrace();
      return false;
     }
   }
    
}
然后是把这个转码做成线程 ThreadTransCode.java
package com.enorth.lichen.transcode;

public class ThreadTransCode implements Runnable {

  //原始文件
  private String videoPath;
  //目标文件
  private String targetPath;

  public ThreadTransCode(String videoPath, String targetPath) {
    this.videoPath = videoPath;
    this.targetPath = targetPath;
   }

   @Override
  public void run() {
    synchronized (this) {
       System.out.println("转码开始..............");
       ConvertVideo cv = new ConvertVideo(videoPath, targetPath);
       cv.process();
     }
   }
}
下来就是线程池了, 自己写的先贴上 ThreadPool.java
package com.enorth.lichen.transcode;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPool {
    
  public static ExecutorService exec = Executors.newFixedThreadPool(3);
    
  public static synchronized void trans(String videoPath,String targetPath){
     ThreadTransCode trans=new ThreadTransCode(videoPath,targetPath);
     exec.execute(trans);
   }
}  
最后就是在action里调用了,action 里只需要以下

    /**
     * 自己写的线程池
     */

     ThreadPool.trans(videoPath, targetPath);
就可以了.
另一种是spring封装的线程池, 其余部分不变,只是线程池就不用自己写了
  <bean id="taskExecutor"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="3" />
    <property name="keepAliveSeconds" value="200" />
    <property name="maxPoolSize" value="5" />
    <property name="queueCapacity" value="25" />
  </bean>
这样配置之后.记得要在action里注入
    <bean id="saveVideoAction" class="com.enorth.lichen.action.video.SaveVideoAction" scope="prototype">
      <property name="taskExecutor">
        <ref bean="taskExecutor" />
      </property>
    </bean>
最后在action里写一句
    /**
     * 使用spring封装的线程池
     */

     taskExecutor.execute(new ThreadTransCode(videoPath,targetPath));
以上就是使用线程池 多线程视频转码...

值得留念...

 

---------------------------------------------------
重要说明: 如果遇到停掉tomcat才能进行转码的情况. 并不是线程死锁的原因(最初我是这样认为的,所以所有的synchronized可以去除了), 是ffmpeg错误流缓冲区的问题, 感觉算ffmpeg的bug.
解决方法:
在转码的类中 ConvertVideo.java 修改ffmpegTransVideo()方法
  public String ffmpegTransVideo() {
    // if (!checkfile(videoPath)) {
    // System.out.println(videoPath + " is not file aaa");
    // return false;
    // }
     List<String> commend = new java.util.ArrayList<String>();
     commend.add("d:\\flv\\MediaCoder\\codecs\\ffmpeg.exe");
     commend.add("-i");
     commend.add(videoPath);
     commend.add("-ab");
     commend.add("64");
    // commend.add(" -acodec ");
    // commend.add("codec");
     commend.add("-ac");
     commend.add("2");
     commend.add("-ar");
     commend.add("22050");
    // 清晰度 -qscale 4 为最好可是文件大, -qscale 6就可以了
     commend.add("-qscale");
     commend.add("6");
    // commend.add("-b");
    // commend.add("768");
    // commend.add("230");
    // commend.add("-s");
    // commend.add("352x240");
    // commend.add("-r");
    // commend.add("29.97");
     commend.add("-y");
     commend.add(targetPath);
     System.out.println(commend);
    try {
      ProcessBuilder builder = new ProcessBuilder();
       builder.command(commend);
       Process process = builder.start();
       InputStream is = process.getErrorStream();
       InputStreamReader inputStreamReader = new InputStreamReader(is);
       BufferedReader inputBufferedReader = new BufferedReader(
           inputStreamReader);
       String line = null;
       StringBuilder stringBuilder = new StringBuilder();
      while ((line = inputBufferedReader.readLine()) != null) {
         stringBuilder.append(line);
       }
       inputBufferedReader.close();
       inputBufferedReader = null;
       inputStreamReader.close();
       inputStreamReader = null;
       is.close();
       is = null;
      return targetPath;
     } catch (Exception e) {
       e.printStackTrace();
      return null;
     }
   }
分享到:
评论

相关推荐

    精易模块[源码] V5.15

    1、新增“线程_枚举”枚举指定进程ID中所有线程列表,成功返回线程数量,失败返回零。 2、删除“文件_取图标”与"文件_取图标句柄"功能重复。 3、优化“系统_创建桌面快捷方式”流程代码,感谢易友[ds9660]反馈。 4...

    hhhhh安卓开发教程大全

    hhhhh安卓开发教程大全

    avem-labs_Avem_1740990015.zip

    avem-labs_Avem_1740990015.zip

    25883-mofangmall.com 微信群管理机器人系统网站.zip

    微信群机器人管理系统源码 微信群机器人管理系统源码 支持同登陆多个微信 源码类型: C/S 开发环境: VS2010 SQL2008R2 菜单功能 1、支持同时登录多个微信 2、支持机器人聊天(笑话,成语接龙、故事会、智力等等) 3、支持签到 4、可自定义回复 5、可自定义红包语 6、支持定期发送公告(如群规,广告)等 1、WeChatRobots后台配置web版 2、数据库在WeiChartGroup.Net/app_data中,附加即可

    https://upload.csdn.net/creation/uploadResources?spm=1003.2018.3001.4314

    https://upload.csdn.net/creation/uploadResources?spm=1003.2018.3001.4314

    名字微控制器_STM32_课程_DeepBlue_1740989720.zip

    名字微控制器_STM32_课程_DeepBlue_1740989720.zip

    S7-200Smart恒压供水程序示例与485通讯实践:操作指南与案例解析,S7-200 Smart可编程控制器恒压供水程序设计与实现,附带485通讯范例,S7-200Smart 恒压供水程序样例+4

    S7-200Smart恒压供水程序示例与485通讯实践:操作指南与案例解析,S7-200 Smart可编程控制器恒压供水程序设计与实现,附带485通讯范例,S7-200Smart 恒压供水程序样例+485通讯样例 ,S7-200Smart; 恒压供水程序样例; 485通讯样例,S7-200Smart程序样例:恒压供水及485通讯应用示例

    Java读写Mifare M1卡IC卡源码

    Java使用JNA、JNI两种不同方式调用DLL、SO动态库方式读写M1卡源码,支持读写M1卡扇区数据、修改IC卡扇区密钥、改写UID卡卡号等功能,支持Windows系统,同时支持龙芯Mips、LoongArch、海思麒麟鲲鹏飞腾Arm、海光兆芯x86_Amd64等架构平台的国产统信、麒麟等Linux系统,内有jna-4.5.0.jar包,vx13822155058 qq954486673

    UDP协议接收和发送数据示例JAVA

    UDP协议接收和发送数据示例JAVA

    VU-DBS项目:深脑刺激器的全程辅助

    本文介绍了范德堡大学深脑刺激器(DBS)项目,该项目旨在开发和临床评估一个系统,以辅助从规划到编程的整个过程。DBS是一种高频刺激治疗,用于治疗运动障碍,如帕金森病。由于目标区域在现有成像技术中可见性差,因此DBS电极的植入和编程过程复杂且耗时。项目涉及使用计算机辅助手术技术,以及一个定制的微定位平台(StarFix),该平台允许在术前进行图像采集和目标规划,提高了手术的精确性和效率。此外,文章还讨论了系统架构和各个模块的功能,以及如何通过中央数据库和网络接口实现信息共享。

    图像识别项目源码资源(Python和C++)

    图像识别”项目源码资源(Python和C++)

    虚拟同步电机与并电网模型的Simulink仿真参数配置与直接使用指南,虚拟同步电机与并电网模型的Simulink仿真:参数齐全,直接使用,同步电机simulink仿真 并电网模型仿真 参数设置好了

    虚拟同步电机与并电网模型的Simulink仿真参数配置与直接使用指南,虚拟同步电机与并电网模型的Simulink仿真:参数齐全,直接使用,同步电机simulink仿真 并电网模型仿真 参数设置好了,可直接使用 ,虚拟同步电机; simulink仿真; 并电网模型仿真; 参数设置; 使用,虚拟同步电机Simulink仿真与并电网模型参数化应用

    三菱FX3U与力士乐VFC-x610变频器通讯案例详解:PLC控制下的变频器操作与设置程序,含接线方式及昆仑通态触摸屏操作指南,三菱FX3U与力士乐VFC-x610变频器通讯案例详解:接线、设置与程序

    三菱FX3U与力士乐VFC-x610变频器通讯案例详解:PLC控制下的变频器操作与设置程序,含接线方式及昆仑通态触摸屏操作指南,三菱FX3U与力士乐VFC-x610变频器通讯案例详解:接线、设置与程序注解,实现频率设定、启停控制与实时数据读取功能。,三菱FX3U与力士乐VFC-x610变频器通讯程序三菱FX3U与力士乐VFC-x610变频器通讯案例程序,有注释。 并附送程序,有接线方式,设置。 器件:三菱FX3U的PLC,力士乐VFCx610变频器,昆仑通态,威纶通触摸屏。 功能:实现频率设定,启停控制,实际频率读取等。 ,三菱FX3U;力士乐VFC-x610变频器;通讯程序;案例程序;注释;接线方式;设置;频率设定;启停控制;实际频率读取;昆仑通态;威纶通触摸屏。,三菱FX3U与力士乐VFC-x610变频器通讯程序及案例:频率控制与读取实践

    xmselect测试用例~~~~~~~~~~~~~~

    xmselect测试用例~~~~~~~~~~~~~~

    Unity-游戏开发-模型资源-科幻武器

    总共包含 32 款 AAA 级科幻武器。四种武器类型,每种有 8 种不同的纹理变化! 所有内容均采用 PBR 材质,可直接用于开发游戏!

    python词云生成器,将txt文本自动分割生成词云图

    python词云生成器,将txt文本自动分割生成词云图

    基于物联网智能化平台的智慧园区解决方案PPT(28页).pptx

    智慧园区,作为现代城市发展的新形态,旨在通过高度集成的信息化系统,实现园区的智能化管理与服务。该方案提出,利用智能手环、定制APP、园区管理系统及物联网技术,将园区的各类设施与设备紧密相连,形成一个高效、便捷、安全的智能网络。从智慧社区到智慧酒店,从智慧景区到智慧康养,再到智慧生态,五大应用板块覆盖了园区的每一个角落,为居民、游客及工作人员提供了全方位、个性化的服务体验。例如,智能手环不仅能实现定位、支付、求助等功能,还能监测用户健康状况,让科技真正服务于生活。而智慧景区的建设,更是通过大数据分析、智能票务、电子围栏等先进技术,提升了游客的游玩体验,确保了景区的安全有序。 尤为值得一提的是,方案中的智慧康养服务,展现了科技对人文关怀的深刻体现。通过智慧手环与传感器,自动感知老人身体状态,及时通知家属或医疗机构,有效解决了“空巢老人”的照护难题。同时,智慧生态管理系统的应用,实现了对大气、水、植被等环境要素的实时监测与智能调控,为园区的绿色发展提供了有力保障。此外,方案还提出了建立全域旅游营销平台,整合区域旅游资源,推动旅游业与其他产业的深度融合,为区域经济的转型升级注入了新的活力。 总而言之,这份智慧园区建设方案以其前瞻性的理念、创新性的技术和人性化的服务设计,为我们展示了一个充满智慧与活力的未来园区图景。它不仅提升了园区的运营效率和服务质量,更让科技真正融入了人们的生活,带来了前所未有的便捷与舒适。对于正在规划或实施智慧园区建设的决策者而言,这份方案无疑提供了一份宝贵的参考与启示,激发了他们对于未来智慧生活的无限遐想与憧憬。

    使用 SignalR 在 .NET Core 8 最小 API 中构建实时通知

    使用 SignalR 在 .NET Core 8 最小 API 中构建实时通知,构建实时应用程序已成为现代 Web 开发中必不可少的部分,尤其是对于通知、聊天系统和实时更新等功能。SignalR 是 ASP.NET 的一个强大库,可实现服务器端代码和客户端 Web 应用程序之间的无缝实时通信。 参考文章:https://blog.csdn.net/hefeng_aspnet/article/details/145990801

    自适应网址导航网站发布页单页网页模板html源码

    自适应网址导航网站发布页单页网页模板html源码,超级好看自适应清新网址导航网站发布页单页网页模板html源码!无论电脑还是手机,这是一个网页单页源码!! 模板无后台模板,无需数据库,上传服务器直接能用。

Global site tag (gtag.js) - Google Analytics