ffpeg 簡單視頻壓縮 普通需求類型

   在這個直播 ,點播時代 這個市場對Andriod 音視頻開發 需求越來越多   這個門檻也是有點高的,如果你能熟練的掌握 ffpeg   就業問題不大了。



   ffpeg 太強大  我在項目中也有用到,只是摸到邊而已,自己寫一下記錄一下,自己也挺想往這個方向走,技多不壓身嘛。



   使用ffpeg 壓縮視頻    文末放一個demo 好了   包括視頻錄製 + 壓縮 + 上傳


   我使用的是  Andriod原生  MediaRecorder +SurfaceView + Camera  進行視頻錄製   ffpeg  cmd 命令 執行壓縮。


   先說下壓縮命令好了 :

final String path1 = new File(path).getParent() + "/"
						+ getDate() + "vido.mp4";
				String cmd = "-y -i "
						+ path
						+ " -strict -2 -vcodec libx264 -preset ultrafast -crf 24 -acodec aac -ar 44100 -ac 2 -b:a 96k -s 480x480 -aspect 16:16 "
						+ path1;


參數說明 :  path  錄製源視頻地址     path1  壓縮後視頻保存地址     

 -y(覆蓋輸出文件,即如果1.***文件已經存在的話,不經提示就覆蓋掉了) 
-i "1.avi"(輸入文件是和ffmpeg在同一目錄下的1.avi文件,可以自己加路徑,改名字) 

-strict strictness 跟標準的嚴格性

-vcodec xvid(使用XVID編碼壓縮視頻,不能改的)  本demo 是 libx264    這個是設置壓縮視頻的格式

-preset:指定編碼的配置。x264編碼算法有很多可供配置的參數,不同的參數值會導致編碼的速度大相徑庭,甚至可能影響質量。爲了免去用戶瞭解算法,然後手工配置參數的麻煩。x264提供了一些預設值,而這些預設值可以通過preset指定。這些預設值有包括:ultrafast,superfast,veryfast,faster,fast,medium,slow,slower,veryslow和placebo。ultrafast編碼速度最快,但壓縮率低,生成的文件更大,placebo則正好相反。x264所取的默認值爲medium。需要說明的是,preset主要是影響編碼的速度,並不會很大的影響編碼出來的結果的質量。壓縮高清電影時,我一般用slow或者slower,當你的機器性能很好時也可以使用veryslow,不過一般並不會帶來很大的好處。

-crf:這是最重要的一個選項,用於指定輸出視頻的質量,取值範圍是0-51,默認值爲23,數字越小輸出視頻的質量越高。這個選項會直接影響到輸出視頻的碼率。一般來說,壓制480p我會用20左右,壓制720p我會用16-18,1080p我沒嘗試過。個人覺得,一般情況下沒有必要低於16。最好的辦法是大家可以多嘗試幾個值,每個都壓幾分鐘,看看最後的輸出質量和文件大小,自己再按需選擇。

-acodec aac(音頻編碼用AAC) 

-ac 2(聲道數1或2) 


-ar 24000(聲音的採樣頻率,好像PSP只能支持24000Hz)

-b 1500(視頻數據流量,用-b xxxx的指令則使用固定碼率,數字隨便改,1500以上沒效果;還可以用動態碼率如:-qscale 4和-qscale 6,4的質量比6高) 

-s 368x208(輸出的分辨率爲368x208,注意片源一定要是16:9的不然會變形) 


-aspect aspect 設置橫縱比 4:3 16:9 或 1.3333 1.7777



 這麼在代碼中使用

artts 文件   armeabi-v7a-neon   x86  下放 ffpeg 資源




libs  jar       sardar.jar



寫 3個封裝類 方便調用

package com.mly.sardar;

import android.app.Activity;

import com.github.hiteshsondhi88.libffmpeg.ExecuteBinaryResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.FFmpeg;
import com.github.hiteshsondhi88.libffmpeg.LoadBinaryResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegCommandAlreadyRunningException;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegNotSupportedException;

/**
 *
 */
public class Compressor {

    public Activity a;
    public FFmpeg ffmpeg;
    public Compressor(Activity activity){
        a = activity;
        ffmpeg = FFmpeg.getInstance(a);
    }

    public void loadBinary(final InitListener mListener) {
        try {
            ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
                @Override
                public void onStart() {}

                @Override
                public void onFailure() {
                    mListener.onLoadFail("incompatible with this device");
                }

                @Override
                public void onSuccess() {
                    mListener.onLoadSuccess();
                }
                @Override
                public void onFinish() {

                }
            });
        } catch (FFmpegNotSupportedException e) {
            e.printStackTrace();
        }
    }

    public void execCommand(String cmd,final CompressListener mListener){
        try {
            ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {

                @Override
                public void onStart() {}

                @Override
                public void onProgress(String message) { mListener.onExecProgress(message);}

                @Override
                public void onFailure(String message) { mListener.onExecFail(message); }

                @Override
                public void onSuccess(String message) {
                    mListener.onExecSuccess(message);
                }

                @Override
                public void onFinish() {}
            });
        } catch (FFmpegCommandAlreadyRunningException e) {
            e.printStackTrace();
        }
    }




}


package com.mly.sardar;


/**
 * 
 */
public interface InitListener {
    public void onLoadSuccess();
    public void onLoadFail(String reason);
}

package com.mly.sardar;

/**
 * 
 */
public interface CompressListener {
    public void onExecSuccess(String message);
    public void onExecFail(String reason);
    public void onExecProgress(String message);
}



在oncreate 中初始化

 Compressor com = new Compressor(this);


com.loadBinary(new InitListener() {
			@Override
			public void onLoadSuccess() {
				final String path1 = new File(path).getParent() + "/"
						+ getDate() + "vido.mp4";
				String cmd = "-y -i "
						+ path
						+ " -strict -2 -vcodec libx264 -preset ultrafast -crf 24 -acodec aac -ar 44100 -ac 2 -b:a 96k -s 480x480 -aspect 16:16 "
						+ path1;
				com.execCommand(cmd, new CompressListener() {
					@Override
					public void onExecSuccess(String message) {
						Log.i("success", message);
						record_video_activity_up_text
								.setVisibility(View.VISIBLE);
						new File(path).delete();
						path = path1;
						record_video_activity_up.setVisibility(View.VISIBLE);
						StarLoadDirlog.dialog.dismiss();
						
					}

					@Override
					public void onExecFail(String reason) {
						Log.i("fail", reason);
					}

					@Override
					public void onExecProgress(String message) {
						Log.i("progress", message);
					}
				});


 Demo   整理中····




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