实现独唱
更新时间: 2024/11/26 15:44:05
独唱是指麦位上的用户独自演唱,房间内的观众在线观看。
功能原理
独唱的原理图如下图所示。
NERTC SDK 将主唱的伴奏和干声传给 NERTC 服务器, NERTC 服务器将音频传给观众端。
前提条件
主唱实现方案
-
主唱调用
setAudioProfile
接口,设置音频profile
类型为HighQualityStereo
,设置scenario
为MUSIC
。 -
主唱申请上麦,成为连麦主播。具体实现方式请参见 IM 的聊天室队列。
-
麦位上的用户可以点歌,具体实现逻辑实现需要业务自行实现。
-
下载歌曲文件和并展现歌词,具体实现逻辑需要业务自行实现。
-
主唱和合唱者在开始合唱前,调用如下代码开启 AEC 伴奏模式。
开启 AEC 伴奏模式时,本端的人声保留比较好,有助于演唱者的唱歌体验。
[NERtcEngine.sharedEngine setParameters:@{kNERtcKeyAudioProcessingExternalAudioMixEnable": @YES}];
-
主唱以主流方式发送伴奏,将伴奏和人声混流后的音频流推送到远端。
收到歌曲开始消息后,开始 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
-
歌词同步。
主唱收到伴奏播放进度回调,并将自己的伴奏进度通过 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;//同步本地歌词进度 }
-
主唱申请下麦。具体实现方式请参见 IM 的聊天室队列。
观众端实现方案
观众端通过以下方法同步本地歌词进度。
- 观众端监听
onNERtcEngineRecvSEIMsg
的 SEI 回调信息。 - 观众收到主唱发送的 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];
此文档是否对你有帮助?