Android 音频播放速率调整实现

举报
程思扬 发表于 2022/01/13 01:02:43 2022/01/13
【摘要】 最近接触到的一个项目, 有音频播放、切换播放速率和拖动进度到某处播放的需求 ,由于之前只是见过并没有尝试过切换播放速率 , 于是开始调研并最终实现,下面简单记录一下这次的调研过程。 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;
        }
    };



  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

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

ijkPlayer

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

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

ijkMediaPlayer.setSpeed(2.0f);

  
 
  • 1
  • 2
  • 3

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"));
    }

}



  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149

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

文章来源: chengsy.blog.csdn.net,作者:程思扬,版权归原作者所有,如需转载,请联系作者。

原文链接:chengsy.blog.csdn.net/article/details/99694281

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。