通过FFmpeg在Android上进行视频剪辑

7
我从这个链接的github下载了视频剪辑代码。 第一次使用时它完美地工作,但当我尝试第二次运行它时,代码会崩溃而没有任何异常。然后在崩溃后再次尝试第三次运行它时,它又可以正常工作!有人对这种行为有什么想法吗? 我还正在开发一个应用程序,其中有一个模块是用于修剪视频。如果有人能帮助我,我将不胜感激。

尝试不要清理项目,这样它就可以无问题运行。 - M Abdul Sami
4个回答

4

https://lists.ffmpeg.org/pipermail/libav-user/2012-May/001964.html

在Activity中调用第三方库的本地方法两次会导致Android应用程序关闭

阅读关于“ffmpeg.c”中静态变量问题的内容...

我敢打赌你有同样的问题,需要做一些事情(3个备选项)来重置或GC这些变量:

  1. 获取加载lib的Java类加载器并GC它

  2. 在C层中执行上面链接中OP所做的操作

  3. 编写第二个共享库,在每个调用周期中使用“dlsym”和“dlclose”对第一个库进行操作

Github,请参见此处的“README”

与您遇到的相同问题


非常好的答案,伙计。来自Github链接的README很有用。您能否为您的答案1、2和3提供示例演示? OP给出的第三个答案仅仅是象征性的,作为一个C编程的新手,我无法理解他在做什么,所以是否有其他链接可以更好地解释它? - Arif Nadeem
1
使用Go语言进行第3步。在C语言中构建第2个共享模块,该模块获取FFmpeg中的变量并使用dlsym获取句柄,然后调用Java_net_video_trimmer_natives_VideoTrimmer_trim函数,最后执行DLCLOSE操作。DLCLOSE操作可以清除第一次调用时留下的所有残留物。我的原始答案中的第三个链接中有代码解释。克隆它并查看“ffmpeg_invoke”。 - Robert Rowntree
我想知道你是如何让dlclose工作的,在ndk文档中明确指出:“静态析构函数在程序退出时或调用dlclose()时都不会被调用。” 请参考您的ndk文件夹中的SYSTEM-ISSUES文档。 - Arif Nadeem
5个步骤:(*env)->GetStringUTFChars,dlopen,(*env)->ReleaseStringUTFChars,从包装器调用主要的JNI库...,dlclose。 - Robert Rowntree
对于仍然想使用加载和卸载方法来完成此操作的人(似乎这仍然是最受欢迎的方法),我在最近实现中添加了一些注释,请参考:https://dev59.com/amgv5IYBdhLWcg3wXPsu#28752190 - Mick

3
只需要在你的ffmpeg.c文件中创建一个方法,它应该长这样:
void exitmycode(){
       ffmpeg_exit(0);

}

ffmpeg.c中已经有了ffmpeg_exit(0)方法,你只需要在视频裁剪完成后在你的主C文件中调用exitmycode();即可。

现在发生的情况是,当你使用ffmpeg裁剪视频或其他内容时,它无法完全退出,所以下次运行命令时,它会退出,但它也不会运行你的裁剪命令。再次运行第三次,命令会被完美地执行。因此,我所做的就是在处理完成后手动调用ffmpeg_exit(0)


我认为这会导致整个应用程序退出,包括 Android Java 调用代码?另外,据我所见,最新的 ffmpeg 源代码中已经将 ffmpeg_exit() 替换为 exit_program()。 - Mick

0

我认为在代码中进行视频裁剪调用后,您可以完成活动并重新启动应用程序。

如果应用程序在第二次崩溃后,在第三次运行时正常工作,那么可能是应用程序初始化并在崩溃后重新启动了应用程序。

尝试加载和卸载本地库link


-1

做一件事

如果您已经安装了ffmpeg4android_os库,那么您只需要注释掉StopTranscoding方法中的1行代码即可,就像这样

public void stopTranscoding() {
        Log.d(Prefs.TAG, "stopTranscoding called");
        if (_transcodeBackground != null) {
            //_transcodeBackground.forceCancel();
        }
    }

那就是全部了...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接