FFmpeg4Android:如何从图库中选择视频?

时间:2015-12-04 07:14:42

标签: android android-intent video ffmpeg

我使用FFmpeg4Android库创建了一个应用程序。我想使用ffmpeg在视频中添加水印。添加水印的命令工作正常但编码在命令中具有预先固定的视频名称。我想从图库文件夹中选择视频,然后在视频中添加水印。我不知道如何添加使用FFmpeg选择视频的意图。我试图添加像这样的意图用PICK_FROM_GALLERY意图替换in.mp4:

 private void runTranscodingUsingLoader() {
    Log.i(Prefs.TAG, "runTranscodingUsingLoader started...");

    PowerManager powerManager = (PowerManager)ProgressBarExample.this.getSystemService(Activity.POWER_SERVICE);
    WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VK_LOCK");
    Log.d(Prefs.TAG, "Acquire wake lock");
    wakeLock.acquire();

    Intent intent = new Intent();

    intent.setType("video/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);

    startActivityForResult(Intent.createChooser(intent, "Complete action using"), PICK_FROM_GALLERY);


    String[] complexCommand = {"ffmpeg","-y" ,"-i", String.valueOf(PICK_FROM_GALLERY),"-strict","experimental",
            "-vf", "movie=/sdcard/videokit/watermark.png [watermark];" +
            " [in][watermark] overlay=main_w-overlay_w-10:10 [out]","-s",
            "320x240","-r", "30", "-b", "15496k", "-vcodec", "mpeg4","-ab",
            "48000", "-ac", "2", "-ar", "22050", "/sdcard/videokit/out1.mp4"};

它会打开图库,但水印命令不会在所选视频中执行。有人可以帮我解决这个问题。我找不到关于此的适当参考/示例。我的完整编码如下。

public class ProgressBarExample extends Activity  {

public ProgressDialog progressBar;

String workFolder = null;
String demoVideoFolder = null;
String demoVideoPath = null;
String vkLogPath = null;
LoadJNI vk;
private final int STOP_TRANSCODING_MSG = -1;
private final int FINISHED_TRANSCODING_MSG = 0;
private boolean commandValidationFailedFlag = false;
private static final int PICK_FROM_GALLERY = 1;

private void runTranscodingUsingLoader() {
    Log.i(Prefs.TAG, "runTranscodingUsingLoader started...");

    PowerManager powerManager = (PowerManager)ProgressBarExample.this.getSystemService(Activity.POWER_SERVICE);
    WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VK_LOCK");
    Log.d(Prefs.TAG, "Acquire wake lock");
    wakeLock.acquire();




    String[] complexCommand = {"ffmpeg","-y" ,"-i", "/sdcard/videokit/in.mp4","-strict","experimental",
            "-vf", "movie=/sdcard/videokit/watermark.png [watermark];" +
            " [in][watermark] overlay=main_w-overlay_w-10:10 [out]","-s",
            "320x240","-r", "30", "-b", "15496k", "-vcodec", "mpeg4","-ab",
            "48000", "-ac", "2", "-ar", "22050", "/sdcard/videokit/out1.mp4"};
    ///////////////////////////////////////////////////////////////////////


    vk = new LoadJNI();
    try {
        // running complex command with validation
        vk.run(complexCommand, workFolder, getApplicationContext());

        // running without command validation
        //vk.run(complexCommand, workFolder, getApplicationContext(), false);

        // running regular command with validation
        //vk.run(GeneralUtils.utilConvertToComplex(commandStr), workFolder, getApplicationContext());

        Log.i(Prefs.TAG, "vk.run finished.");
        // copying vk.log (internal native log) to the videokit folder
        GeneralUtils.copyFileToFolder(vkLogPath, demoVideoFolder);

    } catch (CommandValidationException e) {
        Log.e(Prefs.TAG, "vk run exeption.", e);
        commandValidationFailedFlag = true;

    } catch (Throwable e) {
        Log.e(Prefs.TAG, "vk run exeption.", e);
    }
    finally {
        if (wakeLock.isHeld()) {
            wakeLock.release();
            Log.i(Prefs.TAG, "Wake lock released");
        }
        else{
            Log.i(Prefs.TAG, "Wake lock is already released, doing nothing");
        }
    }

    // finished Toast
    String rc = null;
    if (commandValidationFailedFlag) {
        rc = "Command Vaidation Failed";
    }
    else {
        rc = GeneralUtils.getReturnCodeFromLog(vkLogPath);
    }
    final String status = rc;
    ProgressBarExample.this.runOnUiThread(new Runnable() {
        public void run() {
            Toast.makeText(ProgressBarExample.this, status, Toast.LENGTH_LONG).show();
            if (status.equals("Transcoding Status: Failed")) {
                Toast.makeText(ProgressBarExample.this, "Check: " + vkLogPath + " for more information.", Toast.LENGTH_LONG).show();
            }
        }
    });
}


@Override
public void onCreate(Bundle savedInstanceState) {
    Log.i(Prefs.TAG, "onCreate ffmpeg4android ProgressBarExample");

    super.onCreate(savedInstanceState);
    setContentView(R.layout.ffmpeg_demo_client_2);

    demoVideoFolder = Environment.getExternalStorageDirectory().getAbsolutePath() + "/videokit/";
    demoVideoPath = demoVideoFolder + "in.mp4";

    Log.i(Prefs.TAG, getString(R.string.app_name) + " version: " + GeneralUtils.getVersionName(getApplicationContext()) );

    Button invoke =  (Button)findViewById(R.id.invokeButton);
    invoke.setOnClickListener(new OnClickListener() {
        public void onClick(View v){
            Log.i(Prefs.TAG, "run clicked.");
            runTranscoding();
        }
    });

    workFolder = getApplicationContext().getFilesDir() + "/";
    Log.i(Prefs.TAG, "workFolder (license and logs location) path: " + workFolder);
    vkLogPath = workFolder + "vk.log";
    Log.i(Prefs.TAG, "vk log (native log) path: " + vkLogPath);
    GeneralUtils.copyLicenseFromAssetsToSDIfNeeded(this, workFolder);
    GeneralUtils.copyDemoVideoFromAssetsToSDIfNeeded(this, demoVideoFolder);
    int rc = GeneralUtils.isLicenseValid(getApplicationContext(), workFolder);
    Log.i(Prefs.TAG, "License check RC: " + rc);
}



private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        Log.i(Prefs.TAG, "Handler got message");
        if (progressBar != null) {
            progressBar.dismiss();

            // stopping the transcoding native
            if (msg.what == STOP_TRANSCODING_MSG) {
                Log.i(Prefs.TAG, "Got cancel message, calling fexit");
                vk.fExit(getApplicationContext());


            }
        }
    }
};

public void runTranscoding() {
    progressBar = new ProgressDialog(ProgressBarExample.this);
    progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    progressBar.setTitle("FFmpeg4Android Direct JNI");
    progressBar.setMessage("Press the cancel button to end the operation");
    progressBar.setMax(100);
    progressBar.setProgress(0);

    progressBar.setCancelable(false);
    progressBar.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            handler.sendEmptyMessage(STOP_TRANSCODING_MSG);
        }
    });

    progressBar.show();

    new Thread() {
        public void run() {
            Log.d(Prefs.TAG,"Worker started");
            try {
                //sleep(5000);
                runTranscodingUsingLoader();
                handler.sendEmptyMessage(FINISHED_TRANSCODING_MSG);

            } catch(Exception e) {
                Log.e("threadmessage",e.getMessage());
            }
        }
    }.start();

    // Progress update thread
    new Thread() {
        ProgressCalculator pc = new ProgressCalculator(vkLogPath);
        public void run() {
            Log.d(Prefs.TAG,"Progress update started");
            int progress = -1;
            try {
                while (true) {
                    sleep(300);
                    progress = pc.calcProgress();
                    if (progress != 0 && progress < 100) {
                        progressBar.setProgress(progress);
                    }
                    else if (progress == 100) {
                        Log.i(Prefs.TAG, "==== progress is 100, exiting Progress update thread");
                        pc.initCalcParamsForNextInter();
                        break;
                    }
                }

            } catch(Exception e) {
                Log.e("threadmessage",e.getMessage());
            }
        }
    }.start();
}

}

任何帮助/指导都会非常有帮助。谢谢。

1 个答案:

答案 0 :(得分:1)

FFmpeg不用于从图库或任何地方获取视频。
但它用于处理给定路径的视频,因此您需要根据用户选择选择视频通过意图默认的android视频选择器。在onActivityResult(...)方法之后,您将获得所选视频的路径,然后在获取此视频路径后,您可以将此路径传递给适当的ffmpeg命令进行视频处理。