自定义views 多媒体科技

Android 音频倍速探究

2019-03-11  本文已影响22人  IT枫

系统自带播放器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官网

音频开发ijkplayer小结 android

  1. 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。

ijlPlayer的so库
官方没有提供现成的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;
        }
    };
上一篇下一篇

猜你喜欢

热点阅读