独唱
本文介绍如何实现独唱。在此之前,请确保你已参考实现文档集成 KTV API。
方案介绍
独唱场景下存在两种角色:
- 独唱者:加入频道,加载并播放歌曲。KTV API 模块内部控制音乐播放器播放音乐,发布音乐到远端,将音乐播放进度同步到远端,让歌词组件进入歌词滚动状态等逻辑。
- 听众:加入频道,加载歌词。KTV API 模块内部控制听众订阅独唱者的人声和音乐的音频合流,同步独唱者的音乐播放进度,让歌词组件进入歌词滚动状态等逻辑。如果普通听众需要上麦聊天,可以更新媒体选项。
下图为独唱方案的技术原理图:

独唱者实现
1. 加入频道
调用 joinChannelByToken
加入频道。为保证高音质,声网推荐你在加入频道前调用 setAudioProfile
将音频编码属性设为 AgoraAudioProfileMusicHighQuality
,调用 setAudioScenario
将音频场景设为 AgoraAudioScenarioGameStreaming
。
[self.rtcKit joinChannelByToken:<YOUR TOKEN>
channelId:<YOUR CHANNEL NAME>
info:nil
uid:<YOUR UID>
// 媒体选项,详见第 5 步操作
mediaOptions:mediaOption
joinSuccess:nil];
为同步频道内的歌词进度等状态信息,你需要在成功加入频道后调用 renewInnerDataStreamId
来创建数据流通道。如果退出频道后再次加入频道,你需要在加入频道成功后重新调用该方法来创建数据流通道。一个频道中最多只能创建 5 个数据流通道。
2. 加载及播放歌曲
调用 loadMusic
加载歌曲。在调用该方法后需调用 switchSingerRole
将用户角色设为独唱(SoloSinger
),然后调用 startSing
才可以播放歌曲。
如需加载声网提供的版权音乐,请参考获取版权音乐。
KTVSongConfiguration* songConfig = [[KTVSongConfiguration alloc] init];
// 同时加载歌曲和歌词
songConfig.songIdentifier = songIdentifier;
songConfig.mode = KTVLoadMusicModeLoadMusicAndLrc;
songConfig.mainSingerUid = mainSingerUid;
// 歌曲加载失败的原因
- (void)onMusicLoadFailWithSongCode:(NSInteger)songCode reason:(enum KTVLoadSongFailReason)reason {
}
// 歌曲加载成功的回调,在此回调内调用 switchSingerRole 切换角色,调用 startSing 开始播放歌曲
- (void)onMusicLoadSuccessWithSongCode:(NSInteger)songCode lyricUrl:(NSString * _Nonnull)lyricUrl {
// 切换角色
[weakSelf.ktvApi switchSingerRoleWithNewRole:KTVSingRoleSoloSinger
onSwitchRoleState:^(KTVSwitchRoleState state, KTVSwitchRoleFailReason reason) {
// 切换角色状态回调
}];
// 开始播放歌曲
[weakSelf.ktvApi startSingWithSongCode:songCode startPos:0];
}
[self.ktvApi loadMusicWithSongCode:songCode config:songConfig onMusicLoadStateListener:self];
// 歌曲加载进度回调
- (void)onMusicLoadProgressWithSongCode:(NSInteger)songCode
percent:(NSInteger)percent
status:(AgoraMusicContentCenterPreloadStatus)status
msg:(NSString *)msg
lyricUrl:(NSString *)lyricUrl {
}
3. 歌曲结束
当歌曲播放完成或切歌后,你需要调用 switchSingerRole
将用户的角色切回听众。
[self.ktvApi switchSingerRoleWithNewRole:KTVSingRoleAudience
onSwitchRoleState:^(KTVSwitchRoleState state, KTVSwitchRoleFailReason reason) {
}];
4. 关闭麦克风
独唱者停止唱歌或希望暂时关闭麦克风时,可以调用 muteMic(true)
。
[self.ktvApi muteMicWithMuteStatus: true/false];
5. 根据角色更新媒体选项
通过 updateChannelWithMediaOptions
方法在主播加入频道后更新频道媒体选项,例如是否开启本地音频采集,是否发布本地音频流等。
AgoraRtcChannelMediaOptions* options = [AgoraRtcChannelMediaOptions new];
// 发布本地麦克风流
options.publishMicrophoneTrack = YES;
// 启用音频采集和播放
options.enableAudioRecordingOrPlayout = YES;
// 设置角色为主播
options.clientRoleType = AgoraClientRoleBroadcaster;
// 更新媒体选项
[self.RTCKit updateChannelWithMediaOptions:options];
听众实现
1. 加入频道
调用 joinChannelByToken
让听众加入频道。
// 加入频道
[self.rtcKit joinChannelByToken:<YOUR TOKEN>
channelId:<YOUR CHANNEL NAME>
info:nil
uid:<YOUR UID>
// 媒体选项,详见第 3 步操作
mediaOptions:mediaOption
joinSuccess:nil];
2. 加载歌词
调用 loadMusic
加载歌词。听众加入频道后,默认订阅独唱者发布的音频合流,即独唱者人声和音乐混合的音频流,因此只需要加载歌词。
KTVSongConfiguration* songConfig = [[KTVSongConfiguration alloc] init];
// 仅加载歌词
songConfig.songIdentifier = songIdentifier;
songConfig.mode = KTVLoadMusicModeLoadLrcOnly;
songConfig.mainSingerUid = mainSingerUid;
[self.ktvApi loadMusicWithSongCode:songCode config:songConfig onMusicLoadStateListener:self];
// 歌曲加载失败回调
- (void)onMusicLoadFailWithSongCode:(NSInteger)songCode reason:(enum KTVLoadSongFailReason)reason {
}
// 歌曲加载成功回调
- (void)onMusicLoadSuccessWithSongCode:(NSInteger)songCode lyricUrl:(NSString * _Nonnull)lyricUrl {
}
// 歌曲加载进度回调
- (void)onMusicLoadProgressWithSongCode:(NSInteger)songCode
percent:(NSInteger)percent
status:(AgoraMusicContentCenterPreloadStatus)status
msg:(NSString *)msg
lyricUrl:(NSString *)lyricUrl {
}
3. 根据角色更新媒体选项
通过 updateChannelWithMediaOptions
方法在听众加入频道后更新频道媒体选项,例如是否开启本地音频采集,是否发布本地音频流等。
听众的用户角色为 AgoraClientRoleAudience
,因此无法在频道内发布音频流。如果听众想上麦与独唱者语聊,需要将用户角色修改为 AgoraClientRoleBroadcaster
。修改角色后,SDK 默认发布该连麦听众的音频流,独唱者和其他听众都能听到连麦听众的声音。
// 对需要上麦聊天的听众更新媒体选项
AgoraRtcChannelMediaOptions* options = [AgoraRtcChannelMediaOptions new];
// 发布本地麦克风流
options.publishMicrophoneTrack = YES;
// 启用音频采集和播放
options.enableAudioRecordingOrPlayout = YES;
// 设置角色为主播
options.clientRoleType = AgoraClientRoleBroadcaster;
// 更新媒体选项
[self.RTCKit updateChannelWithMediaOptions:options];
// 对未上麦的听众更新媒体选项
AgoraRtcChannelMediaOptions* options = [AgoraRtcChannelMediaOptions new];
// 不发布本地麦克风流
options.publishMicrophoneTrack = NO;
// 启用音频采集和播放
options.enableAudioRecordingOrPlayout = YES;
// 设置角色为观众
options.clientRoleType = AgoraClientRoleAudience;
// 更新媒体选项
[self.RTCKit updateChannelWithMediaOptions:options];
下图展示独唱的 API 调用时序图:
API 参考
本文集成步骤中使用如下 API: