编译环境
编译平台:ubuntu 16.04LTS
ffmpeg版本:release/4.2(exoplayer2.18.0版本官方推荐的)
ndk版本:android-ndk-r21e(exoplayer2.18.0版本官方进行过测试)
这里主要是参考官方的文档来进行编译的,我这一篇是参考2.18.0版本官方文档编译的。
如果这里和官方文档不一致,大家按照官方文档进行编译。
拉取ExoPlayer代码和ffmpeg代码
clone ExoPlayer
git clone https://github.com/google/ExoPlayer.git
clone ffmpeg 然后切换分支
git clone git://source.ffmpeg.org/ffmpeg
cd ffmpeg
git checkout release/4.2
最好是能科学上网要不然这拉取代码的速度真的是栓Q
配置终端的变量
刚clone下来的ExoPlay项目ffmpeg扩展对应的路径
cd "<path to EXOPlayer project checkout>"
FFMPEG_MODULE_PATH="$(pwd)/extensions/ffmpeg/src/main"
NDK的路径
NDK_PATH="<path to Android NDK>"
配置系统环境
HOST_PLATFORM="linux-x86_64"
配置ffmpeg的路径
FFMPEG_PATH="<这里是刚刚clone下来的ffmpeg4.2版本的路径>"
配置要支持音频格式
Sample format | Decoder name(s) |
---|---|
Vorbis | vorbis |
Opus | opus |
FLAC | flac |
ALAC | alac |
PCM μ-law | pcm_mulaw |
PCM A-law | pcm_alaw |
MP1, MP2, MP3 | mp3 |
AMR-NB | amrnb |
AMR-WB | amrwb |
AAC | aac |
AC-3 | ac3 |
E-AC-3 | eac3 |
DTS, DTS-HD | dca |
TrueHD | mlp truehd |
看到这里我一脸懵逼,上面除了mp3和pcm其他的我都不认识。 然后就在网上找到了这个,对这些格式有个简单的了解吧。
名称 | 无损压缩 | 文件扩展名 |
---|---|---|
Monkey's Audio | ✔️ | .ape |
FLAC(Free Lossless Audio Codec) | ✔️ | .flac |
ALAC(Apple Lossless Audio Codec) | ✔️ | .m4a/.caf |
MP3(MPEG Audio Layer III) | ❌ | .mp3 |
WMA(Windows Media Audio) | ❌ | .wma |
AAC(Advanced Audio Coding) | ❌ | .acc/.mp4/.m4a |
Vorbis | ❌ | .ogg |
Speex | ❌ | .spx |
Opus | ❌ | .opus |
Ogg | .ogg | |
WAV(Waveform Audio File Format) | .wav | |
AIFF(Audio Interchange File Format) | .aiff、.aif |
配置要支持音频格式
这里就这样配置吧,大家就按照自己的需求配置,也可以全部写上。
ENABLED_DECODERS=(vorbis opus flac alac mp3 aac ac3 eac3)
创建ffmpeg源码的链接
cd "${FFMPEG_MODULE_PATH}/jni" && \
ln -s "$FFMPEG_PATH" ffmpeg
编辑build_ffmpeg.sh(可选)
打开build_ffmpeg.sh 可以编辑它,选择你要编译的平台armeabi-v7a
, arm64-v8a
, x86
and x86_64
。
这里全部都要,就不编辑它了。
最后编译
cd "${FFMPEG_MODULE_PATH}/jni" && \
./build_ffmpeg.sh \
"${FFMPEG_MODULE_PATH}" "${NDK_PATH}" "${HOST_PLATFORM}" "${ENABLED_DECODERS[@]}"
可能会碰到的问题:
xxx/toolchains/llvm/prebuilt/linux-x86_64/xxx not found
我碰到这个问题的原因是我没去官网下载对应的NDK,我是直接用AndroidStudio 里的SdkManadager下载对应的Ndk,然后找到AndroidStudio对应的SDK里面找到对应的ndk版本的路径。
一定要去官网下载对应的NDK
然后重新配置NDK的路径,最后编译就好了。
编译得到ExoPlayer ffmpeg 扩展的aar
在AndroidStudio中打开ExoPlayer这个项目(就是最开始clone的Exoplayer的路径),然后在终端(用ubuntu终端也行)输入下面命令:
./gradlew extension-ffmpeg:assembleRelease
最后编译完成,在下图可以找到编译出来的aar,然后拿到你自己的项目当中取用
编译可能会出现的问题:
> Failed to apply plugin 'com.android.internal.application'.
> Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
Your current JDK is located in /usr/lib/jvm/java-8-openjdk-amd64/jre
You can try some of the following options:
- changing the IDE settings.
- changing the JAVA_HOME environment variable.
- changing `org.gradle.java.home` in `gradle.properties`.
可以在工程的gradle.properties加上配置:
org.gradle.java.home=<jdk 11 版本的路径>
可以不用下载直接用androidStudio的路径
org.gradle.java.home=/home/jackiehou/Android_studio/AS/android-studio/jre
下一个问题:ERROR: CMake '3.21.0' or higher was not found in SDK
这里CMake最高只有3.18.0,androidStudio也是最新版本,如果sdkmanager有高版本的cmake,大家直接在这里安装就行了。
如果没有就要去CMake的官网下载对应的cmake,这里我们用3.23.2版本的
下载上图选中的地方,然后解压。
配置特定版本的 CMake
将其添加到项目的 local.properties
文件中,如下所示。
# If you set this property, Gradle no longer uses PATH to find CMake.
cmake.dir = "path-to-cmake"
在自己的项目中使用编译好的aar
依赖之前编译好的aar
implementation files('libs/extension-ffmpeg-release.aar')
添加FfmpegAudioRenderer,并打开这个扩展
private val mRenderFactory =
object : DefaultRenderersFactory(MyApp.instance.applicationContext) {
override fun buildAudioRenderers(
context: Context,
extensionRendererMode: Int,
mediaCodecSelector: MediaCodecSelector,
enableDecoderFallback: Boolean,
audioSink: AudioSink,
eventHandler: Handler,
eventListener: AudioRendererEventListener,
out: ArrayList<Renderer>
) {
//添加FfmpegAudioRenderer
out.add(FfmpegAudioRenderer())
super.buildAudioRenderers(
context,
extensionRendererMode,
mediaCodecSelector,
enableDecoderFallback,
audioSink,
eventHandler,
eventListener,
out
)
}
}.apply {
setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER)
}
播放器实例化
val player: ExoPlayer by lazy {
Log.d("ExoPlayer", "${FfmpegLibrary.isAvailable()}")
if (FfmpegLibrary.isAvailable() && useFfmpeg) {
ExoPlayer.Builder(MyApp.instance.applicationContext, mRenderFactory)
} else {
ExoPlayer.Builder(MyApp.instance.applicationContext)
}
.build()
.also {
it.addAnalyticsListener(EventLogger())
it.addListener(listener)
}
}
播放
//这里用exoPlayer Demo里找了一个没使用扩展无法播放的资源
val url = "https://storage.googleapis.com/exoplayer-test-media-1/flac/play.flac"
val mediaItem: MediaItem = MediaItem.fromUri(url)
player.setMediaItem(mediaItem)
player.prepare()
player.play()