Android h264視頻與G711轉碼合併MP4文件

Android h264視頻與G711轉碼合併MP4文件

首先轉碼音頻

音頻轉碼使用EasyAACEncoder 此是EasyDarwin開源流媒體服務團隊整理、開發的一款音頻轉碼到AAC的工具庫編譯的轉碼庫。
具體庫怎麼編譯請看我的另一篇文章:Android G711(PCMA/PCMU)、G726、PCM音頻轉碼到AAC
具體Android怎麼使用該庫方法

使用方法示例:

    /**
     * g711a轉碼爲aac
     *
     * @param cachePath  文件路徑
     * @param inFilename 輸入音頻文件名
     * @param outAacname 輸出音頻文件名
     */
    public void g711toAAC(final String cachePath, final String inFilename, final String outAacname) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                JNIAACEncode.init(JNIAACEncode.Law_ALaw);
                File audiofile = new File(cachePath, inFilename);
                File audiofile2 = new File(cachePath, outAacname);
                int encode = JNIAACEncode.encode(audiofile.getAbsolutePath(), audiofile2.getAbsolutePath());
                if (encode == 0) {
                    ToastUtil.showMessage("聲音轉碼成功");
               }else{
                    ToastUtil.showMessage("聲音轉碼失敗");
                }
            }
        }).start();
    }

注意此處需要編譯的so庫文件,具體文件可以自行編譯或者請查看我上面的文章裏下載編譯好的庫。
然後新建個Java類例如:

    public class JNIAACEncode {

        public static final int Law_ULaw = 0;/**< U law */
        public static final int Law_ALaw = 1;/**< A law */
        public static final int Law_PCM16 = 2;/**< 16 bit uniform PCM values. 原始 pcm 數據 */  
        public static final int Law_G726 = 3;/**< G726 */

        //首先進行實例化audioCodec爲上面聲明的音頻類型
        public static native void init(int audioCodec);
        //原音頻文件路徑與轉碼後的音頻文件路徑
        public static native int encode(String infilename, String outAacname);

        static {
            System.loadLibrary("AACEncode");
        }
    }

h264與aac合併MP4

上面方法可以把g711音頻文件轉碼成aac文件,然後那h264文件與aac文件進行合併MP4文件,轉碼方法有很多,網上教程也很多,不過好多都要進行編譯so庫文件,整起來很是費勁而且導致項目很大。

但是java有工具進行轉碼,那就是isoparser,該爲jar文件直接放到lib裏即可使用,簡直方便的不要不要,而且很小!比那編譯的庫小很多的!使用也很簡單哈。
至於isoparser可以自行下載,不想動手的可以點我下載isoparser-1.1.21.jar

然後怎麼使用呢,請看本人的使用方法:

    /**
     * h264視頻進行轉碼爲MP4
     * <p/>
     * Creates a new Track object from a raw H264 source (DataSource fc). Whenever the timescale and frametick are set to negative value (e.g. -1) the H264TrackImpl tries to detect the frame rate. Typically values for timescale and frametick are:
     * 23.976 FPS: timescale = 24000; frametick = 1001
     * 25 FPS: timescale = 25; frametick = 1
     * 29.97 FPS: timescale = 30000; frametick = 1001
     * 30 FPS: timescale = 30; frametick = 1
     * Parameters:
     * fc - the source file of the H264 samples
     * lang - language of the movie (in doubt: use "eng")
     * timescale - number of time units (ticks) in one second
     * frametick - number of time units (ticks) that pass while showing exactly one frame
     *
     * @param path      h264文件路徑
     * @param audioPath aac聲音文件路徑
     * @param videoPath 保存視頻文件路徑
     * @param fileName  保存視頻文件名
     */
    public void saveVideo(final String path, final String audioPath, final String videoPath, final String fileName) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    DataSource video_file = new FileDataSourceImpl(path);
                    H264TrackImpl h264Track = new H264TrackImpl(video_file, "eng", fps, 1); 
                    Movie movie = new Movie();
                    movie.addTrack(h264Track);

                    File audiofile = new File(audioPath);
                    //如果音頻文件不存在,則不合成音頻,存在則加上音頻
                    if (audiofile.exists()) {
                        AACTrackImpl aacTrack = null;
                        try {
                            DataSource audio_file = new FileDataSourceImpl(audioPath);
                            aacTrack = new AACTrackImpl(audio_file);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        movie.addTrack(aacTrack);
                    }

                    File myCaptureFile = new File(videoPath);
                    if (!myCaptureFile.exists() ) {
                        myCaptureFile.mkdirs();
                    }

                    Container out = new DefaultMp4Builder().build(movie);
                    final File file = new File(myCaptureFile, fileName);
                    FileOutputStream fos = new FileOutputStream(file);
                    out.writeContainer(fos.getChannel());
                    fos.close();

                    //LogMsg.i(TAG, "視頻轉碼完成");

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            // 最後通知圖庫更新
                            sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

上面方法的fps要根據你合成的視頻具體來設置。
可以參考一下:
23.976 FPS: timescale = 24000; frametick = 1001

25 FPS: timescale = 25; frametick = 1

29.97 FPS: timescale = 30000; frametick = 1001

30 FPS: timescale = 30; frametick = 1

這樣就可以完成視頻的合成啦,當然別忘了加上需要的權限比如讀寫權限。
是不是很方便啦啦,還有就是如果視頻合成後播放如果沒有到播放進度最後就播放完了,那是給關鍵幀有關係,如果你的視頻最後沒有關鍵幀話可能導致後面一段不能播放。

GitHub地址

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