最近接触到的一个项目, 有音频播放、切换播放速率和拖动进度到某处播放的需求 ,由于之前只是见过并没有尝试过切换播放速率 , 于是开始调研并最终实现,下面简单记录一下这次的调研过程。

  • MediaPlayer

播放音频最先想到的就是MediaPlayer这个Android提供的原生API了,在Android 6.0+(23+)MediaPlayer可以通过setSpeed来改变播放速率

在代码中,我们需要:

// 设置音乐播放速度
public static void changeplayerSpeed(float speed) {
if (mPlayer == null) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// API 23 (6.0)以上 ,通过设置Speed改变音乐的播放速率
if (mPlayer.isPlaying()) {
// 判断是否正在播放,未播放时,要在设置Speed后,暂停音乐播放
mPlayer.setPlaybackParams(mPlayer.getPlaybackParams().setSpeed(speed));
} else {
mPlayer.setPlaybackParams(mPlayer.getPlaybackParams().setSpeed(speed));
mPlayer.pause();
}
} else {
// 在Android6.0以前,需要另想办法处理,后续查到好的方法再补充
}
}

实际实现过程中 ,我发现手上的测试机Honor V9执行该操作后 ,播放静默了 ,不仅没有实现播放速率的切换,播放也不能恢复。无奈,只好另寻他法。

  • PLMediaPlayer 

PLDroidPlayer是七牛SDK提供的一套API, PLMediaPlayer实现了一个媒体播放器的各种基础功能和接口,与 Android 官方的 MediaPlayer 的设计基本保持一致。

关键代码就一行

    private PLOnPreparedListener mOnPreparedListener = new PLOnPreparedListener() {
@Override
public void onPrepared(int preparedTime) {
Log.i(TAG, "On Prepared !");
mMediaPlayer.start();
       //设置播放速率为2x
mMediaPlayer.setPlaySpeed(2.0f);
mIsStopped = false;
}
};

实际实现过程中 ,播放速率切换正常,但seekTo操作大概率失效,于是去github上查探究竟,发现仍存在该问题的ISSUE,遂放弃。

  • ijkPlayer

ijkplayer是b站基于ffplay的轻量级Android/iOS视频播放器,实现了跨平台的功能,API易于集成;编译配置可裁剪,方便控制安装包大小。

ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", 1);
ijkMediaPlayer.setSpeed(2.0f);

api和用法类似mediaplayer,关键代码也是只有一行。

实际实现过程中 ,seekTo正常,播放速率切换也正常(只是在切换到慢速0.5x的时候存在重音的情况),但是播放不了https开头url的音频文件,搜索了一下需要自己编译ijkplayer源码以支持https,遂放弃。

  • ExoPlayer

 最终选择的是google的exoPlayer来实现,api类似MediaPlayer,但也有些差异,下面贴出关键播放控制部分的代码。

package com.weex.app.media;

import android.content.Context;
import android.net.Uri; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util; import java.io.File; public class AudioPlayerManager { private static final String TAG = "AudioPlayerManager";
public static Float[] speedArray = new Float[]{1.0f, 1.25f, 1.75f, 0.5f, 0.75f};
private static AudioPlayerManager instance;
private Context context;
private SimpleExoPlayer mediaPlayer;
private DataSource.Factory dataSourceFactory; private AudioPlayerManager(Context context) {
this.context = context;
createPlayer();
} public static AudioPlayerManager getInstance(Context context) {
synchronized (AudioPlayerManager.class) {
if (instance == null) {
instance = new AudioPlayerManager(context);
}
} return instance;
} public ExoPlayer getMediaPlayer() {
return mediaPlayer;
}
  //设置播放url
public void setAudioUrl(String audioUrl) {
try {
//这是一个代表将要被播放的媒体的MediaSource
MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(audioUrl));
mediaPlayer.prepare(mediaSource);
mediaPlayer.setPlayWhenReady(false);
} catch (Exception e) {
e.printStackTrace();
}
}
  //设置播放file
public void setAudioFile(File file) {
try {
//这是一个代表将要被播放的媒体的MediaSource
MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.fromFile(file));
mediaPlayer.prepare(mediaSource);
mediaPlayer.setPlayWhenReady(false);
} catch (Exception e) {
e.printStackTrace();
}
}
  //开始播放
public void start() {
mediaPlayer.setPlayWhenReady(true);
}
  //判断是否是播放状态
public boolean isPlaying() {
int playbackState = mediaPlayer.getPlaybackState();
if (playbackState == SimpleExoPlayer.STATE_READY && mediaPlayer.getPlayWhenReady()) {
return true;
}
return false;
}
  //播放,带回调事件
public void playWithCompletionListener(String url, Player.EventListener listener) {
if (listener != null) {
mediaPlayer.addListener(listener);
}
if (url.startsWith("http")) {
setAudioUrl(url);
} else {
setAudioFile(new File(url));
}
mediaPlayer.setPlayWhenReady(true);
}
  //播放or暂停
public void playOrPause() {
if (isPlaying()) {
mediaPlayer.setPlayWhenReady(false);
} else {
mediaPlayer.setPlayWhenReady(true);
}
}
  //切换播放速率
public void switchSpeed(int speedIndex) {
// API 23 (6.0)以上 ,通过设置Speed改变音乐的播放速率
if (isPlaying()) {
// 判断是否正在播放,未播放时,要在设置Speed后,暂停音乐播放
getMediaPlayer().setPlaybackParameters(new PlaybackParameters(speedArray[speedIndex]));
} else {
getMediaPlayer().setPlaybackParameters(new PlaybackParameters(speedArray[speedIndex]));
getMediaPlayer().setPlayWhenReady(false);
}
}
  //停止播放
public void stop(boolean reset) {
if (mediaPlayer != null) {
mediaPlayer.stop(reset);
}
}
  //释放资源
public void release() {
if (mediaPlayer != null) {
mediaPlayer.release();
}
} //创建一个新的player
private void createPlayer() {
// 创建带宽
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
// 创建轨道选择工厂
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
// 创建轨道选择器实例
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
//step2.创建播放器
mediaPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
//创建一个DataSource对象,通过它来下载多媒体数据
dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, "loader"));
} }

实际自测过程中,表现正常,而且切换播放速率时,没有重(chong)音的情况,但没有在6.0以下的设备上测试过。

Android 音频播放速率调整实现的更多相关文章

  1. Android音频播放之SoundPool

    SoundPool 一.基本概念 在Android应用程序的开发过程中,经常需要播放多媒体文件,也许最先想到的会是MediaPlayer类了,该类提供了播放.暂停.停止及重复播放等功能性方法(该类位于 ...

  2. android 音频播放总结 soundlPool,MediaPlay

    soundlPool 用于小音频的播放多个同时播放. 使用步骤: 步骤一: 首先下载音频文件可以将其放入assets文件夹下或者res下的raw文件夹下,区别在于assets下可以再新建文件夹二raw ...

  3. Android 音频播放分析笔记

    AudioTrack是Android中比较偏底层的用来播放音频的接口,它主要被用来播放PCM音频数据,和MediaPlayer不同,它不涉及到文件解析和解码等复杂的流程,比较适合通过它来分析Andro ...

  4. Android音频播放之SoundPool 详解

    SoundPool —— 适合短促且对反应速度比较高的情况(游戏音效或按键声等) 下面介绍SoundPool的创建过程: 1. 创建一个SoundPool (构造函数) public SoundPoo ...

  5. Android音频播放实例

    MediaPlayer: 此类适合播放较大文件,此类文件应该存储在SD卡上,而不是在资源文件里,还有此类每次只能播放一个音频文件. 1.从资源文件中播放 MediaPlayer player = ne ...

  6. Android MediaPlayer 音频倍速播放,调整播放速度

    本文链接: Android MediaPlayer 倍速播放,调整播放速度 现在市面上的很多音视频App都有倍速播放的功能,例如把播放速度调整为0.5.1.5.2倍等等. 从Android API 2 ...

  7. Android MediaPlayer播放一般音频与SoundPool播放短促的音效

    [1]使用MediaPlayer实现一般的音频播放 MediaPlayer播放通常的音频文件 MediaPlayer mediaPlayer = new MediaPlayer(); if (medi ...

  8. 【转】解决在Android设备播放音频与其他应用重音的问题,并监听耳机的控制按钮

    概述 在安卓开发中免不了需要播放一点音乐了,音频了.但是这时候有别的应用正在播放,这时候就会出现重音的现象,完全影响用户体验,我们的项目就遇上了这样的尴尬,然后查找了一些文档,记录一下: 管理音频焦点 ...

  9. 【Android】播放音频的几种方式介绍

    接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类: 1.使用MediaPl ...

随机推荐

  1. MySQL数据库备份之xtrabackup工具使用

    一.Xtrabackup备份介绍及原理 二.Xtrabackup的安装 1.在centos7上基于yum源安装percona-xtrabackup软件 [root@node7 ~]# yum -y i ...

  2. 阶段5 3.微服务项目【学成在线】_day18 用户授权_18-微服务之间认证-需求分析

    4.1 需求分析 前边章节已经实现了用户携带身份令牌和JWT令牌访问微服务,微服务获取jwt并完成授权. 当微服务访问微服务,此时如果没有携带JWT则微服务会在授权时报错. 测试课程预览: 1.将课程 ...

  3. JavaScript正则表达式补充

    定义正则表达式 /.../用于定义正则表达式 /.../g表示全局匹配 /.../i表示不区分大小写 /.../m表示多行匹配 JS正则匹配时本身就是支持多行,此处多行匹配只是影响正则表达式^和$,m ...

  4. DB2中的NVL和NVL2函数

    NVL函数是一个空值转换函数 NVL(表达式1,表达式2) 如果表达式1为空值,NVL返回值为表达式2的值,否则返回表达式1的值. 该函数的目的是把一个空值(null)转换成一个实际的值.其表达式的值 ...

  5. 使用sort,uniq去重并统计出现次数

    测试文档test 1 2 3 4 1 2 1 1 sort把相同的放在一起 [root@salt-test ~]# sort test 1 1 1 1 2 2 3 4 uniq -c统计出现的次数 [ ...

  6. 最新 创蓝253java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.创蓝253等10家互联网公司的校招Offer,因为某些自身原因最终选择了创蓝253.6.7月主要是做系统复习.项目复盘.Le ...

  7. 49.Django起步学习

    django起步 django安装 pip install django==2.0.4(版本号) pip install django 默认安装最新版本 创建项目 django-admin start ...

  8. 怎么通过外网来访问自己在Tomcat服务器中配置的项目

    目前还没有试验过 https://blog.csdn.net/qingyisuo/article/details/80086105

  9. Hbuider APP打包流程

      1,下载HBuilder,注册并登陆.首先打开“文件”-“新建”-“移动APP”,输入“应用名称”,“位置”可以根据需要自己选择即可,“选择模板”建议选择空模板: 2,新建完成后, 在项目管理器会 ...

  10. 从MongoDB及mysql 谈B/B+树

    一 B树的由来 B树指的是一类树,包括B-树,B+树,B*树等,是一种自平衡的搜索树,它类似普通的平衡二叉树,不同的一点是B树允许每个节点有更多的子节点.B树是专门为外部存储器设计的,如磁盘,它对于读 ...