很艰辛很痛苦...几次几乎被玩死...代码贴出来...对自己是留念...对别人是引玉...
 
开始...
首先是视频转码, 多种视频格式都转换成.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("p_w_picpath2");
    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;
    }
  }