Java視頻轉碼

參考:

http://outofmemory.cn/code-snippet/4079/java-usage-Xuggler-get-video-shichang-fen-bianlv-high-kuan-kind-information
http://blog.csdn.net/kissdeath/article/details/6062277
http://www.oschina.net/code/snippet_220255_7784

主函數,開啓線程轉碼:

package com.main;
public class Conver {
        public static void main (String args[]) {
            //開啓新線程轉碼視頻(參數是要轉碼的文件)
            threadPool pool = new threadPool("D:\\video\\old\\test.avi");
//          threadPool pool2 = new threadPool();
            pool.start();
//          pool2.start();
        }
}

線程方法:

package com.main;
public class threadPool extends Thread{
     private String PATH;
     public threadPool( String PATH)
        {
            this.PATH = PATH;
        }
    @Override 
      public void run() { 
            ConverVideo cv = new ConverVideo();
            cv.process(PATH);
      }
}

轉碼函數:

package com.main;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class ConverVideo {

        private String flvfolder = "D:\\video\\old\\"; // 視頻的目錄
        private String ffmpegpath = "D:\\video\\FFmpeg\\bin\\ffmpeg.exe"; // ffmpeg.exe的目錄,轉碼需要的文件
        public boolean process(String PATH) {
            //調用VedioInfoUtil方法得到視頻信息
            VedioInfoUtil viu = new VedioInfoUtil();
            int width = viu.getwidth(PATH);
            int hight = viu.gethight(PATH);
            File fi = new File(PATH);
            String filename = fi.getName();
            //獲得文件名
            filename = filename.substring(0, filename.lastIndexOf("."))
                    .toLowerCase();
            boolean status = true;
            //根據視頻的分辨率向下轉碼
            if(width==1280){
                boolean statu1 = FWVGA(PATH,filename);
                boolean statu2 = nHD(PATH,filename);
                boolean statu3 = PAL(PATH,filename);
                boolean statu4 = VGA(PATH,filename);
                if(statu1==statu2==statu3==statu4==true)
                    status = true;
            }else if(width==854){
                 boolean statu4 = VGA(PATH,filename);
                 boolean statu3 = PAL(PATH,filename);
                 boolean statu2 = nHD(PATH,filename);
                 if(statu2==statu3==statu4==true)
                        status = true; 
            }else if(width==720){
                 boolean statu4 = VGA(PATH,filename);
                 boolean statu2 = nHD(PATH,filename);
                 if(statu2==statu4==true)
                        status = true; 
            }else if(width==640&&hight==480){
                 boolean statu2 = nHD(PATH,filename);
                        status = statu2; 
            }
            return status;
        }


        private boolean checkfile(String path) {
            File file = new File(path);
            if (!file.isFile()) {
                return false;
            } else {
                return true;
            }
        }
        /***
         * 854x480視頻
         * @param p
         * @return
         */
        private boolean FWVGA(String PATH,String filename) {

            if (!checkfile(PATH)) {
                System.out.println(PATH + "不存在");
                return false;
            }
            int i = PATH.indexOf(".");
            //視屏類型
            String videoType = PATH.substring(i);

            List commend = new java.util.ArrayList();
            commend.add(ffmpegpath);
            commend.add("-i");
            commend.add(PATH);
            commend.add("-s");//指定分辨率
            commend.add("854x480");

            commend.add("-r");//楨速率(可以改,確認非標準楨率會導致音畫不同步,所以只能設定爲15或者29.97)
            commend.add("25");

            commend.add("-b");// 指定壓縮比特率,似乎ffmpeg是自動VBR的,指定了就大概是平均比特率,比如768,1500這樣的 
            //就是原來默認項目中有的
            commend.add("1400");

            commend.add("-ab");//設定聲音比特率,前面-ac設爲立體聲時要以一半比特率來設置,比如192kbps的就設成96,轉換 
           // 君默認比特率都較小,要聽到較高品質聲音的話建議設到160kbps(80)以上 
            commend.add("128");




            commend.add("-acodec");//設定聲音編碼
            commend.add("libmp3lame");

            commend.add("-ac");//設定聲道數,1就是單聲道,2就是立體聲
            commend.add("2");

            commend.add("-y");
            commend.add(flvfolder + filename +"854x480"+videoType);

            try {
                ProcessBuilder builder = new ProcessBuilder();
                builder.command(commend);
                Process p = builder.start();
                doWaitFor(p);
                p.destroy();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }



        /***
         * 640X360視頻
         * @param p
         * @return
         */
        private boolean nHD(String PATH,String filename) {

            if (!checkfile(PATH)) {
                System.out.println(PATH + "不存在");
                return false;
            }
            int i = PATH.indexOf(".");
            //視屏類型
            String videoType = PATH.substring(i);

            List commend = new java.util.ArrayList();
            commend.add(ffmpegpath);
            commend.add("-i");
            commend.add(PATH);

            commend.add("-s");//指定分辨率
            commend.add("640X360");

            commend.add("-r");//楨速率(可以改,確認非標準楨率會導致音畫不同步,所以只能設定爲15或者29.97)
            commend.add("25");

            commend.add("-b");// 指定壓縮比特率,似乎ffmpeg是自動VBR的,指定了就大概是平均比特率,比如768,1500這樣的 
            //就是原來默認項目中有的
            commend.add("800");

            commend.add("-ab");//設定聲音比特率,前面-ac設爲立體聲時要以一半比特率來設置,比如192kbps的就設成96,轉換 
           // 君默認比特率都較小,要聽到較高品質聲音的話建議設到160kbps(80)以上 
            commend.add("128");


            commend.add("-acodec");//設定聲音編碼
            commend.add("libmp3lame");

            commend.add("-ac");//設定聲道數,1就是單聲道,2就是立體聲
            commend.add("2");


            commend.add("-y");
            commend.add(flvfolder + filename + "640X360"+videoType);

            try {
                ProcessBuilder builder = new ProcessBuilder();
                builder.command(commend);
                Process p = builder.start();
                doWaitFor(p);
                p.destroy();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

        /***
         *720x576視頻
         * @param p
         * @return
         */
        private boolean PAL(String PATH,String filename) {

            if (!checkfile(PATH)) {
                System.out.println(PATH + "不存在");
                return false;
            }
            int i = PATH.indexOf(".");
            //視屏類型
            String videoType = PATH.substring(i);

            List commend = new java.util.ArrayList();
            commend.add(ffmpegpath);
            commend.add("-i");
            commend.add(PATH);

            commend.add("-s");//指定分辨率
            commend.add("720x576");

            commend.add("-r");//楨速率(可以改,確認非標準楨率會導致音畫不同步,所以只能設定爲15或者29.97)
            commend.add("25");

            commend.add("-b");// 指定壓縮比特率,似乎ffmpeg是自動VBR的,指定了就大概是平均比特率,比如768,1500這樣的 
            //就是原來默認項目中有的
            commend.add("1500");

            commend.add("-ab");//設定聲音比特率,前面-ac設爲立體聲時要以一半比特率來設置,比如192kbps的就設成96,轉換 
           // 君默認比特率都較小,要聽到較高品質聲音的話建議設到160kbps(80)以上 
            commend.add("128");

            commend.add("-acodec");//設定聲音編碼
            commend.add("libmp3lame");

            commend.add("-ac");//設定聲道數,1就是單聲道,2就是立體聲
            commend.add("2");

            commend.add("-y");
            commend.add(flvfolder + filename + "720x576"+videoType);



            try {
                ProcessBuilder builder = new ProcessBuilder();
                builder.command(commend);
                Process p = builder.start();
                doWaitFor(p);
                p.destroy();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }




        /***
         *640x480視頻
         * @param p
         * @return
         */
        private boolean VGA(String PATH,String filename) {

            if (!checkfile(PATH)) {
                System.out.println(PATH + "不存在");
                return false;
            }
            int i = PATH.indexOf(".");
            //視屏類型
            String videoType = PATH.substring(i);

            List commend = new java.util.ArrayList();
            commend.add(ffmpegpath);
            commend.add("-i");
            commend.add(PATH);

            commend.add("-s");//指定分辨率
            commend.add("640x480");

            commend.add("-r");//楨速率(可以改,確認非標準楨率會導致音畫不同步,所以只能設定爲15或者29.97)
            commend.add("25");

            commend.add("-b");// 指定壓縮比特率,似乎ffmpeg是自動VBR的,指定了就大概是平均比特率,比如768,1500這樣的 
            //就是原來默認項目中有的
            commend.add("1000");

            commend.add("-ab");//設定聲音比特率,前面-ac設爲立體聲時要以一半比特率來設置,比如192kbps的就設成96,轉換 
           // 君默認比特率都較小,要聽到較高品質聲音的話建議設到160kbps(80)以上 
            commend.add("128");

            commend.add("-acodec");//設定聲音編碼
            commend.add("libmp3lame");

            commend.add("-ac");//設定聲道數,1就是單聲道,2就是立體聲
            commend.add("2");

            commend.add("-y");
            commend.add(flvfolder + filename + "640x480"+videoType);


            try {
                ProcessBuilder builder = new ProcessBuilder();
                builder.command(commend);
                Process p = builder.start();
                doWaitFor(p);
                p.destroy();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }


        @SuppressWarnings("static-access")
        public int doWaitFor(Process p) {
            InputStream in = null;
            InputStream err = null;
            int exitValue = -1; // returned to caller when p is finished
            try {
                System.out.println("comeing");
                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());
                            System.out.print(c);
                        }
                        while (err.available() > 0) {
                            Character c = new Character((char) err.read());
                            System.out.print(c);
                        }

                        exitValue = p.exitValue();
                        finished = true;

                    } catch (IllegalThreadStateException e) {
                        Thread.currentThread().sleep(500);
                    }
                }
            } catch (Exception e) {
                System.err.println("doWaitFor();: unexpected exception - "
                        + e.getMessage());
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }

                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
                if (err != null) {
                    try {
                        err.close();
                    } catch (IOException e) {
                        System.out.println(e.getMessage());
                    }
                }
            }
            return exitValue;
        }

}

獲得視頻信息函數:

package com.main;
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;

/**
 * 視頻操作類
 * @author Administrator
 *
 */
public class VedioInfoUtil {
    /**
     * 獲取視頻的時長,分辨率、大小
     * @param filename
     * @return
     */
    public int getwidth(String filename){
        int width = 0;

         // first we create a Xuggler container object
        IContainer container = IContainer.make();

        // we attempt to open up the container
        int result = container.open(filename, IContainer.Type.READ, null);

        // check if the operation was successful
        if (result<0)
            return 0;

        // query how many streams the call to open found
        int numStreams = container.getNumStreams();
        // query for the total duration
        long duration = container.getDuration();
        // query for the file size
        long fileSize = container.getFileSize();
        long secondDuration = duration/1000000;
        System.out.println("時長:"+secondDuration+"秒");
        System.out.println("文件大小:"+fileSize+"M");
        for (int i=0; i<numStreams; i++) {
            IStream stream = container.getStream(i);
            IStreamCoder coder = stream.getStreamCoder();
            if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
                 System.out.println("視頻寬度:"+coder.getWidth());
                 System.out.println("視頻高度:"+coder.getHeight());
                 width = coder.getWidth() ;
            }
        }
        return width;
    }

    public int gethight(String filename){

        int hight = 0;
        IContainer container = IContainer.make();
        int result = container.open(filename, IContainer.Type.READ, null);

        // check if the operation was successful
        if (result<0)
            return 0;
        int numStreams = container.getNumStreams();
        long duration = container.getDuration();
        long fileSize = container.getFileSize();
        long secondDuration = duration/1000000;

        System.out.println("時長:"+secondDuration+"秒");
        System.out.println("文件大小:"+fileSize+"M");
        for (int i=0; i<numStreams; i++) {
            IStream stream = container.getStream(i);
            IStreamCoder coder = stream.getStreamCoder();
            if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
                 System.out.println("視頻寬度:"+coder.getWidth());
                 System.out.println("視頻高度:"+coder.getHeight());
                 hight = coder.getHeight() ;
            }
        }
        return hight;
}

}

案例下載:

http://pan.baidu.com/s/1geVK8Qv 密碼:hsgd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章