FFmpeg在android 10上不起作用,变成空消息的onFailure(String message)

时间:2019-10-25 20:24:41

标签: java android ffmpeg

我在一个项目中使用FFmpeg进行视频压缩。在Android 10(Google Pixel 3a)上,它将直接发送到onFailure(字符串消息),其中包含发送用于执行的任何命令的空消息。

所以我在我的应用gradle文件中指定了(api'com.writingminds:FFmpegAndroid:0.3.2')

指定清单中的

权限(android.permission.WRITE_EXTERNAL_STORAGE)

我这样做:

InitializationCallback initializationCallback = new InitializationCallback();
    try {
        FFmpeg.getInstance(context).loadBinary(initializationCallback);
    } catch (FFmpegNotSupportedException e) {
        initializationCallback.onFailure();
        initializationCallback.onFinish();
    }

初始化就可以了,这里没有问题。

稍后:

void getData(File inputFile) {
//inputFile points to: /storage/emulated/0/Android/data/{package_name}/files/temp_files/temp_1.mp4
        String[] cmd = ("-i " + inputFile.getAbsolutePath()).split(" ");
        try {
            FFmpeg.getInstance(App.instance).execute(cmd, this);
        } catch (FFmpegCommandAlreadyRunningException e) {
            throw new Error(e);
        }
    }

    @Override
    public void onStart() {
         //This method is called
    }

    @Override
    public void onSuccess(String message) {
         //This method is NOT called
         extractAvailableData(message);
    }

    @Override
    public void onProgress(String message) {
        //This method is NOT called
        extractAvailableData(message);
    }

    @Override
    public void onFailure(String message) {
        //This method is called and the message is empty
        extractAvailableData(message);
    }

    @Override
    public void onFinish() {
        //This method is called
    }

如果我做类似的事情:

String command = "-i ***/file1.mp4 -map 0:v -map 0:a -preset ultrafast -s:v 750:350 ***/file2.mp4";
//file2.mp4 is a non existent file at this point
// (***) --> is just a replacement for the full path of the file, just to keep things shorter here.

String[] cmd = command.split(" ");
        try {
            FFmpeg.getInstance(App.instance).execute(cmd, this);
        } catch (FFmpegCommandAlreadyRunningException e) {
            throw new Error(e);
        }

提供相同的结果,不进行视频转换,仅调用onFailure(“ Nothing”)

即使我这样做:

String[] cmd = {"-version"};
        try {
            FFmpeg.getInstance(App.instance).execute(cmd, this);
        } catch (FFmpegCommandAlreadyRunningException e) {
            throw new Error(e);
        }

我什么也没得到,根本没有输出。

到目前为止,我仅在Android 10上遇到过此问题,在其他设备上也可以正常工作。

2 个答案:

答案 0 :(得分:3)

Android 10发生了行为更改,其中删除了应用主目录的执行权限。如果尝试从App主目录运行执行文件,则将获得权限被拒绝的异常。

以下是有关目标SDK版本29的更改的详细信息:https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission

java.io.IOException: Cannot run program "/data/user/0/<package name>/files/ffmpeg": error=13, Permission denied
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1050)
        at nl.bravobit.ffmpeg.ShellCommand.run(ShellCommand.java:15)
        at nl.bravobit.ffmpeg.FFcommandExecuteAsyncTask.doInBackground(FFcommandExecuteAsyncTask.java:43)
        at nl.bravobit.ffmpeg.FFcommandExecuteAsyncTask.doInBackground(FFcommandExecuteAsyncTask.java:12)
        at android.os.AsyncTask$3.call(AsyncTask.java:378)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: java.io.IOException: error=13, Permission denied
        at java.lang.UNIXProcess.forkAndExec(Native Method)
        at java.lang.UNIXProcess.<init>(UNIXProcess.java:133)
        at java.lang.ProcessImpl.start(ProcessImpl.java:141)

答案 1 :(得分:0)

我不知道这是否是您的情况,但就我而言,问题是在使用它之前我没有调用ffmpeg.loadBinary。

这似乎有点违反直觉,因为它实际上可以与我的测试设备一起使用,而无需这样做。我对为什么有一些想法,但没有时间去测试。重要的是它现在正在工作。这是我必须实现的示例:

            FFmpeg ffmpeg = FFmpeg.getInstance(context);
            ffmpeg.loadBinary(new FFmpegLoadBinaryResponseHandler() {
                @Override
                public void onFailure() {
                       // Report failure to logcat,show the user a dialog, throw an exception or whatever you want to do in case of failure
                }

                @Override
                public void onSuccess() {
                    // Execute the real ffmpeg stuff here

                }

                @Override
                public void onStart() {
                }

                @Override
                public void onFinish() {
                }
            });

在现实世界中,如果您打算多次使用它,则可以使用一个标志来确保它尚未被加载,并避免在这种情况下尝试重新加载它。