最新靠谱可用的-Mac-环境下-FFmpeg-环境搭建

最近在尝试搭建 FFmpeg 开发环境时遇到一个蛋疼的事,Google 了 N 篇文章竟然没有一篇是可以跑起来的!

少部分教程是给出了自我矛盾的配置(是的,按照贴出来的代码和配置,他自己都跑不起来),大部分教程是看着挺全但忽略了某几个关键的点导致跑不起来,更蛋疼的是碰到报错后错误相关的文章也很少,当然还有一些是年代久远过时了。

于是在成功跑起来后,我将整个搭建过程整理出来,希望可以帮到后面的人。

本文基于 Mac OS X + Android Studio 3.2 + FFmpeg 3.3 + CMake。

文章会分为两部分,第一部分是总结一下碰到的几个坑,这样只是因为报错而无法继续的朋友可以先看看是否可以解决问题;第二部分是搭建过程的完整描述(我特意用另一台电脑测试过,可以完美跑起来)。

一、FFmpeg 搭建的常见问题

1. NDK 的问题

在编译之前,教程都会让我们修改命令中 NDK 的地址为自己本地的地址,我们当然自然而然地改成了 Android Studio 自带的 ndk-bundle。

然后编译的时候就发现会出现errno.h: No such file or directory字样的error。

这是因为 Android Studio 自带的 NDK 缺少相关的 .h 文件,从网上额外下载 NDK 然后编译时使用就可以解决问题。(基于 FFmpeg 3.3)

2. 编译命令的问题

报错信息形如

ffmpeg_build.sh: line 14: ./configure: No such file or directoryffmpeg_build.sh: line 20: --extra-cflags=-Os -fpic -marm: command not found

之类的,请检查一下 Android 编辑脚本的 “/” 后是否有空格。

由于不同系统存在差异,最好找对应系统下他人验证可行的编译命令。

3. 编译相关的版本

编译过程有 NDK 版本、Android 版本、FFmpeg 版本、Android Studio 版本等,不同版本存在差异,最好是完全使用教程描述时的版本。

比如编译命令中包含的 Android 版本
 

export SYSROOT=$NDK/platforms/android-21/arch-arm/

这里的 android-21 改成 26 就不行,因为搜索了这两个文件夹只有 21 中有需要的 .h 文件。

4. 项目构建配置

需要将相关的 .so 文件和 include 文件夹(里面包含一些头文件)都放入 libs 文件夹中,并在 gradle 文件夹中指定 jni 目录,最后编写 CMake 文件,缺少一步就报错

相关学习资料推荐,点击下方链接免费报名,先码住不迷路~】

音视频免费学习地址:https://xxetb.xet.tech/s/2cGd0

【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~

二、FFmpeg 环境配置最佳实践

1. 下载 FFmpeg 源码

git clone https://git.ffmpeg.org/ffmpeg.git

再切到 3.3 分支

git checkout -b 3.3 remotes/origin/release/3.3

2. 修改 configure 文件

在下载好的 ffmpeg 文件夹内可以找到一个 configure 文件,将其中的:

SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'  
LIB_INSTALL_EXTRA_CMD='?(RANLIB)"$(LIBDIR)/$(LIBNAME)"'  
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'  
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)'

修改成

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'  
LIB_INSTALL_EXTRA_CMD='?(RANLIB)"$(LIBDIR)/$(LIBNAME)"'  
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'  
SLIB_INSTALL_LINKS='$(SLIBNAME)'

3. 下载 NDK

就如上文所述,Android Studio 自带的 NDK 缺少部分 .h 文件,不确定是否跟 Android Studio 的 版本或者 NDK 版本有关,也不确定是否所有人都这样。但为了简单,还是下载吧(下载下来的的这个 NDK 只为了编译 FFmpeg,不影响之前的 NDK)。

可以选择去官网下载,我找了个国内的 Android NDK下载(r10d r13b r14b)

下载适用于 Mac OS X 的 android-ndk-r14b-darwin-x86_64.zip 文件。

4. 编写编译脚本
在 ffmpeg 文件夹根目录下创建一个 ffmpeg_build.sh 文件(名称跟配置不相关,想改可以改),具体内容如下:

#!/bin/bash
make clean
# NDK的路径,根据自己的安装位置进行设置
export NDK=/Users/yanzhenghui/Downloads/android-ndk
export SYSROOT=$NDK/platforms/android-21/arch-arm/
export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
export CPU=arm
export PREFIX=$(pwd)/android/$CPU
export ADDI_CFLAGS="-marm"
function build_one
{
./configure \--prefix=$PREFIX \--target-os=linux \--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \--arch=arm \--sysroot=$SYSROOT \--extra-cflags="-Os -fpic $ADDI_CFLAGS" \--extra-ldflags="$ADDI_LDFLAGS" \--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \--nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \--enable-shared \--enable-runtime-cpudetect \--enable-gpl \--enable-small \--enable-cross-compile \--disable-debug \--disable-static \--disable-doc \--disable-asm \--disable-ffmpeg \--disable-ffplay \--disable-ffprobe \--disable-ffserver \--enable-postproc \--enable-avdevice \--disable-symver \--disable-stripping \
$ADDITIONAL_CONFIGURE_FLAG
sed -i '' 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h
sed -i '' 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h
sed -i '' 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h
sed -i '' 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h
sed -i '' 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h
sed -i '' 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h
sed -i '' 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h
sed -i '' 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h
make clean
# 这里是定义用几个CPU编译,我用4个,一般在5分钟之内编译完成
make -j4
make install
}
build_one

需要更改的是这个:

# NDK的路径,根据自己的安装位置进行设置
export NDK=/Users/yanzhenghui/Downloads/android-ndk

改成你本地的路径。

5.执行脚本

从命令行进入 ffmpeg 文件夹后,先执行

chmod +x ffmpeg_build.sh

命令给脚本开启权限,再执行编译脚本:

./ffmpeg_build.sh

等待编译完成,即可在 ffmpeg 文件夹内看到 android 文件夹,里面包含了我们需要的 .so 文件和对应的头文件

6.配置 ffmpeg 项目

这部分 Android - FFmpeg & Mac & AndroidStudio & CMake 环境搭建 这篇文章写得足够好,我就不重复造轮子了,下面摘抄部分权当转载了。(当然,我也全部测试过能跑起来)

6.1 新建项目

新建一个以 CMake 方式构建的 C++ 项目(记得勾选 Include C++ Support)

图二

6.2 拷贝文件到 libs 目录下

将编译好的 .so 和头文件拷贝到 libs 目录下:

6.3 指定 jniLibs 路径

android {...sourceSets {main {jniLibs.srcDirs = ['libs']}}
}

6.4 配置 abiFilters

因为我们只编译出 armeabi-v7a 的 so,所以需要特别指定一下 abi

android {...defaultConfig {...ndk {abiFilters 'armeabi-v7a'}}
}

6.5 编写 CMakeLists

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.native-lib# Sets the library as a shared library.SHARED# Provides a relative path to your source file(s).src/main/cpp/native-lib.cpp )
add_library( avcodec-57SHAREDIMPORTED )
set_target_properties( avcodec-57PROPERTIES IMPORTED_LOCATION../../../../libs/armeabi-v7a/libavcodec-57.so )
add_library( avfilter-6SHAREDIMPORTED )
set_target_properties( avfilter-6PROPERTIES IMPORTED_LOCATION../../../../libs/armeabi-v7a/libavfilter-6.so )
add_library( avformat-57SHAREDIMPORTED )
set_target_properties( avformat-57PROPERTIES IMPORTED_LOCATION../../../../libs/armeabi-v7a/libavformat-57.so )
add_library( avutil-55SHAREDIMPORTED )
set_target_properties( avutil-55PROPERTIES IMPORTED_LOCATION../../../../libs/armeabi-v7a/libavutil-55.so )
add_library( swresample-2SHAREDIMPORTED )
set_target_properties( swresample-2PROPERTIES IMPORTED_LOCATION../../../../libs/armeabi-v7a/libswresample-2.so )
add_library( swscale-4SHAREDIMPORTED )
set_target_properties( swscale-4PROPERTIES IMPORTED_LOCATION../../../../libs/armeabi-v7a/libswscale-4.so )
include_directories( libs/include )
find_library( # Sets the name of the path variable.log-lib# Specifies the name of the NDK library that# you want CMake to locate.log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.native-libavcodec-57avfilter-6avformat-57avutil-55swresample-2swscale-4# Links the target library to the log library# included in the NDK.${log-lib} )

6.6 Java 引入 so 库

static {System.loadLibrary("native-lib");System.loadLibrary("avcodec-57");System.loadLibrary("avfilter-6");System.loadLibrary("avformat-57");System.loadLibrary("avutil-55");System.loadLibrary("swresample-2");System.loadLibrary("swscale-4");
}

最后运行测试下,即配置完成。

原文 最新靠谱可用的-Mac-环境下-FFmpeg-环境搭建 - 掘金

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/618373.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Leetcode】2182. 构造限制重复的字符串

文章目录 题目思路代码 题目 2182. 构造限制重复的字符串 问题:给你一个字符串 s 和一个整数 repeatLimit ,用 s 中的字符构造一个新字符串 repeatLimitedString ,使任何字母 连续 出现的次数都不超过 repeatLimit 次。你不必使用 s 中的全…

关于在前台应用路由调用子应用

需求 在实际写项目的过程中,关于一些前台的官网首页,会需要在一写特定的路由侠调用子应用的需求,在编写的过程中在公用的方法中,来进行处理,处理思想如下,在特定的.vue文件中, 后端 通过后端…

【新年福利】买1送1,告别360!这个系统清理神器干净无广告!

在日常的工作中,面对重要文件时往往都会备份一份;在下载文件时,有时也会不小心把一份文件下载好多次。这些情况会导致电脑中出现重复的文件,删除这些重复文件,可以节省电脑空间,帮助提高电脑运行速度。那么…

人机协同若干问题的分析

一、人机协同的发展态势 人机协同的发展态势是指人类和机器之间合作和协同工作的趋势和动态。 1、增强人类能力 机器可以通过智能算法、大数据分析和机器学习等技术来增强人类的能力。例如,人工智能可以帮助医生更准确地诊断疾病,或者帮助律师更高效地处…

mysql关于创建表的小试题

目录 例题: 解题思路及步骤: 实验步骤: 步骤一:创建数据库 步骤二:创建表 步骤三:插入数据 例题: 1、创建一个英雄表(hero),管于四大名著的主键 nam…

2-《Java并发编程实战》(Java Concurrency in Practice) 代码示例

说明 这是针对《Java并发编程实战》(Java Concurrency in Practice)一书中的示例代码进行扩展,并且进行验证的完整代码,具体背景可看这篇文章:1-《Java并发编程实战》(Java Concurrency in Practice) 代码示例 下面的示例代码都是针对书中的&…

白学的小知识[css3轮播]

代码如下: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>轮播</title><style>.boss {position: relative;width: 200px;height: 200px;overflow: hidden;}.boss>div {width: 10000p…

pytest-mock 数据模拟

文章目录 mock 测试unittest.mockMock类MagicMock类patch装饰器create_autospec函数断言的方法 pytest-mock 使用 mock 测试 在单元测试时&#xff0c;有些数据需要依赖其他服务或者不好获取到&#xff0c;此时需要使用mock来模拟对应的函数、对象等。 mock模拟数据的python…

71、C++ 环境搭建:10分钟快速在 windows 上安装一个 Linux 系统

这一节带大家搭建一个统一的 C++ 环境。 因为不少人用的 C++ 环境都不一样,用的编译器、编辑器也都不一致,很难统一。我在准备写这篇的时候,思考了很久,最终决定搭建一个统一的环境,希望大家后面在运行和调试C++代码时,可以参考这个环境来进行。 如果你是 linux 老用户…

Android Studio个性化修改

Android Studio原始界面看着也太无趣了叭&#xff0c;话不多说跟步骤走就可以。 1.更改Android Studio主题及背景 1.背景修改 File->Settings->Plugins&#xff0c;搜索Sexy Editor 重启后&#xff0c;左侧边栏出现Other Settings选项&#xff0c;点击SexyEditor进行背…

二分搜索边界问题的简单结论

引言 二分搜索是一个说简单也很简单&#xff08;代码很固定&#xff0c;也没几行&#xff09;&#xff0c;说难也很难&#xff08;边界问题可能会让人想不太清楚&#xff09;。 事实上&#xff0c;边界问题也是是算法题中普遍存在的难点。 这篇文章讲两个简单的结论&#xff0…

009-Zynq基操之如何去玩转PL向PS的中断(对新手友好,走过路过千万不要错过)

文章目录 前言一、PL-PS的中断是啥&#xff1f;二、PL-PS端中断详细步骤1.ZYNQ核配置2.PS端中断函数配置3.需要拓展多个中断函数 总结 前言 本设计跟我的ZYNQ实战合集专栏中的脉冲触发电路有关系&#xff0c;也正好趁这个机会讲述一下PL-PS的中断系统&#xff0c;如何去触发中…

Java 设计模式

1.单例设计模式 对某个类只能存在一个对象实例&#xff0c;并且该类只提供一个取得其对象实例的方法。 1.1 饿汉式 构造器私有化 --> 防止直接new类的内部创建对象提供一个static的public方法 getInstance class GirlFriend {private String name;private static GirlFri…

MySQL第二次

作业要求&#xff1a; 作业代码实现&#xff1a; create database db_04 default charsetutf8mb4;use db_04;create table if not exists t_hero(id int primary key auto_increment,name varchar(20) not null unique,nickname varchar(50) not null unique,address varchar…

【Python机器学习系列】建立KNN模型预测心脏疾病(完整实现过程)

这是Python程序开发系列原创文章&#xff0c;我的第198篇原创文章。 一、问题 对于表格数据&#xff0c;一套完整的机器学习建模流程如下&#xff1a; 针对不同的数据集&#xff0c;有些步骤不适用即不需要做&#xff0c;其中橘红色框为必要步骤&#xff0c;由于数据质量较高&…

4点优势,昂首资本使用浮动差价不使用固定差价的原因

在交易中&#xff0c;很多投资者和昂首资本一样&#xff0c;会使用浮动点差而不使用固定点差&#xff0c;那是因为投资者和昂首资本一样认为&#xff0c;使用浮动差价交易会比使用固定价差交易更有优势。 首先在大部分交易时段&#xff0c;价差缩小。正如投资者和昂首资本所知…

Pandas实战100例 | 案例 40: 分组并应用多个聚合函数

案例 40: 分组并应用多个聚合函数 知识点讲解 Pandas 的 groupby 和 agg 方法使得对数据分组后应用多个聚合函数成为可能。这在数据分析中非常有用&#xff0c;可以快速得到分组统计数据。 分组聚合: 使用 groupby 方法对数据进行分组。多重聚合: 使用 agg 方法并传递一个包…

用python批量合并word文件并统一调整图片大小

import os,time from docx import Document from docxcompose.composer import Composer import win32com.client as win32 # 获取要处理的文件夹路径 folder_path r"C:\Users\Thinkpad\Desktop\wordoutput" datanames os.listdir(folder_path) list_wordoutname …

6. 逻辑删除

逻辑删除对应的是物理删除&#xff0c;分别介绍一下这两个概念&#xff1a; 物理删除 &#xff1a;指的是真正的删除&#xff0c;即&#xff1a;当执行删除操作时&#xff0c;将数据表中的数据进行删除&#xff0c;之后将无法再查询到该数据逻辑删除 &#xff1a;并不是真正意…

SQL 解析与执行流程

一、前言 在先前的技术博客中&#xff0c;我们已经详细介绍过数据库的 parser 模块与执行流程&#xff1a;用户输入的 SQL 语句通过词法解析器生成 token&#xff0c;再通过语法分析器生成抽象语法树&#xff08;AST&#xff09;&#xff0c;经过 AST 生成对应的 planNode&…