Android-ffmpeg最佳方法

Android-ffmpeg最佳方法,android,android-ndk,ffmpeg,java-native-interface,Android,Android Ndk,Ffmpeg,Java Native Interface,我正在尝试为android构建ffmpeg。我想用它实现两件事。 1.旋转视频 2.加入两个或多个视频 在我的应用程序中使用ffmpeg有两种方法。 1.具有ffmpeg可执行文件,将其复制到/data/package/并执行ffmpeg命令。 2.用ndk建立ffmpeg库.so文件,编写jni代码等 根据我的需要,哪种方法最好?我可以得到一些遵循这些方法的代码片段吗?您可以通过两种方法实现它,我将使用第一种方法: 将ffmpeg文件放入原始文件夹 您需要使用命令使用ffmpeg可执行文件,但

我正在尝试为android构建ffmpeg。我想用它实现两件事。 1.旋转视频 2.加入两个或多个视频

在我的应用程序中使用ffmpeg有两种方法。 1.具有ffmpeg可执行文件,将其复制到/data/package/并执行ffmpeg命令。 2.用ndk建立ffmpeg库.so文件,编写jni代码等


根据我的需要,哪种方法最好?我可以得到一些遵循这些方法的代码片段吗?

您可以通过两种方法实现它,我将使用第一种方法:

将ffmpeg文件放入原始文件夹

您需要使用命令使用ffmpeg可执行文件,但需要将该文件放入文件系统文件夹并更改该文件的权限,因此请使用以下代码:

public static void installBinaryFromRaw(Context context, int resId, File file) {
    final InputStream rawStream = context.getResources().openRawResource(resId);
    final OutputStream binStream = getFileOutputStream(file);

    if (rawStream != null && binStream != null) {
        pipeStreams(rawStream, binStream);

        try {
            rawStream.close();
            binStream.close();
        } catch (IOException e) {
            Log.e(TAG, "Failed to close streams!", e);
        }       

        doChmod(file, 777);
    }       
}
public static OutputStream getFileOutputStream(File file) {
    try {
        return new FileOutputStream(file);
    } catch (FileNotFoundException e) {
        Log.e(TAG, "File not found attempting to stream file.", e);
    }
    return null;
}

public static void pipeStreams(InputStream is, OutputStream os) {
    byte[] buffer = new byte[IO_BUFFER_SIZE];
    int count;
    try {
        while ((count = is.read(buffer)) > 0) {
            os.write(buffer, 0, count);
        }
    } catch (IOException e) {
        Log.e(TAG, "Error writing stream.", e);
    }
}
public static void doChmod(File file, int chmodValue) {
    final StringBuilder sb = new StringBuilder();
    sb.append("chmod");
    sb.append(' ');
    sb.append(chmodValue);
    sb.append(' ');
    sb.append(file.getAbsolutePath());

    try {
        Runtime.getRuntime().exec(sb.toString());
    } catch (IOException e) {
        Log.e(TAG, "Error performing chmod", e);
    }
}
String command = "data/data/YOUR_PACKAGE/cache/ffmpeg" + THE_REST_OF_YOUR_COMMAND;
        try {
            Process process = Runtime.getRuntime().exec(command);
            process.waitFor();
            Log.d(TAG, "Process finished");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
调用此方法:

private void installFfmpeg() {
    File ffmpegFile = new File(getCacheDir(), "ffmpeg");
    String mFfmpegInstallPath = ffmpegFile.toString();
    Log.d(TAG, "ffmpeg install path: " + mFfmpegInstallPath);
    if (!ffmpegFile.exists()) {
        try {
            ffmpegFile.createNewFile();
        } catch (IOException e) {
            Log.e(TAG, "Failed to create new file!", e);
        }
        Utils.installBinaryFromRaw(this, R.raw.ffmpeg, ffmpegFile);
    }else{
        Log.d(TAG, "It was installed");
    }

    ffmpegFile.setExecutable(true);
}
然后,您就可以通过命令使用ffmpeg文件了。(这种方法对我很有效,但有些人说它不起作用,我不知道为什么,希望不是你的情况)。然后,我们将ffmpeg与以下代码一起使用:

public static void installBinaryFromRaw(Context context, int resId, File file) {
    final InputStream rawStream = context.getResources().openRawResource(resId);
    final OutputStream binStream = getFileOutputStream(file);

    if (rawStream != null && binStream != null) {
        pipeStreams(rawStream, binStream);

        try {
            rawStream.close();
            binStream.close();
        } catch (IOException e) {
            Log.e(TAG, "Failed to close streams!", e);
        }       

        doChmod(file, 777);
    }       
}
public static OutputStream getFileOutputStream(File file) {
    try {
        return new FileOutputStream(file);
    } catch (FileNotFoundException e) {
        Log.e(TAG, "File not found attempting to stream file.", e);
    }
    return null;
}

public static void pipeStreams(InputStream is, OutputStream os) {
    byte[] buffer = new byte[IO_BUFFER_SIZE];
    int count;
    try {
        while ((count = is.read(buffer)) > 0) {
            os.write(buffer, 0, count);
        }
    } catch (IOException e) {
        Log.e(TAG, "Error writing stream.", e);
    }
}
public static void doChmod(File file, int chmodValue) {
    final StringBuilder sb = new StringBuilder();
    sb.append("chmod");
    sb.append(' ');
    sb.append(chmodValue);
    sb.append(' ');
    sb.append(file.getAbsolutePath());

    try {
        Runtime.getRuntime().exec(sb.toString());
    } catch (IOException e) {
        Log.e(TAG, "Error performing chmod", e);
    }
}
String command = "data/data/YOUR_PACKAGE/cache/ffmpeg" + THE_REST_OF_YOUR_COMMAND;
        try {
            Process process = Runtime.getRuntime().exec(command);
            process.waitFor();
            Log.d(TAG, "Process finished");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
正如我所说的,您必须通过命令使用ffmpeg文件,因此您应该在Internet上搜索并选择要使用的命令,然后将其添加到命令字符串中。如果命令失败,您将不会收到任何日志的警告,因此您应该使用终端仿真器尝试您的命令,并确保它工作正常。如果它不起作用,你就看不到任何结果


希望它有用看看您不允许在封闭源代码的应用程序中使用可执行文件(二进制),我以前试过这个应用程序,但它的商业版本是付费的。是的,这个应用满足了我的需求。但是我买不起它的执照。谢谢。是的,我理解你的局限性。事实上,我认为他们的许可模式是不可持续的。但我认为把它列为一种选择是很重要的。是的,我完全同意你的看法。在我看到冈萨罗发布的答案之前,这是我面前唯一的选择。我可以用他的答案实现我想要的。嗨,冈萨罗,这很好用:)。有一个问题,你给我的文件是ffmpeg 0.1.11,我如何使用最新的ffmpeg重新构建它?嗨,rohit。我很高兴它起作用了!你应该重新编译它,如果你不使用linux,它是如此的困难。。。请参阅此链接:我也使用相同的链接在linux上构建ffmpeg。但我还是不能建造它。顺便说一句,链接是用来创建libffmpeg.so文件的,不是用来创建ffmpeg可执行文件的。哦,对不起,我给你发了一个不正确的链接。我不能帮你创建一个新的ffmpeg,因为我使用的是一个朋友编译的,不是我自己,我不知道如何准确地编译它。。。抱歉…使用FFmpeg二进制文件的方法不好,您只能在商业封闭源代码应用程序中使用共享库(.so文件)(使用LGPL许可证,不使用x264)