ZEGO 版权内容中心,提供了在线 K 歌场景所需歌曲内容。内容由音乐合作的版权方提供,如需进一步了解版权内容中心,请联系 ZEGO 商务人员咨询。
本文将介绍如何快速实现在线 KTV 场景下搜索、下载和播放正版曲库歌曲的流程。
下载 示例源码,体验 ZEGO 在线 KTV 版权音乐点歌功能。
在实现基本的版权音乐功能之前,请确保:
SDK 支持 Token 鉴权。若您需要升级鉴权方式,可参考 如何从 AppSign 鉴权升级为 Token 鉴权。
用户实现点歌并播放的基本流程如下图:
"/top/song"
可获取到当前热门的歌曲列表。步骤 1:调用 createEngineWithProfile 初始化 SDK。
初始化 ZEGO Express SDK 时,内部处理的操作较多,建议用户在 App 启动时候进行。详情参考:实时语音 - 快速开始 - 实现流程。
/** 引入 ZegoExpressEngine.h 头文件 */
#import <ZegoExpressEngine/ZegoExpressEngine.h>
@property (nonatomic, strong) ZegoExpressEngine *engine;
/** 1. 创建 ZegoExpressEngine 对象 */
ZegoEngineProfile *profile = [ZegoEngineProfile new];
// 请通过官网注册获取,格式为:1234567890
profile.appID = appID;
// 请通过官网注册获取,格式为:@"0123456789012345678901234567890123456789012345678901234567890123"(共64个字符)
// 如果使用 token 鉴权,不需要配置此参数
profile.appSign = appSign;
// KTV场景接入
profile.scenario = ZegoScenarioKaraoke;
// 创建引擎,并注册 self 为 eventHandler 回调。不需要注册回调的话,eventHandler 参数可以传 nil,后续可调用 "-setEventHandler:" 方法设置回调
self.engine = [ZegoExpressEngine createEngineWithProfile:profile eventHandler:self];
步骤 2(可选):调用 loginRoom 登录房间。
/** 2. 登录房间*/
// 此步骤对于使用 **appSign** 鉴权的开发者而言,此步骤为 **可选** 步骤;对于使用 **token** 鉴权的开发者,此步骤为 **必需** 步骤。/
- (void)loginRoom {
// roomID 由您本地生成,需保证 “roomID” 全局唯一。不同用户要登录同一个房间才能进行通话
NSString *roomID = @"room1";
// 创建用户对象,ZegoUser 的构造方法 userWithUserID 会将 “userName” 设为与传的参数 “userID” 一样。“userID” 与 “userName” 不能为 “nil”,否则会导致登录房间失败。
// userID 由您本地生成,需保证 “userID” 全局唯一。
ZegoUser *user = [ZegoUser userWithUserID:@"user1"];
// 只有传入 “isUserStatusNotify” 参数取值为 “true” 的 ZegoRoomConfig,才能收到 onRoomUserUpdate 回调。
ZegoRoomConfig *roomConfig = [[ZegoRoomConfig alloc] init];
// token 由用户自己的服务端生成,为了更快跑通流程,也可以通过 ZEGO 控制台 https://console.zego.im/dashboard 获取临时的音视频 token
roomConfig.token = @"<#token#>"; // 如果使用appSign 鉴权,登录房间不需要此参数
roomConfig.isUserStatusNotify = YES;
// 登录房间
[[ZegoExpressEngine sharedEngine] loginRoom:roomID user:user config:roomConfig callback:^(int errorCode, NSDictionary * _Nullable extendedData) {
// (可选回调) 登录房间结果,如果仅关注登录结果,关注此回调即可
if (errorCode == 0) {
NSLog(@"房间登录成功");
} else {
// 登录失败,请参考 errorCode 说明 https://doc-zh.zego.im/article/4377
NSLog(@"房间登录失败");
}
}];
}
步骤 3:调用 createCopyrightedMusic 创建版权音乐对象。
/** 定义 CopyrightedMusic 对象 */
@property (nonatomic, strong) ZegoCopyrightedMusic *copyrightedMusic;
/** 3. 创建 CopyrightedMusic 对象 */
self.copyrightedMusic = [[ZegoExpressEngine sharedEngine] createCopyrightedMusic];
/** 设置版权音乐回调 */
[self.copyrightedMusic setEventHandler:self];
步骤 4:调用 initCopyrightedMusic 初始化版权音乐对象。
/** 4. 初始化版权音乐对象 */
ZegoCopyrightedMusicConfig *config = [ZegoCopyrightedMusicConfig new];
// 这里的 userID 和 userName 应该和登录房间的 userID 和 userName 保持一致。
ZegoUser *user = [ZegoUser userWithUserID:userID userName:userName];
config.user = user;
[self.copyrightedMusic initCopyrightedMusic:config callback:^(int errorCode) {
if (errorCode == 0) {
NSLog(@"创建的版权音乐对象 initCopyrightedMusic 初始化成功");
}
else {
NSLog(@"创建的版权音乐对象 initCopyrightedMusic 初始化失败,错误码 = %d",errorCode);
}
}];
用户可用以下三种方式获取歌曲列表:
方法 | 具体说明 |
---|---|
第 1 种:先获取标签列表,然后通过标签获取歌曲列表 |
|
第 2 种:通过搜索获取 |
通过用户传入关键字搜索歌曲(/search/song)。 |
第 3 种:通过榜单获取 |
获取榜单列表(/top/song)。 |
如下介绍如何使用第 1 种获取歌曲列表的方法:
调用 sendExtendedRequest 接口,command 传入 "/tag/list"
,params 传入 "{vendor_id:xx}",即版权方 ID(具体信息请联系 ZEGO 技术支持),在回调中获取到标签列表。
sendExtendedRequest 接口完整参数与返回结果的说明请参考 发送扩展请求接口说明。
选择某个标签,调用 sendExtendedRequest 接口,command 传入 "/tag/song"
,params 传入下列 JSON 格式的字符串,即可在回调中获取到歌曲列表。
JSON 格式如下:
{
"tag_id": "587", // 从步骤 1 的标签列表回调中选择
"page": 1,
"filter": [1],
"vendor_id": 0
}
示例代码:
// 下面以通过标签获取歌曲列表为例
NSString *command = @"/tag/song"; // command 参数代表您请求的业务指令,该示例为通过标签获取歌曲
NSString *params = @"{ \"vendor_id\": 0, \"tag_id\": \"587\", \"page\": 1, \"filter\": [1]}"; // params 参数,是 JSON 格式的字符串,需要您传入的额外参数
[self.copyrightedMusic sendExtendedRequest:command params:params callback:^(int errorCode, NSString * _Nonnull command, NSString * _Nonnull result) {
// command 参数代表您请求的业务指令
// result 回调结果,JSON 格式字符串
}];
在获得的歌曲列表中,每首歌曲都有对应的 copyright 字段,表示这个歌曲的版权信息。
copyright 的结构如下:
//该字段位于 result.data.songs[i].copyright
{
"song_lyric": 0,
"recording": 1,
"channel": 0
}
具体字段说明如下:
字段 | 说明 |
---|---|
song_lyric |
|
recording |
|
channel |
歌曲渠道。
|
不同版权方对应的歌曲资源不同、资源的有效时长也不同。
ZEGO 目前仅支持按点歌次数计费,即每调用一次 requestResource 接口,都会计一次费。不同版权方的计费方式不同:
版权方的详细信息(歌曲资源、资源有效时长、计费方式等),请联系 ZEGO 商务咨询。
如果包含人声的歌曲资源有版权,可以调用 requestResource 接口获取到歌曲的资源信息,包括歌曲名、歌曲时长、resourceID 等,接口具体回调的信息参考 获取歌曲与歌词资源接口说明。
字段 | 功能 | 该字段在回调结果中的获取方式 |
---|---|---|
resource_id |
一个 songID 对应的歌曲可能对应有多个不同的音质资源(如标清、高清、无损),因此需要定义 resource_id 来唯一对应每一个资源。可用于下载歌曲(调用 download 接口)。 |
result.resources[0].resource_id |
// recording 为 1 代表该首歌有包含人声的歌曲的版权
if (recording == 1) {
/** 配置 */
ZegoCopyrightedMusicRequestConfig *config = [ZegoCopyrightedMusicRequestConfig new];
/** 音乐 songID,从歌曲列表中获取*/
config.songID = songID;
/** 计费模式,请联系 ZEGO 商务咨询 */
config.mode = ZegoCopyrightedMusicBillingModeCount;
/** 版权方,其对应的枚举值信息,请联系 ZEGO 商务咨询*/
config.vendorID = ZegoCopyrightedMusicVendorDefault;
/** 场景 ID:1 语聊房、2 直播间在线 K 歌、3 直播间播放背景音乐、4 抢唱*/
/** 请联系 ZEGO 商务开通使用场景,使用过程请传入正确的场景 ID。*/
config.sceneID = 0;
/**
* 资源类型包含:
* ZegoCopyrightedMusicResourceSong:包含人声的原曲
* ZegoCopyrightedMusicResourceAccompaniment:伴奏
* ZegoCopyrightedMusicResourceAccompanimentClip:伴奏高潮片段
*/
ZegoCopyrightedMusicResourceType resourceType = ZegoCopyrightedMusicResourceSong;
/** 点歌 */
[self.copyrightedMusic requestResource:config type:resourceType callback:^(int errorCode, NSString * _Nonnull resource) {
}];
} else {
// 该首歌没有包含人声的歌曲的版权
}
通过调用 requestResource 接口,还可以获取歌曲对应的 “伴奏资源”、“长分片高潮片段资源”、“短分片高潮片段资源”,其实现流程与 获取包含人声的歌曲资源 一致。
获取歌曲对应伴奏、长/短分片高潮片段、抢唱片段的资源时,回调会多出了一些字段,比如 krc_token 等,详情请参考 获取歌曲与歌词资源接口说明。
不同版权方对应的歌曲资源有效时长不同(详情请咨询 ZEGO 商务人员),调用 download 接口下载资源时,如果返回了 1017019
错误码,表示资源已失效,请重新调用 requestResource 接口获取资源。
通过 4.3 获取歌曲资源 中点歌获取 resourceID 后,调用 download 接口下载歌曲,下载成功的结果通过 download 接口本身的回调获取。
如果需要获取下载进度,可通过 onDownloadProgressUpdate 回调获取。
resourceID 是开发者在调用 requestResource、getSharedResource时生成的,只在 SDK 的生命周期里有效,SDK 反初始化时就会销毁,因此不能储存到磁盘或者分发给其他用户使用。
/** resourceID */
NSString *resourceID = @"";
[self.copyrightedMusic download:resourceID callback:^(int errorCode) {
if (errorCode == 0) {
// 歌曲下载成功,可以进行播放等操作
} else {
// 歌曲下载失败
}
}];
歌曲下载完成后(收到 download 接口的成功回调),使用 ZegoMediaPlayer 并调用 start 接口开始播放歌曲。
/** 音乐资源 ID,点歌(requestResource)时可获取到 */
NSString *resourceID = @"";
// play 开始播放时的进度
unsigned long long startPosition = 0;
// 1. 通过 ZegoExpressEngine 的 createMediaPlayer 方法 创建 ZegoMediaPlayer
ZegoMediaPlayer *mediaPlayer = [[ZegoExpressEngine sharedEngine] createMediaPlayer];
// 2. 加载歌曲对应的 resourceID,从 startPosition 处开始加载。注意,只有该歌曲资源下载完成了,这里才能加载成功
[mediaPlayer loadCopyrightedMusicResourceWithPosition:resourceID startPosition: startPosition callback:^(int errorCode) {
}];
// start 开始播放
[mediaPlayer start];
调用 download 接口下载完资源后,可以调用 pause、resume、seekTo、stop 等接口控制播放状态。
// pause 暂停播放
[mediaPlayer pause];
// resume 恢复播放
[mediaPlayer resume];
// seekTo 调整播放进度到 position 位置,position 为毫秒数
long position = 1000;
[mediaPlayer seekTo:position callback:^(int errorCode) {
}];
// stop 停止播放
[mediaPlayer stop];
点播歌曲完成后,需要推送歌声音频流,以供远端用户听到演唱用户的歌声。请根据实际需求,参考 独唱方案、实时合唱方案、串行合唱方案 或 抢唱方案 实现推流。
联系我们
文档反馈