实现独唱

更新时间: 2022/11/11 09:57:26

独唱是指麦位上的用户独自演唱,房间内的观众在线观看。

功能原理

独唱的原理图如下图所示。

独唱的原理图.png

NERTC SDK 将主唱的伴奏和干声传给 NERTC 服务器, NERTC 服务器将音频传给观众端。

前提条件

已实现加入和离开 RTC 房间。

主唱实现方案

  1. 主唱调用setAudioProfile接口,设置音频 profile 类型为 HighQualityStereo,设置 scenarioMUSIC

  2. 主唱申请上麦,成为连麦主播。具体实现方式请参见 IM 的聊天室队列

  3. 麦位上的用户可以点歌,具体实现逻辑需要业务自行实现。

  4. 歌词展示与同步,具体实现逻辑需要业务自行实现。

  5. 主唱和合唱者在开始合唱前,调用如下代码开启 AEC 伴奏模式。

    开启 AEC 伴奏模式时,本端的人声保留比较好,有助于演唱者的唱歌体验。

    NERtcParameters mRtcParameters = new NERtcParameters();
    NERtcParameters.Key audioMixKey = NERtcParameters.Key.createSpecializedKey("key_audio_external_audio_mix");
    mRtcParameters.set(audioMixKey, true);
    NERtcEx.getInstance().setParameters(mRtcParameters); //先设置参数,后初始化
    
  6. 主唱以主流方式发送伴奏,将伴奏和人声混流后的音频流推送到远端。

    收到歌曲开始消息后,开始 3 秒倒计时,3 秒后开始播放伴奏。

    long position = System.currentTimeMillis() + 3 * 1000;
    NERtcCreateAudioEffectOption optPure = new NERtcCreateAudioEffectOption();
    optPure.path = 纯伴奏音乐路径
    optPure.loopCount = 1;
    optPure.sendEnabled = true;
    optPure.sendVolume = 发送音量;  //如果当前放纯伴奏音乐,将带原唱的伴奏发送音量设成0
    optPure.playbackVolume = 播放音量;  //如果当前放纯伴奏音乐,将带原唱的播放音量设成0
    optPure.sendWithAudioType = NERtcAudioStreamType.kNERtcAudioStreamTypeMain; //伴奏以主流方式发送
    optPure.startTimestamp = position;
    NERtcEx.getInstance().playEffect(optPureEffectId, optPure);  //optPureEffectId 自己定义的 effect id
    
    
    NERtcCreateAudioEffectOption optOriginalSong = new NERtcCreateAudioEffectOption();
    optOriginalSong.path = 带原声音乐路径
    optOriginalSong.loopCount = 1;
    optOriginalSong.sendEnabled = true;
    optOriginalSong.sendVolume = 0; //如果当前播放纯伴奏,将带原唱的伴奏发送音量设置成0
    optOriginalSong.playbackVolume = 0; //如果当前播放纯伴奏音乐,将带原唱的播放音量设置成0
    optOriginalSong.sendWithAudioType = NERtcAudioStreamType.kNERtcAudioStreamTypeMain; //伴奏以主流的方式发送
    optOriginalSong.startTimestamp = position;
    NERtcEx.getInstance().playEffect(optOriginalEffectId, optOriginalSong); //自己定义的effect id
    
    
  7. 歌词同步。

    主唱收到伴奏播放进度回调,并将自己的伴奏进度通过 SEI 发送出去。

    @Override
    public void updateAudioEffectTimestamp(long effectId, long timestampMs) {
    //纯伴奏和带原唱的伴奏,两个进度是一样的,歌词进度只需要根据其中的一个伴奏进行同步
        if(effectId != optOriginalEffectId) {
            return ;
        }
    
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("audio_effect_pos", timestampMs);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        NERtcEx.getInstance().sendSEIMsg(jsonObject.toString());
        dataSource.pickService.musicPostion = timestampMs; //同步本地歌词进度
    }
    
  8. 主唱申请下麦。具体实现方式请参见IM 的聊天室队列

观众端实现方案

观众端通过以下方法同步本地歌词进度。

  1. 观众端监听 onNERtcEngineRecvSEIMsg 的 SEI 回调信息。
  2. 观众收到主唱发送的 SEI 消息,根据拿到的时间戳,解析歌词、展示时间戳对应时间段的歌词数据。
@Override
public void onRecvSEIMsg(long l, String s) {
    long musicPosition = -1;
    try {
        JSONObject data = new JSONObject(s);
        musicPosition = Integer.parseInt(data.getString("audio_effect_pos"));
    } catch (Exception e) {
        e.printStackTrace();
    }
    if(musicPosition == -1) {
        Log.i(TAG, "Error decode SEI message");
        return ;
    }
    dataSource.pickService.musicPosition = musicPosition;
}

进阶功能

静音和取消静音

建议通过以下方式静音和取消静音,以免损耗性能。该设置只影响麦克风采集音量,不影响发送的伴奏音量。

//mute
NERtcEx.getInstance().adjustRecordingSignalVolume(0);
//unmute
NERtcEx.getInstance().adjustPlaybackSignalVolume(100);

切换原唱和伴奏

实现切换播放原唱的示例代码如下:

//将带原唱的伴奏音量调整到正常,并将纯伴奏的伴奏音量调整成 0
NERtcEx.getInstance().setEffectSendVolume(optPureEffectId, 0);
NERtcEx.getInstance().setEffectPlaybackVolume(optPureEffectId, 0);
NERtcEx.getInstance().setEffectSendVolume(optOriginalEffectId, audioEffectVolume);
NERtcEx.getInstance().setEffectPlaybackVolume(optOriginalEffectId, audioEffectVolume);

实现切换为播放伴奏的示例代码如下:

//将带原唱的伴奏音量调整成 0,并将纯伴奏的伴奏音量调整成正常
NERtcEx.getInstance().setEffectSendVolume(optPureEffectId, audioEffectVolume);
NERtcEx.getInstance().setEffectPlaybackVolume(optPureEffectId, audioEffectVolume);
NERtcEx.getInstance().setEffectSendVolume(optOriginalEffectId, 0);
NERtcEx.getInstance().setEffectPlaybackVolume(optOriginalEffectId, 0);
此文档是否对你有帮助?
有帮助
去反馈
  • 功能原理
  • 前提条件
  • 主唱实现方案
  • 观众端实现方案
  • 进阶功能
  • 静音和取消静音
  • 切换原唱和伴奏