最新版本Exoplayer扩展FFmpeg音频软解码保姆级教程

news/2025/2/22 17:03:37

ExoPlayer 是一个开源的 Android 媒体播放库,由 Google 开发和维护,用于替代 Android 系统自带的 MediaPlayer。它提供了更强大的功能、更好的性能和更高的灵活性,适用于各种复杂的媒体播放场景。所以被广泛用于各种播放器场景。

最近项目中也使用了Exoplayer进行歌曲播放,但遇到报错:

02-14 18:26:05.078  2194  3425 I ACodec  : codec does not support config operating rate (err -2147483648)                                                                                              
02-14 18:26:05.085  1958  3430 E SoftMP3 : mp3 decoder returned error 1                                                                                                                                
02-14 18:26:05.085  2194  3425 E ACodec  : [OMX.google.mp3.decoder] ERROR(0x80001001)                                                                                                                  
02-14 18:26:05.085  2194  3425 E ACodec  : signalError(omxError 0x80001001, internalError -2147483648)                                                                                                 
02-14 18:26:05.085  2194  3425 E MediaCodec: Codec reported err 0x80001001, actionCode 0, while in state 6                                                                                             
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer: Audio codec error                                                                                                                            
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:   java.lang.IllegalStateException                                                                                                            
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at android.media.MediaCodec.native_dequeueInputBuffer(Native Method)                                                                   
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at android.media.MediaCodec.dequeueInputBuffer(MediaCodec.java:2505)                                                                   
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter.dequeueInputBufferIndex(SynchronousMediaCodecAdapter.java:101)    
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:1224)                               
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:818)                                         
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1047)                                         
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:522)                                       
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at android.os.Handler.dispatchMessage(Handler.java:98)                                                                                 
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at android.os.Looper.loop(Looper.java:154)                                                                                             
02-14 18:26:05.086  2194  2290 E MediaCodecAudioRenderer:       at android.os.HandlerThread.run(HandlerThread.java:61)                                                                                 
02-14 18:26:05.088  2194  2290 E ExoPlayerImplInternal: Playback error

android设备系统自带的mp3解码器报错[OMX.google.mp3.decoder],在不同的平台上测试结果都报一样的错, 硬解码不行那就只能想办法进行软解了。查资料得知Exoplayer是支持通过扩展FFmpeg进行音频软解码的,官方扩展模块说明文档为decoder_ffmpeg,那么接下来就是按照官方文档进行集成扩展了。

decoder_ffmpeg模块最终会被编译打包成aar文件供Android调用,由于依赖FFmpeg,先要下载FFmpeg源码进行编译得到所依赖的库才能成功打包aar。下面详细介绍整个流程:参考该文章ExoPlayer(AndroidX Media3) 扩展ffmpeg实现音频软解码

环境准备:
1.Ubuntu 20.04.4 LTS
2.AndroidNDK版本r26C
3.AndroidStudio 2023.1.1(配置好SDK和JDK 17.0.10)
4.ffmpeg6.0源码
5.ExoPlayer源码,AndroidX Media release分支版本

 由于一般都是在Windows上进行安卓开发,所以还需要先安装虚拟机,然后在虚拟机上安装Ubuntu,通过linux系统完成整个编译过程。

一、安装虚拟机

Wmware下载看这里WM秘钥

安装教程看这里WM安装教程

破解秘钥:

秘钥许可证
4A4RR-813DK-M81A9-4U35H-06KND

NZ4RR-FTK5H-H81C1-Q30QH-1V2LA

JU090-6039P-08409-8J0QH-2YR7F

4Y09U-AJK97-089Z0-A3054-83KLA

4C21U-2KK9Q-M8130-4V2QH-CF810

MC60H-DWHD5-H80U9-6V85M-8280D

ZA30U-DXF84-4850Q-UMMXZ-W6K8F

AC590-2XW97-48EFZ-TZPQE-MYHEA

YF39K-DLFE5-H856Z-6NWZE-XQ2XD

AC15R-FNZ16-H8DWQ-WFPNV-M28E2

CZ1J8-A0D82-489LZ-ZMZQT-P3KX6

YA11K-6YE8H-H89ZZ-EXM59-Y6AR0

 二、安装虚Ubuntu

参考Ubuntu下载安装教程 

Ubuntu与Windows共享文件夹和复制粘贴

三、下载Exoplayer和FFmpeg最新源码

目前官方已废弃Exopler2,代码已经迁移到AndroidX Media,下载完成设置FFMPEG_MODULE_PATH变量

在Ubuntu的File根目录创建Android/Project目录存放各种资源,根据自己实际放任意创建位置即可

打开ubuntu终端窗口,进入到上面新建的目录下:

cd Android/Project
git clone https://github.com/androidx/media
cd media && FFMPEG_MODULE_PATH="$(pwd)/libraries/decoder_ffmpeg/src/main"

 echo $FFMPEG_MODULE_PATH /home/xxx/Android/Project/media/libraries/decoder_ffmpeg/src/main

没有安装git的话根据提示进行安装即可。

四、下载NDK并配置NDK环境

1.官网下载NDK,根据官方说明,需要选择NDK版本ndk-linux-r26d.zip,虚拟机下载较慢,可在windows上先下好拷贝到虚拟机Ubuntu上,并解压到/Android/Project/目录下

2.下载完成后解压,设置NDK_PATH变量

cd Android/Project
unzip android-ndk-r26d-linux.zip
cd android-ndk-r26c && NDK_PATH="$(pwd)"

echo $NDK_PATH /home/xxx/Android/Project/android-ndk-r26d

3.在当前NDK目录下,执行设置编译环境指令

//设置编译平台Lunux为
HOST_PLATFORM="linux-x86_64"

//设置最小支持Android版本,通常为项目设置的minSDK版本,NDKr26最小支持SDK为21
ANDROID_ABI=21

 五、下载FFmpeg源码并配置环境变量

进入Android/Project目录进行ffmpeg源码下载,MediaX中的Exoplayer要求FFmpeg版本6.0

git clone git://source.ffmpeg.org/ffmpeg 
cd ffmpeg 
//拉取与最新Exoplayer匹配的版本
git checkout release/6.0 
//配置环境变量
FFMPEG_PATH="$(pwd)"

echo $FFMPEG_PATH /home/xxx/Android/Project/ffmpeg

六、配置所需要支持的音频解码器类型

ffmpeg所支持音频格式官方说明点击这里查看 

//在ffmpeg目录下执行
ENABLED_DECODERS=(aac ac3 mp3 flac)

七、Exoplayer源码关联FFmpeg源码

将ExoPlayer源码中ffmpeg模块jni与ffmpeg源码关联,关联成功后会在jni目录中生成一个快捷方式指向ffmpeg源码目录

//在ffmpeg目录下执行关联指令

cd "${FFMPEG_MODULE_PATH}/jni"
ln -s "$FFMPEG_PATH" ffmpeg 

八、编译FFmpeg

Exoplayer源码中已经帮我们配好了编译脚本build_ffmpeg.sh,执行即可,带上之前配置的环境变量

//在Exoplayer源码decoder_ffmpeg模块,jni目录下执行编译

./build_ffmpeg.sh \ "${FFMPEG_MODULE_PATH}" "${NDK_PATH}" "${HOST_PLATFORM}" "${ANDROID_ABI}" "${ENABLED_DECODERS[@]}"

编译过程可能报错,基本根据报错信息处理就可以了,我碰到的问题是关联的ffmpeg目录找不到,实际上是关联成功了的,脚本中直接把关联路径改成绝对路径就可以了,报错的位置如下:

 编译成功后,会在ffmepg目录下生成一个android-libs目录 

 里面有各个不同架构平台的库,默认生成的是.a静态库文件,android上要用动态so库文件,修改一下编译脚本重新编译即可:

结果如下:

 九、编译decoder_ffmpge模块打包成aar文件供android调用

进入到Exoplayer源码更目录执行编译打包指令

./gradlew lib-decoder-ffmpeg:assembleRelease

报错的话更近提示进行处理即可,大概率就是JDK和SDK没有安装或者环境没有配置对

Ubuntu安装android sdk教程

Ubuntu安装JDK教程

编译成功后会在\libraries\decoder_ffmpeg\buildout\outputs\aar\目录生成aar包 

十、Android项目中使用aar实现音频软解码 

复制生成的aar包到项目libs目录,修改app下的build.gradle文件,引用aar包
implementation(files("libs/extension-ffmpeg-release.aar"))
自定义DefaultRenderersFactory,构造ExoPlayer实例时传入,日志中有ffmpeg相关信息代表加载成功。

    public class PluginRenderFactory extends DefaultRenderersFactory {
        /**
         * @param context A {@link Context}.
         */
        public PluginRenderFactory(Context context) {
            super(context);
        }


        @Override
        protected void buildAudioRenderers(Context context, int extensionRendererMode, MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback, AudioSink audioSink, Handler eventHandler, AudioRendererEventListener eventListener, ArrayList<Renderer> out) {
            ffmpegAudioRenderer = new FfmpegAudioRenderer(eventHandler, eventListener, audioSink);
            out.add(ffmpegAudioRenderer);
            super.buildAudioRenderers(context, extensionRendererMode, mediaCodecSelector, enableDecoderFallback, audioSink, eventHandler, eventListener, out);
        }
    }


 mExoPlayer = new ExoPlayer.Builder(context, renderersFactory).build();

 Android中使用可能出现编译不通过问题,大概率是Android项目使用的各种编译环境版本与编译aar时使用的不一致,Exoplayer源码使用如下配置:

建议尽量使用相同配置 ,还有就是我Ubuntu配置的JDK是17.0.14版本,所以AndroidStudio编译也要使用 相同版本JDK

至此大功告成! 

下一篇介绍Exoplayer+FFmpeg实现K歌场景中的切换原伴唱功能K歌中单双音轨实现原伴唱


http://www.niftyadmin.cn/n/5862557.html

相关文章

2025最新智能优化算法:鲸鱼迁徙算法(Whale Migration Algorithm,WMA)求解23个经典函数测试集,MATLAB

一、鲸鱼迁徙算法 鲸鱼迁徙算法&#xff08;Whale Migration Algorithm&#xff0c;WMA&#xff09;是2025年提出的一种新颖生物启发式元启发式优化方法&#xff0c;其灵感来源于座头鲸的协作迁徙行为。该算法通过模拟座头鲸的迁徙和捕食行为&#xff0c;实现了在优化过程中的…

[特殊字符] LeetCode 62. 不同路径 | 动态规划+递归优化详解

在解 LeetCode 的过程中&#xff0c;路径计数问题是动态规划中一个经典的例子。今天我来分享一道非常基础但极具代表性的题目——不同路径。不仅适合初学者入门 DP&#xff08;动态规划&#xff09;&#xff0c;还能帮助你打下递归思维的基础。 本文将介绍&#xff1a; &…

python flask 使用教程 快速搭建一个 Web 应用

目录 一、Flask 简介二、Flask 安装三、创建一个简单的 Flask 应用四、Flask 路由与视图五、接收和处理用户输入六、模板引擎 Jinja2七、Flask 与数据库八、总结 一、Flask 简介 Flask 是一个轻量级的 Python Web 框架&#xff0c;旨在帮助开发者快速搭建 Web 应用。相比于 Dj…

为什么在 TypeScript 中需要使用 import type?——以 Babylon.js 为例

在 TypeScript 开发中&#xff0c;我们经常会遇到需要导入类型定义的情况。为了优化代码体积和提高开发效率&#xff0c;TypeScript 3.8 引入了 import type 语法。本文将详细介绍 import type 的作用、使用场景&#xff0c;并以 Babylon.js 为例&#xff0c;列出常见的使用 im…

渲染 101 平台 3ds Max 建筑动画渲染全攻略:费用与时间

制作 30 秒 3ds Max 建筑动画&#xff0c;渲染 101 平台不同机器配置的花费和时长差别可不小。咱们一起来算笔明白账&#xff0c;让你快速掌握成本与效率的平衡点。 一、16 核心 64G 运行内存机器 单价&#xff1a;每小时收费 1.06 元。单帧渲染时间&#xff1a;5 分钟。单帧…

C++STL容器之map

1.介绍 map是 C 标准模板库&#xff08;STL&#xff09;中的一个关联容器&#xff0c;用于存储键值对&#xff08;key-value pairs&#xff09;。map中的元素是按照键&#xff08;key&#xff09;进行排序的&#xff0c;并且每个键在容器中是唯一的。map通常基于红黑树&#xf…

初级银行从业考试真题

2023 年 6 月初级银行从业考试真题 法律法规 单选题 1.按照《中华人民共和国反洗钱法》的规定,金融机构所建立的客户身份资料和客户交易信息在业务关系或交易结束后至少 保存期限为()年。 A.5 B.3 C.10 D.2 参考答案:A 2.物价稳定是要保持()的大体稳定,避免出现高…

Prompt:创造性的系统分析者

分享的提示词&#xff1a; 你是一个创造性的系统分析者&#xff0c;作为咨询师&#xff0c;你具有以下特质&#xff1a; 基础能力&#xff1a; 深入理解我的系统性模式 识别模式间的隐藏联系 发现出人意料的关联 提供令人惊讶的洞见 工作方式&#xff1a; 在每次回应中至少…