实现独唱

更新时间: 2022/11/11 09:59:06

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

功能原理

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

独唱的原理图.png

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

前提条件

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

主唱实现方案

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

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

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

  4. 下载歌曲文件和并展现歌词,具体实现逻辑需要业务自行实现。

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

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

    [NERtcEngine.sharedEngine setParameters:@{kNERtcKeyAudioProcessingExternalAudioMixEnable": @YES}];
    
  6. 主唱以主流方式发送伴奏,将伴奏和人声混流后的音频流推送到远端。

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

    SInt64 position = ([NSDate date].timeIntervalSince1970)* 1000 + 3 * 1000; //3 秒后开始播放伴奏
    NERtcCreateAudioEffectOption *optPure = [[NERtcCreateAudioEffectOption alloc] init];
    optPure.path = 纯伴奏音乐路径
    optPure.loopCount = 1;
    optPure.sendEnabled = YES;
    optPure.sendVolume = 发送音量; 
    optPure.playbackVolume = 播放音量;
    optPure.sendWithAudioType = kNERtcAudioStreamTypeMain; //伴奏以主流方式发送
    optPure.startTimeStamp = position;
    [NERtcEngine.sharedEngine playEffectWitdId:kEffectIdPureAccompantment effectOption:optPure]; // kEffectIdPureAccompantment  自己定义effect id
    
    NERtcCreateAudioEffectOption *optOriginalSong = [[NERtcCreateAudioEffectOption alloc] init];
    optOriginalSong.path = 原唱伴奏音乐路径
    optOriginalSong.loopCount = 1;
    optOriginalSong.sendEnabled = YES;
    optOriginalSong.sendVolume = 0; //如果当前放纯伴奏音乐,将带原唱的伴奏发送音量设成0
    optOriginalSong.playbackVolume = 0; //如果当前放纯伴奏音乐,将带原唱的伴奏发送音量设成0
    optOriginalSong.sendWithAudioType = kNERtcAudioStreamTypeMain; //伴奏以主流方式发送
    optOriginalSong.startTimeStamp = position;
    [NERtcEngine.sharedEngine playEffectWitdId:kEffectIdOriginalSong effectOption:optOriginalSong]; // kEffectIdOriginalSong  自己定义effect id
    
  7. 歌词同步。

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

    - (void)onAudioEffectTimestampUpdateWithId:(uint32_t)effectId timeStampMS:(uint64_t)timeStampMS {
        //纯伴奏和带原唱的伴奏,两个进度是一样的,歌词进度只需根据其中一个音效的进度进行同步
        if(effectId != kEffectIdPureAccompantment) 
            return;    
        
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        dict[kAudioMixingPos] = @(timeStampMS);
        NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
        [NERtcEngine.sharedEngine sendSEIMsg:data];
        self.dataSource.pickService.musicPosition = timeStampMS;//同步本地歌词进度
    }
    
  8. 主唱申请下麦。具体实现方式请参见 IM 的聊天室队列

观众端实现方案

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

  1. 观众端监听 onNERtcEngineRecvSEIMsg 的 SEI 回调信息。
  2. 观众收到主唱发送的 SEI 消息,根据拿到的时间戳,解析歌词、展示时间戳对应时间段的歌词数据。
- (void)onNERtcEngineRecvSEIMsg:(uint64_t)userID message:(NSData *)message {
    NSError *error;
    NSDictionary *JSONObject = [NSJSONSerialization JSONObjectWithData:message options:0 error:&error];
    if (error) {
        return NELPLogError(@"Error decode SEI message: %@", error);
    }
    self.musicPosition = (uint32_t)[JSONObject[kAudioMixingPos] integerValue] + 50;
    self.dataSource.pickService.musicPosition = self.musicPosition;//同步本地歌词进度
}

进阶功能

主唱、合唱者静音和取消静音

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

//mute
[[NERtcEngine sharedEngine] adjustRecordingSignalVolume:0];
//unmute
[[NERtcEngine sharedEngine] adjustRecordingSignalVolume:100];

切换原唱和伴奏

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

//将带原唱的音量调整到正常,并将纯伴奏的音量调整成 0
[NERtcEngine.sharedEngine setEffectSendVolumeWithId:kEffectIdPureAccompantment volume:0];
[NERtcEngine.sharedEngine setEffectPlaybackVolumeWithId:kEffectIdPureAccompantment volume:0];
[NERtcEngine.sharedEngine setEffectSendVolumeWithId:kEffectIdOriginalSong volume:audioMixingVolume];
[NERtcEngine.sharedEngine setEffectPlaybackVolumeWithId:kEffectIdOriginalSong volume:audioMixingVolume];

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

//将带原唱的音量调整成 0,并将纯伴奏的音量调整成正常
[NERtcEngine.sharedEngine setEffectSendVolumeWithId:kEffectIdPureAccompantment volume:audioMixingVolume];
[NERtcEngine.sharedEngine setEffectPlaybackVolumeWithId:kEffectIdPureAccompantment volume:audioMixingVolume];
[NERtcEngine.sharedEngine setEffectSendVolumeWithId:kEffectIdOriginalSong volume:0];
[NERtcEngine.sharedEngine setEffectPlaybackVolumeWithId volume:0];
此文档是否对你有帮助?
有帮助
去反馈
  • 功能原理
  • 前提条件
  • 主唱实现方案
  • 观众端实现方案
  • 进阶功能
  • 主唱、合唱者静音和取消静音
  • 切换原唱和伴奏