基于Agora SDK实现Android端的声动互娱(二)——音乐混动
  GVyI0exYBbD3 2023年11月02日 65 0

有人说避免抖音成瘾的最好方法就是静音播放视频,这从侧面反映了音乐和音效在声动互娱领域的重要性,慷慨激昂的音乐能让烈士的就义更加悲壮,轻松愉快的音乐能使高人的隐居更加惬意。Agora提供了简单易用的SDK让开发者更简便地使用音乐混动(AudioMixing),仅需要上文提到过的RtcEngine类和IRtcEngineEventHandler接口,不需要新增任何实体。


播放背景音乐

首先打开的AndroidManifest.xml,在application的结点最后添加上这两行代码:

<!-- 倒数第二行为了使用明文流量 -->
<!-- 最后一行为了解决分区存储问题 -->
<application
    ……
    android:usesCleartextTraffic="true"
    android:requestLegacyExternalStorage="true">
……
</application>

其中usesCleartextTraffic的作用是使用明文流量传输背景音乐和音效,因为明文流量用于背景音乐等不怕黑客窃听的领域可以节省数据加密造成的损耗;而requestLegacyExternalStorage则是为了适配Android系统的分区存储,让用户可以使用其他音乐播放器下载的背景音乐。

我们只需写一行代码便可以使用Agora傻瓜式的背景音乐混音功能:

// 开始播放音乐文件
mRtcEngine.startAudioMixing(
        filePath, // 指定本地或在线音乐文件的路径
        false, // 设置是否只在本地播放音乐文件。false 表示本地用户和远端用户都能听到音乐。
        0, // 音乐文件的播放次数,0表示不播放,-1表示无限循环
        0 // 音乐文件的播放位置,单位为毫秒
);

我来解释一下其中第一个参数的含义,Agora的开发团队全面考虑了Android开发者的需求,这个String类型的写法和Glide的load()方法参数为String时一致,可以填入在线音乐文件的URL路径(http://或https://打头),也可以填入开发者在apk中预制的音乐文件的路径(assets://打头);当然更支持用户手机中的音乐文件的路径(file://打头),不过使用绝对路径可能会遇到缺少文件权限或者分区存储权限的问题,所以建议使用ContentProvider访问本机文件(content://打头)


背景音乐的异常处理

如果需要回调的话,我们就在刚才的IRtcEngineEventHandler()内部类中override这几个方法

private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
    ……
    // 该回调在音乐文件播放状态发生改变时触发,并报告当前的播放状态(state)和错误码(errorCode)
    @Override
    public void onAudioMixingStateChanged(int state, int errorCode) {
        super.onAudioMixingStateChanged(state, errorCode);
    }

    // 该回调在音乐文件播放位置(精确到ms)发生改变时触发
    @Override
    public void onAudioMixingPositionChanged(long position) {
        super.onAudioMixingPositionChanged(position);
    }

    // 该回调在音乐文件播放结束时触发
    @Override
    public void onAudioMixingFinished() {
        super.onAudioMixingFinished();
    }

    ……
};

其中onAudioMixingStateChanged()回调方法的两个参数的值都在io.agora.rtc2. Constants文件中:

/**
 * 代码来自 {@link io.agora.rtc2.Constants}
 */
// state的取值
// 音乐文件正在正常播放
public static final int AUDIO_MIXING_STATE_PLAYING = 710;
// 音乐文件暂停播放
public static final int AUDIO_MIXING_STATE_PAUSED = 711;
// 音乐文件停止播放
public static final int AUDIO_MIXING_STATE_STOPPED = 713;
// 音乐文件报错
public static final int AUDIO_MIXING_STATE_FAILED = 714;

// errorCode的取值
// 正常
public static final int AUDIO_MIXING_REASON_OK = 0;
// 音乐文件打开出错
public static final int AUDIO_MIXING_REASON_CAN_NOT_OPEN = 701;
// 音乐文件打开太频繁
public static final int AUDIO_MIXING_REASON_TOO_FREQUENT_CALL = 702;
// 音乐文件播放异常中断
public static final int AUDIO_MIXING_REASON_INTERRUPTED_EOF = 703;
// 音乐文件完成一次循环播放
public static final int AUDIO_MIXING_REASON_ONE_LOOP_COMPLETED = 721;
// 音乐文件完成所有循环播放
public static final int AUDIO_MIXING_REASON_ALL_LOOPS_COMPLETED = 723;
// 成功调用 pauseAudioMixing 暂停播放音乐文件
public static final int AUDIO_MIXING_REASON_STOPPED_BY_USER = 724;

我来解释一下这几种异常的成因,并非Agora出bug导致的,感兴趣的朋友们可以在自己实践中手动触发这几种错误:AUDIO_MIXING_REASON_CAN_NOT_OPEN(701)的触发方式就是你把一个随便什么不是音乐文件的文件(比如.txt啦、.png啦之类的)的扩展名改成Agora支持的文件格式(比如.mp3啦、.aac啦之类的),然后调用startAudioMixing()方法;而AUDIO_MIXING_REASON_INTERRUPTED_EOF(703)的触发方式则是你在播放音乐的时候让队友给你打个电话。


然后onAudioMixingPositionChanged()的触发条件其中之一是开始播放的时候返回开始播放的时刻,就是startAudioMixing()方法的最后一个参数;另一个触发条件是调用resumeAudioMixing()方法时返回回复播放的时刻;还有一个被动触发条件是播放中会返回播放中的时刻,当然并不是每毫秒都会返回,我暂时还没搞懂这个方法被动触发的逻辑;当然我们可以调用setAudioMixingPosition()手动触发


背景音乐混动的其他方法

因为篇幅有限,暂停、恢复、停止等和背景音乐有关的其他方法不做文字介绍,好在Agora的开发团队命名通俗易懂:

//以下方法仅能在调用startAudioMixing()方法并收到onAudioMixingStateChanged(AUDIO_MIXING_STATE_PLAYING) 回调后调用
/**
 * 当前音频文件的声道模式
 * 详见{@link Constants.AudioMixingDualMonoMode}
 * 0-原始模式,1-左声道模式,2-右声道模式,3-混合模式
 * 这个方法建议用耳机体验,扬声器效果不明显
 */
// mRtcEngine.setAudioMixingDualMonoMode(Constants.AudioMixingDualMonoMode.AUDIO_MIXING_DUAL_MONO_AUTO);

// 调整本地播放的音乐文件的音调
// 默认值为 0,即不调整音调。取值范围为 [-12,12],每相邻两个值的音高距离相差半音
// mRtcEngine.setAudioMixingPitch(0);

// 设置音乐文件的播放位置
// mRtcEngine.setAudioMixingPosition(0);

// 暂停音乐文件
public void pauseMusic(){
    mRtcEngine.pauseAudioMixing();
}

// 恢复播放音乐
public void resumeMusic(){
    mRtcEngine.resumeAudioMixing();
}

// 停止播放音乐
public void stopMuisc(){
    mRtcEngine.stopAudioMixing();
}

private int musicVolume = 50;

// 音乐音量+
public void musicVolumeUp(){
    musicVolume++;
    mRtcEngine.adjustAudioMixingVolume(musicVolume);
    // 调节当前音乐文件在对方那边的播放音量
    // mRtcEngine.adjustAudioMixingPublishVolume(musicVolume);
    // 调节当前音乐文件在自己这边的播放音量
    // mRtcEngine.adjustAudioMixingPlayoutVolume(musicVolume);
}

// 音乐音量-
public void musicVolumeDown(){
    musicVolume--;
    mRtcEngine.adjustAudioMixingVolume(musicVolume);
}

最后我们以一个欢乐的视频结束本文,视频里主画面(我的正脸)是对方视角,副画面(我的侧脸)是本人视角

【视频】

我们接下来学习的内容是如何使用音效(Audio Effect)

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
GVyI0exYBbD3