說說Android的視頻裁剪(三)

有一段時間沒有更新博客了。
最近有人在我的博客中跟我說mp4Parse不能裁剪mov視頻,問我有沒有其他的解決方案,所以這次我更新了一下自己的項目:Android-Video-Trimmer,使用ffmpeg來實現視頻的裁剪。

FFmpeg是為大家所熟悉的處理視頻的一個跨平臺的開源庫,支持android、ios。我們可以自己手動編譯不同平臺的lib庫,從何集成到我們的項目中去。但是FFmpeg是一個C/C++的庫,對于熟悉Java開發的Android同學來說,更希望是Java層面的調用。

在我的項目中,集成了一個FFmpegAndroid開發庫,這個庫優點是我們可以直接用Java的API來執行ffmpge的命令,缺點是該庫比較大(大概19M),沒辦法對庫做瘦身縮減工作。下面是我集成這個庫的幾個步驟。

1. 引入庫的方式有兩種:aar或者源碼依賴

aar依賴:

dependencies {
    compile 'com.writingminds:FFmpegAndroid:0.3.2'
}

源碼依賴:
用git將ffmpeg-android-javaclone到本地,然后把項目中FFmpegAndroid庫的源碼加入到自己的項目中。

FFmpegAndroid

2.庫的初始化
public class ZApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        initFFmpegBinary(this);
    }

    private void initFFmpegBinary(Context context) {

        try {
            FFmpeg.getInstance(context).loadBinary(new LoadBinaryResponseHandler() {
                @Override
                public void onFailure() {
                }
            });

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

初始化的目的是根據Android手機的cpu架構,load對應架構的ffmpeg庫。

3.執行ffmpeg的commend命令

上面的準備工作做完之后,剩下就是我們關心的問題了,如何執行ffmpeg命令行呢?在前面我已經說了,這個庫是對ffmpeg的在Linux系統中命令行的一個封裝,所以我們需要在該庫中找到一個這樣的API。
那我在FFmpegInterface.java類中找到了如下的PAI:

    /**
     * Executes a command
     * @param environvenmentVars Environment variables
     * @param cmd command to execute
     * @param ffmpegExecuteResponseHandler {@link FFmpegExecuteResponseHandler}
     * @throws FFmpegCommandAlreadyRunningException
     */
    public void execute(Map<String, String> environvenmentVars, String[] cmd, FFmpegExecuteResponseHandler ffmpegExecuteResponseHandler) throws FFmpegCommandAlreadyRunningException;
 /**
     * Executes a command
     * @param cmd command to execute
     * @param ffmpegExecuteResponseHandler {@link FFmpegExecuteResponseHandler}
     * @throws FFmpegCommandAlreadyRunningException
     */
    public void execute(String[] cmd, FFmpegExecuteResponseHandler ffmpegExecuteResponseHandler) throws FFmpegCommandAlreadyRunningException;

小伙伴們可以看到參數String[] cmd,就是我所說的控制臺的命令行參數,只要將我們的命令行傳入,設置好回調,剩下的事情就是靜靜等著ffmpeg觸發我們的回調了,是不是感覺很爽!
下面是我的調用實現:

public static void trimVideo(Context context, String inputFile, String outputFile, long startMs, long endMs, final OnTrimVideoListener callback) {
       final String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
       final String outputName = "trimmedVideo_" + timeStamp + ".mp4";

       String start = convertSecondsToTime(startMs/1000);
       String duration = convertSecondsToTime((endMs - startMs)/1000);

       /**ffmpeg -ss START -t DURATION -i INPUT -vcodec copy -acodec copy OUTPUT
        -ss 開始時間,如: 00:00:20,表示從20秒開始;
        -t 時長,如: 00:00:10,表示截取10秒長的視頻;
        -i 輸入,后面是空格,緊跟著就是輸入視頻文件;
        -vcodec copy 和 -acodec copy 表示所要使用的視頻和音頻的編碼格式,這里指定為copy表示原樣拷貝;
        INPUT,輸入視頻文件;
        OUTPUT,輸出視頻文件*/
       String cmd = "-ss " + start + " -t " + duration + " -i " + inputFile + " -vcodec copy -acodec copy " + outputFile + "/" + outputName;
       String[] command = cmd.split(" ");
       try {
           FFmpeg.getInstance(context).execute(command, new ExecuteBinaryResponseHandler() {
               @Override
               public void onFailure(String s) {
               }

               @Override
               public void onSuccess(String s) {
                   callback.onFinishTrim(null);
               }

               @Override
               public void onStart() {
                   callback.onStartTrim();
               }

               @Override
               public void onFinish() {
               }
           });
       } catch (FFmpegCommandAlreadyRunningException e) {
           // do nothing for now
       }
   }

上面主要是拼出ffmpeg視頻裁剪的命令行參數。
FFmpeg命令大全
視頻裁剪的命令如下:
ffmpeg -ss START -t DURATION -i INPUT -vcodec copy -acodec copy OUTPUT
需要主意的是:
DURATION 是表示視頻的持續時間而不是結束時間
INPUT 表示輸入的包含文件名的文件路徑 e.g: sdcard/xxx/xx/input.mp4
OUTPUT 表示輸出的包含文件名的文件路徑 e.g: sdcard/xxx/xx/output.mov

其他命令也基本也差不多,需要實現什么功能之后可以去查詢具體的命令行,對著實現就行。

Thanks for reading. To help others please click ? to recommend this article if you found it helpful.

You can also follow me at GitHub.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,532評論 25 708
  • afinalAfinal是一個android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,569評論 2 45
  • 曾經總是不解風情, 卻無意邂逅美麗風景, 曾經總是不羈流浪, 卻渴求一盞溫暖燈光。 不是我有心逃走, 只是明白將來...
    小王爺小王爺閱讀 234評論 0 0
  • 1.今天又能享受老媽給我準備的愛心早餐,真的好幸福好幸福,進賬20! 2.今天可以享受同事分享的葡萄和零食,進賬1...
    吸引力修煉閱讀 143評論 0 0
  • Eclipse快速添加get、set方法 右鍵 -->Source-->Generate Getters and ...
    WSGNSLog閱讀 513評論 0 0