【问题标题】:FFMPEG Commands is not working on Android 10FFMPEG 命令不适用于 Android 10
【发布时间】:2020-04-30 03:04:15
【问题描述】:

我正在开发一款应用视频效果(如慢动作和快动作)的 Android 应用。我的应用在 android 10 下运行良好,但在 android 10 上运行良好,FFMPEG 没有显示任何错误,只是在 onFailure 回调方法上显示空白错误消息。

我做了一些研究,发现 android 引入了范围权限,您可以通过在清单 android:requestLegacyExternalStorage="true" 上添加此行来暂时绕过它,您将获得存储权限。 添加此行后,应用程序的其余端口可以正常获取用户视频等,但 FFMPEG 无法正常工作。

如果有人对此问题有任何想法或线索,请帮助我。

【问题讨论】:

标签: java android ffmpeg android-ffmpeg


【解决方案1】:

这是适用于 API 16 及以上兼容设备的工作版本。支持android API 29(Q)

dependencies {
    implementation 'com.arthenica:mobile-ffmpeg-full:4.4.LTS'
}

MobileFFmpeg v4.4 的长期支持包

支持以下设备规格

安卓

Android 4.1(API 级别 16)或更高版本

x86 和 x86-64 架构sarm-v7a、arm-v7a-neon、arm64-v8a、

您可以在official repo on github找到更多信息

更新:2021 年 6 月 20 日

不再维护,如What’s next for MobileFFmpeg?中所述

现在被FFmpegKit取代

在这里你可以找到FFmpegKit For Android

特点

  • 在主要版本上支持 API 级别 24+,在 LTS 上支持 API 级别 16+ 发布
  • 包括 arm-v7a、arm-v7a-neon、arm64-v8a、x86 和 x86_64 架构
  • 可以处理存储访问框架 (SAF) Uris
  • 支持设备上的相机访问权限
  • 构建共享本机库 (.so)
  • 创建带有 .aar 扩展名的 Android 存档

【讨论】:

  • 在 Manifest 中为 min API 24 编写的库
  • @MortezaKhodaie 请查看文档了解 LTS 版本 LTS Releases
【解决方案2】:

试试这个

依赖{

实施 'com.arthenica:mobile-ffmpeg-full:4.4.LTS'

}

也看到这个.. ffmpeg-video-editor-android

【讨论】:

  • 在 Manifest 中为 min API 24 编写的库
  • 此库将 apk 大小增加到 64 MB 以上。
【解决方案3】:

使用这个支持 targetSdkVersion 29 的库。

实现'com.arthenica:mobile-ffmpeg-video:4.4'

用于视频压缩的命令:

val complexCommand = arrayOf( “-y”, “-一世”, 输入路径!!, “-s”, "640x480", "-r", "25", “-vcodec”, "mpeg4", "-b:v", "1000k", "-b:a", "48000", “-ac”, "2", “-ar”, "22050", 输出文件路径 )

压缩方式:

  private fun execFFmpegBinary(command: Array<String>, inputPath: String?, listener: CompressionListener?, outputFilePath: String) {
    Config.enableLogCallback { message -> Log.e(Config.TAG, message.text) }
    Config.enableStatisticsCallback { newStatistics ->
        Log.e(
            Config.TAG,
            String.format(
                "frame: %d, time: %d",
                newStatistics.videoFrameNumber,
                newStatistics.time
            )
        )
        Log.d(
            TAG,
            "Started command : ffmpeg " + Arrays.toString(command)
        )
        
        val videoLength = inputPath?.let { VideoUtils.getVideoDuration(it) }
        Log.d(TAG, "execFFmpegBinary: Video Length : $videoLength")
        val progress: Float =
            java.lang.String.valueOf(newStatistics.time).toFloat() / videoLength!!
        val progressFinal = progress * 100
        Log.d(TAG, "Video Length: $progressFinal")
        Log.d(
            Config.TAG,
            java.lang.String.format(
                "frame: %d, time: %d",
                newStatistics.videoFrameNumber,
                newStatistics.time
            )
        )
        Log.d(
            Config.TAG,
            java.lang.String.format(
                "Quality: %f, time: %f",
                newStatistics.videoQuality,
                newStatistics.videoFps
            )
        )
        //progressDialog.setProgress(progressFinal.toInt())
        //val adjustProgress = progressFinal/1.5f
        Log.d(TAG, "execFFmpegBinary: Progress: ${progressFinal.toInt()}")
        listener?.onProgress(progressFinal.toInt())
        Log.d(TAG, "progress : $newStatistics")
    }
    Log.d(
        TAG,
        "Started command : ffmpeg " + Arrays.toString(command)
    )
   /* progressDialog.setMessage("Processing...")
    progressDialog.show()*/
    val executionId = com.arthenica.mobileffmpeg.FFmpeg.executeAsync(
        command
    ) { executionId1: Long, returnCode: Int ->
        if (returnCode == RETURN_CODE_SUCCESS) {
            Log.d(
                TAG,
                "Finished command : ffmpeg " + Arrays.toString(command)
            )

            listener?.compressionFinished(SUCCESS, true, fileOutputPath = outputFilePath)
        } else if (returnCode == Config.RETURN_CODE_CANCEL) {
            Log.e(
                TAG,
                "Async command execution cancelled by user."
            )
            listener?.onFailure(String.format(
                "Async command execution cancelled by user."
            ))
            //if (progressDialog != null) progressDialog.dismiss()
        } else {
            Log.e(
                TAG,
                String.format(
                    "Async command execution failed with returnCode=%d.",
                    returnCode
                )
            )
            listener?.onFailure(String.format(
                "Async command execution failed with returnCode=%d.",
                returnCode
            ))
           // if (progressDialog != null) progressDialog.dismiss()
        }
    }
    Log.e(TAG, "execFFmpegMergeVideo executionId-$executionId")
}

压缩监听器:

 interface CompressionListener {
    fun compressionFinished(
        status: Int,
        isVideo: Boolean,
        fileOutputPath: String?
    )

    fun onFailure(message: String?)
    fun onProgress(progress: Int)
}

调用方式:

execFFmpegBinary(complexCommand, inputPath, listener, outputFilePath)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-16
  • 2021-06-17
相关资源
最近更新 更多