跳到主要内容

混音

音视频 SDK 支持两种混音方式:分别是从指定音频文件混音和用户传入音频数据混音。

  • 5.1.11 之前的 SDK,由于底层使用单通道,不支持同时使用两种混音方式。
  • 自 5.1.11 起,支持两种方式同时混音。

前提条件

从网络音源混音依赖 player 插件。SDK 需要使用以下插件将网络文件下载后播放。如有需要,请集成以下插件:

Groovy
dependencies {
// x.y.z 请替换为具体 SDK 版本号;建议使用 SDK 与插件的最新版
...
implementation 'cn.rongcloud.sdk:player:x.y.z' // Player 插件 CDN 扩展库(用于网络音源,可选)
...
}

从音频文件或网络音源混音

混音功能支持将用户自定义的音频数据、音频文件或网络音源与本地麦克风采集的音频数据进行混合。支持的文件/音源格式:MP3、AAC、M4A、WAV。

加入房间并发布默认资源成功后,调用 RCRTCAudioMixer.startMix 方法使用指定的音频文件混音;离开房间前请调用 RCRTCAudioMixer.stop() 结束混音。

Java
String audioFile = "/sdcard/emulated/0/music.mp3";
RCRTCAudioMixer.getInstance().startMix(audioFile, RCRTCAudioMixer.Mode.MIX, true, -1);

// 调节混音音量(对端听到的音量)
RCRTCAudioMixer.getInstance().setMixingVolume(80);
// 调节本地播放音量(本端听到的音量)
RCRTCAudioMixer.getInstance().setPlaybackVolume(80);
// 获取混音文件播放总时长(ms),方法一
RCRTCAudioMixer.getInstance().getDurationMillis();
// 获取混音文件播放总时长(ms),方法二
RCRTCAudioMixer.getInstance().getDurationMillis(String path);
// 获取混音进度,例如 0.2 表示播放了 20%
RCRTCAudioMixer.getInstance().getCurrentPosition();
// 调节混音进度,例如 0.2 表示从 20% 处开始播放
RCRTCAudioMixer.getInstance().seekTo(float position);
// 暂停混音
RCRTCAudioMixer.getInstance().pause();
// 继续混音
RCRTCAudioMixer.getInstance().resume();
// 停止混音
RCRTCAudioMixer.getInstance().stop();
提示
  • 调用之前,应用必须已授予 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 权限。
  • 若 Android 10 手机上已授权仍混音失败,请参考:为什么 Android 10 无法使用 startMix 进行混音?
  • 自 5.2.5.4 起,SDK 支持先设置播放位置(seekTo),再调用开始混音(startMix)。

在混音开始前或进行中均可设置播放位置。若希望从指定位置开始混音,建议先设置播放位置,再调用开始混音。

参数类型说明
pathString文件绝对路径,如 /sdcard/emulated/0/music.mp3;也可为 assets 资源,如 file:///android_asset/music.mp3;若为网络音源则填音源地址
modeRCRTCAudioMixer.Mode混音模式:Mode.MIX 将音频文件与麦克风采集数据混音发送至对端;Mode.REPLACE 将麦克风采集的数据替换为音频文件的音频数据发送至对端;Mode.NONE 不做处理,对端仅听到麦克风声音
playBackboolean是否在本地播放混音音频文件
loopCountintloopCount > 0:循环混音指定次数;loopCount = -1:无限循环;其他取值:混音一次

从音频数据混音

加入房间并发布默认资源成功后,先调用 RCRTCAudioMixer.getInstance().startWrite(),再调用 RCRTCAudioMixer.write 混音原始音频数据;取消发布音频资源或离开房间后,请调用 RCRTCAudioMixer.getInstance().stop() 停止混音。

示例代码:

Java
// 循环写入音频数据
while (keepAlive) {
RCRTCAudioMixer.getInstance().write(pcmData, 48000, 2, AudioFormat.ENCODING_PCM_16BIT, RCRTCAudioMixer.Mode.MIX);
}
// 结束时需要调用 stop 停止混音
RCRTCAudioMixer.getInstance().stop();

混音设置声道

采用上述方式混音时,可以调用 setAudioDualMonoMode 选择混音的左右声道。例如,您可以通过左右声道切换实现原唱/伴唱切换,以适配卡拉 OK 场景(通过声道切换原唱、伴唱要求音源支持,即原唱、伴唱音轨分别位于两个独立声道)。

此接口默认左右声道同时混音,设置后即时生效。

示例代码:

Java
// 当左声道为伴奏音轨,按如下方式调用即可开启卡拉 OK 模式
RCRTCAudioMixer.getInstance().setAudioDualMonoMode(AudioDualMonoMode.AUDIO_DUAL_MONO_L);

设置混音状态监听

可监听开始/暂停/继续/结束混音、混音文件已自动混流完成、实时混音进度等状态监听。

Java
RCRTCAudioMixer.getInstance().setAudioMixingStateChangeListener(new RCRTCAudioMixingStateChangeListener() {
@Override
public void onMixEnd() {
// 自 5.1.4 起废弃
}

@Override
public void onStateChanged(MixingState state) {
// 自 5.1.4 起废弃
}
/**
* 自 5.1.4 起新增
* 混音状态变化
*
* @param state 变更后的状态
* @param reason 状态变更原因
*/
@Override
public void onStateChanged(MixingState state, MixingStateReason reason) {
if (state == MixingState.STOPPED) {
// 混音完成,可能的原因:
if (reason == MixingStateReason.ALL_LOOPS_COMPLETED) {
// 调用 startMix 时传入的 loopCount > 0,且已完成指定次数
} else if (reason == MixingStateReason.ONE_LOOP_COMPLETED) {
// 调用 startMix 且传入的 loopCount < 0(无限循环)或 > 1,完成一次后将自动开始下一次
} else if (reason == MixingStateReason.STOPPED_BY_USER) {
// 调用 stopMix 方法停止混音
}
} else if (state == MixingState.PLAY) {
// 开始混音,可能的原因:
if (reason == MixingStateReason.STARTED_BY_USER) {
// 调用了 startMix 方法
} else if (reason == MixingStateReason.START_NEW_LOOP) {
// 传入的 loopCount < 0(无限循环)或 > 1,自动开始下一次
} else if (reason == MixingStateReason.RESUMED_BY_USER) {
// 调用了 resume 方法继续混音
} else if (reason == MixingStateReason.FILE_LOAD_FINISHED) {
// 本地或网络混音文件加载完成(SDK 必须等待资源加载完成后才能播放混音文件),该回调要求 SDK ≥ 5.2.5.4
}
} else if (state == MixingState.PAUSED) {
// 暂停混音(reason = MixingStateReason.PAUSED_BY_USER)
}
}

/**
* 自 5.1.4 起新增
* 混音播放进度,默认每 200 毫秒回调一次
* @param progress 播放进度 [0, 1]
*/
@Override
public void onReportPlayingProgress(final float progress) {
// 非 UI 线程,更新 UI 需切换线程
}
});

获取混音后的音频数据

通过注册监听 RCRTCEngine.getInstance().getDefaultAudioStream().setMixedAudioDataListener(...) 获取本地混音后的 PCM 音频流。

参数说明:

参数类型说明
ListenerIRCRTCAudioDataListener本地混音后的 PCM 数据采集回调

回调参数:

回调参数回调类型说明
rtcAudioFrameRCRTCAudioFrame混音后的音频 PCM 数据对象

示例代码:

Java
RCRTCEngine.getInstance().getDefaultAudioStream().setMixedAudioDataListener(new IRCRTCAudioDataListener() {
@Override
public byte[] onAudioFrame(RCRTCAudioFrame rcrtcAudioFrame) {
return rcrtcAudioFrame.getBytes();
}
});