Android 音频倍速探究
系统自带播放器MediaPlayer,虽支持格式较少,但我们项目的mp3音频格式刚好满足,随着时间流失需求变迁,要求音频播放器可控制播放速度
音频播放界面
查阅资料Android6.0开始MediaPlayer增加了音频播放速度功能,以身测试,关键代码
/**
* 倍速播放
* @param speed
*/
public void changePlayerSpeed(float speed) {
// this checks on API 23 and up
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.setPlaybackParams(mMediaPlayer.getPlaybackParams().setSpeed(speed));
} else {
mMediaPlayer.setPlaybackParams(mMediaPlayer.getPlaybackParams().setSpeed(speed));
mMediaPlayer.pause();
}
}
}
真机测试,小米MIX2系统版本Android 8.0.0,测试达预期。华为P20系统版本Android 9,无效,并且播放中调用该方法直接暂停播放。
查遍百度无结果,最终选择ijkplayer(底层基于ffmpeg)来实现音频播放。
ijkplayerGithub官网
- Gradle导入
//ijkplayer引入开始
// required, enough for most devices.
compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
// Other ABIs: optional
compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'
//ExoPlayer as IMediaPlayer: optional, experimental
compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'
//ijkplayer引入结束
MediaPlayer的isPlaying条件 : (1)playing 正在播放
ijkplayer的isPlaying 方法返回为true条件是: (1)prepare or (2)playing 正在播放
下面是c++源码:
if (mp->mp_state == MP_STATE_PREPARED ||
mp->mp_state == MP_STATE_STARTED) {
return true;
}
遇到的坑一:
main, com.fenjiread.learner.player.IJKPlayer.onError(IJKPlayer.java:211)
│ IJKPlayer 播放错误 what is -10000 extra is0
ijkPlayer中的错误码:
IJKMEDIA: SDL_JNI_DetachThreadEnv
ijkplayer如何断掉握手 Android ? ijkplayer如何释放连接 Android ?
/*
* Do not change these values without updating their counterparts in native
*/
int MEDIA_INFO_UNKNOWN = 1;//未知信息
int MEDIA_INFO_STARTED_AS_NEXT = 2;//播放下一条
int MEDIA_INFO_VIDEO_RENDERING_START = 3;//视频开始整备中,准备渲染
int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;//视频日志跟踪
int MEDIA_INFO_BUFFERING_START = 701;//开始缓冲中 开始缓冲
int MEDIA_INFO_BUFFERING_END = 702;//缓冲结束
int MEDIA_INFO_NETWORK_BANDWIDTH = 703;//网络带宽,网速方面
int MEDIA_INFO_BAD_INTERLEAVING = 800;//
int MEDIA_INFO_NOT_SEEKABLE = 801;//不可设置播放位置,直播方面
int MEDIA_INFO_METADATA_UPDATE = 802;//
int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;//不支持字幕
int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;//字幕超时
int MEDIA_INFO_VIDEO_INTERRUPT= -10000;//数据连接中断,一般是视频源有问题或者数据格式不支持,比如音频不是AAC之类的
int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;//视频方向改变,视频选择信息
int MEDIA_INFO_AUDIO_RENDERING_START = 10002;//音频开始整备中
int MEDIA_ERROR_SERVER_DIED = 100;//服务挂掉,视频中断,一般是视频源异常或者不支持的视频类型。
int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;//数据错误没有有效的回收
int MEDIA_ERROR_IO = -1004;//IO 错误
int MEDIA_ERROR_MALFORMED = -1007;
int MEDIA_ERROR_UNSUPPORTED = -1010;//数据不支持
int MEDIA_ERROR_TIMED_OUT = -110;//数据超时
Error (-10000,0)
HTTPS协议不被发现
https://qiniu.fjreading.com/summary/audio/6249f7056312888b799611ad7db60aa6: Protocol not found
继续查
原来 ijkPlayer默认不支持 https 协议的视频,也就是下面这些提供的默认arm依赖不支持https。
官方没有提供现成的so库,需要自己编译支持https协议的so库。
1.准备
下载ijkPlayer源码,下载地址: github.com/Bilibili/ijkplayer
编译之前 首先查看一下是否安装了NDK,没有的请自行安装,下载地址: https://developer.android.google.cn/ndk/downloads/revision_history.html
编译需要的 NDK 最小版本支持 10e,另外作者貌似还没有对NDK15支持
安装NDK之后,要记得在.bash_profile配置 export ANDROID_SDK=”SDK路径” export ANDROID_NDK=”NDK路径”
2.安装需要的程序(在终端输入以下命令)
• 安装homebrew
ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”
• 安装git
brew install git
• 安装yasm
brew install yasm
3.配置文件(终端进入ijkPlayer工程根目录)
有三种文件可供选择
• If you prefer more codec/format
cd config
rm module.sh
ln -s module-default.sh module.sh
• If you prefer less codec/format for smaller binary size (include hevc function)
cd config
rm module.sh
ln -s module-lite-hevc.sh module.sh
• If you prefer less codec/format for smaller binary size (by default)
cd config
rm module.sh
ln -s module-lite.sh module.sh
本来想使用第一种配置文件,支持的类型还多一些,但打出来的so文件11M多,太大了,最后选择了第三种配置文件,打出来so 4M左右.
4.初始化 openssl、ffmpeg(根目录)
./init-android-openssl.sh
./init-android.sh
5.编译
切换到android/contrib目录下(cd android/contrib),执行如下命令 编译so文件
./compile-openssl.sh clean
./compile-ffmpeg.sh clean
./compile-openssl.sh all
./compile-ffmpeg.sh all
其中all 代表所有平台,如果只想编译指定的平台,比如编译armv5 ,则将all改为armv5
6.生成so
切换到android目录下(cd ..),执行如下命令 生成so文件
./compile-ijk.sh all
可更改all为指定版本
生成的so文件可在 ijkplayer/android/ijkplayer/ 下找到
image原文链接
End….
注意:配置NDK路径后,切记要关闭命令行终端再次打开,行为不规范......。
坑二:
通过Android Studio下载的NDK版本为19.xx,官方不支持这么高的版本,需下载NDK版本10~14下载链接
坑三:
需安装Xcode程序
提示未安装Xcode
AppStore下载安装即可,网络一定要给力不然浪费时间,程序5.6G。
安装完成打开提示安装相关组件。
坑四:
提示使用Linux系统来编译,这步真实扯蛋,索性放弃。
最终解决方案:使用七牛播放器
4.4 使用 PLMediaPlayer 实现媒体播放功能
PLDroidPlayer SDK 提供的 PLMediaPlayer
实现了一个媒体播放器的各种基础功能和接口,与 Android 官方的 MediaPlayer
的设计基本保持一致。
关键代码就一行
private PLOnPreparedListener mOnPreparedListener = new PLOnPreparedListener() {
@Override
public void onPrepared(int preparedTime) {
Log.i(TAG, "On Prepared !");
mMediaPlayer.start();
mMediaPlayer.setPlaySpeed(2.0f);
mIsStopped = false;
}
};