Android 音频播放速率调整实现
【摘要】
最近接触到的一个项目, 有音频播放、切换播放速率和拖动进度到某处播放的需求 ,由于之前只是见过并没有尝试过切换播放速率 , 于是开始调研并最终实现,下面简单记录一下这次的调研过程。
MediaPlaye...
最近接触到的一个项目, 有音频播放、切换播放速率和拖动进度到某处播放的需求 ,由于之前只是见过并没有尝试过切换播放速率 , 于是开始调研并最终实现,下面简单记录一下这次的调研过程。
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 的设计基本保持一致。
关键代码就一行
```java
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以下的设备上测试过。
文章来源: chengsy.blog.csdn.net,作者:程思扬,版权归原作者所有,如需转载,请联系作者。
原文链接:chengsy.blog.csdn.net/article/details/99694281
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)