技术实践 | 在线 KTV 实现过程(内附demo体验)
你在线上K过歌吗?
在线K歌自2014年兴起以来,已经发展出了无比庞大的用户群体,每两人中就有就有一人体验过在线 K歌,其前景不可小觑。
如此庞大的市场规模,以及音视频技术使用门槛逐步降低的加持,各类在线K歌玩家大幅增加,在K歌赛道大放异彩,对于开发者而言,如何能够快速实现线上 KTV 的场景就变得十分重要。
想要快速实现一起在线K歌的开发,看起来很难,那是因为你还不知道 ZEGO 即构科技,只要实现以下三步就可以快速的实现一起K歌的开发。
今天的文章就带领大家一起了解线上 KTV 的结构与实现过程,让开发变得更简单!
一、准备工作
1、开发环境的准备
更多详情可点击:集成过程
- Android Studio 2.1 或以上版本。
- Android SDK 25、Android SDK Build-Tools 25.0.2、Android SDK Platform-Tools 25.x.x 或以上版本。
- Android 4.1 或以上版本,且支持音视频的 Android 设备。
- Android 设备已经连接到 Internet。
2、ZEGO 平台账号的注册
开发环境搭建好之后,需要在 ZEGO 管理控制台上创建应用、才能获取开发需要的AppId 和 AppSign 。具体的创建应用过程详见文章:控制台创建项目流程
二、实现流程详细介绍
1、接口规范说明
首先分析ZEGO的API输入输出规范。根据 API使用文档 来看,调用接口格式如下:
以创建 ZegoExpressEngine 单列对象为列,每个参数都详细的解析其作用。每个接口都描述了作用与用法。
2、一起 KTV 的项目开发 (实现流程)
一起KTV 是一个依附于语音聊天室的娱乐场景。在这个场景中,一个KTV房间里包含了三种角色(房主、合唱着、听众)。
房主:创建 KTV 房间并推送人声、伴奏到远端,并发起混流任务。房主会自动上麦并固定为麦上首位。可点歌切歌(包括自己点的歌和合唱者点的歌)
合唱者:合唱者可以点歌,或者与其他合唱者进行合唱。(上麦后成为合唱者,可点歌切歌-只能切当前播放是自己点的歌)
听众:进入 KTV 房间后,拉取播放房间内的混流。
其中的功能模块有,房间管理、麦位管理、点歌系统、合唱同步管理、歌词同步管理 5 个业务模块。
整体架构图如下:
整体实现流程如下:接入参考链接
(1)用户需要调用 createEngine 接口,初始化 ZEGO Express SDK。
/** 定义 SDK 引擎对象 */
ZegoExpressEngine engine;
ZegoEngineProfile profile = new ZegoEngineProfile();
/** 请通过官网注册获取,格式为 123456789L */
profile.appID = appID;
/** 64个字符,请通过官网注册获取,格式为"0123456789" */
profile.appSign = appSign;
/** 通用场景接入 */
profile.scenario = ZegoScenario.GENERAL;
/** 设置app的application 对象 */
profile.application = getApplication();
/** 创建引擎 */
engine = ZegoExpressEngine.createEngine(profile, null);
(2)用户需要调用 createCopyrightedMusic 接口,创建版权音乐对象。
/** 定义 CopyrightedMusic 对象 */
ZegoCopyrightedMusic copyrightedMusic;
/** 创建 CopyrightedMusic 对象 */
copyrightedMusic = engine.createCopyrightedMusic();
(3)用户需要调用 initCopyrightedMusic 接口,初始化版权音乐对象。
/** initCopyrightedMusic */
/** CopyrightedMusicConfig */
ZegoCopyrightedMusicConfig config = new ZegoCopyrightedMusicConfig();
/** 填写 userID、userName */
String userID = ;
String userName = ;
ZegoUser user = new ZegoUser(userID, userName);
config.user = user; copyrightedMusic.initCopyrightedMusic(config, new IZegoCopyrightedMusicInitCallback() {
@Override
public void onInitCallback(int i) {
}
});
(4)用户可以通过调用 sendExtendedRequest 接口,发送版权音乐扩展请求,获取 songID(songID 是一首歌曲的唯一标识)。
// 下面以获取歌单列表为例
String command = "/playlist/classify";
// 扩展请求参数,json格式字符串
String params = "{ \"category_id\": \"577\", \"page\": 1, \"size\": 10}";
copyrightedMusic.sendExtendedRequest(command, params, new IZegoCopyrightedMusicSendExtendedRequestCallback() { @Override
public void onSendExtendedRequestCallback(int i, String s, String s1) {
// s: command
// s1: result json 格式字符串
}
});
(5)用户可以调用 requestSong、requestAccompaniment 接口,进行点歌或点伴奏,然后通过 ZegoCopyrightedMusicRequestSongCallback、ZegoCopyrightedMusicRequestAccompanimentCallback 回调接口,获取 songID 对应的 resourceID、shareToken。
/** 点歌配置 */
ZegoCopyrightedMusicRequestConfig config = new ZegoCopyrightedMusicRequestConfig();
/** 音乐 songID */
config.songID = ;
/** 计费模式 */
config.mode = ZegoCopyrightedMusicBillingMode.getZegoCopyrightedMusicBillingMode(0);
/** 点伴奏 */
copyrightedMusic.requestAccompaniment(config, new IZegoCopyrightedMusicRequestAccompanimentCallback() { @Override
public void onRequestAccompanimentCallback(int i, String s) { // s: result
}
});
(6)在获取到其他用户分享的 shareToken 后,可以在有效时间内调用 getMusicByToken 接口获取被分享的音乐资源,然后通过 ZegoCopyrightedMusicGetMusicByTokenCallback 回调获取 shareToken 对应的 resourceID。
/** 输入 shareToken */
String shareToken = ; copyrightedMusic.getMusicByToken(shareToken, new IZegoCopyrightedMusicGetMusicByTokenCallback() {
@Override
public void onGetMusicByTokenCallback(int i, String s) { // s: result
}
});
(7) 用户可以调用 getLrcLyric 接口获取歌词,将会通过 ZegoCopyrightedMusicGetLrcLyricCallback 回调获取到结果。
/** 音乐 songID */
String songID = ;
copyrightedMusic.getLrcLyric(songID, new IZegoCopyrightedMusicGetLrcLyricCallback() {
@Override
public void onGetLrcLyricCallback(int errorCode,, String lyrics) {
// s: result
}
});
(8)用户获取 resourceID 后可以调用 download 接口下载资源。
/** resourceID */
String resourceID = ;
copyrightedMusic.download(resourceID, new IZegoCopyrightedMusicDownloadCallback() {
@Override
public void onDownloadCallback(int i) { } });
(9)下载资源成功后,用户可以开始调用 start 接口播放资源,或通过 pause 、stop 等接口调整播放状态。
/** 音乐资源 ID */
String resourceID = ;
// play
long startPosition = ;
// 创建
ZegoMediaPlayer mediaPlayer = engine.createMediaPlayer(); mediaPlayer.loadCopyrightedMusicResourceWithPosition(resourceID, startPosition);
mediaPlayer.start();
// pause
mediaPlayer.pause();
// resume
mediaPlayer.resume();
// stop
mediaPlayer.stop();
// seekTo
long position = ;
mediaPlayer.seekTo(position, new IZegoMediaPlayerSeekToCallback() {
@Override
public void onSeekToCallback(int i) {
}
});
3、角色实现流程
(1)房主端的实现流程
- 创建引擎并配置。
- 通过业务后台创建房间,创建成功后调用 loginRoom 加入 RTC 房间。
- 房主默认上麦,并处于麦上首位。
- 房主可自由点歌、切歌(自己点的歌、合唱者点的歌)。
- 精准混流任务仅由房主发起,混流包括房主的人声流、房主伴奏流以及所有合唱者的人声流。
- 发送 SEI 信息,让房间内所有人同步歌曲播放进度。
- 房主可让其他上麦成员下麦,同时需要通知房间内所有成员麦位变化以更新麦位信息。
- 房主调用业务后台销毁房间,成功后调用 logoutRoom 销毁 RTC 房间,房间内所有成员自动退房。
流程图如下:
(2)合唱者端的实现流程
- 创建引擎并进行相关配置。
- 获取房间列表,加入业务后台房间,成功后调用 loginRoom 加入 RTC 房间。
- 进房后上麦成为合唱者。上麦过后可点歌、当前播放的是自己点的歌也可切歌。
- 监听房间歌曲变化,按需加载歌曲和歌词。
- 推送自己的人声流,拉取所有合唱者的人声流,但不拉取混流。
- 解析房主发送的 SEI 信息,当歌曲播放进度与房主的差距过大时,校准本端播放器进度和歌词。
流程图如下:
(3)听众端的实现流程
- 创建引擎并进行相关配置。
- 获取房间列表,加入业务后台房间,成功后调用 loginRoom 加入 RTC 房间。
- 监听房间歌曲变化,按需加载歌词。
- 拉取混流。
- 解析房主发送的 SEI 信息,校准本端歌词进度。
流程图如下:
三、在线 KTV 效果展示
想要体验 Demo 可点击链接下载:Android apk 安装包
四、总结
牛顿曾说:我看得远,是因为我站在巨人的肩膀上!
基于 ZEGO 即构科技的音视频功能、在线K歌的解决方案,一番操作下来,很简单就开发出来一款《一起 KTV》的 demo。而在线KTV的合唱体验能够取得突破,得益于即构科技在端到端通话延迟上的重大进展,即构通过对数据传输每个环节的优化,在保障的合唱体验效果的前提下,将端到端的感官延迟降低至70ms,带来最极致的视听盛宴!
一起动手实操一下吧!
技术实践 | 在线 KTV 实现过程(内附demo体验)的更多相关文章
- mybatis学习笔记(五) -- maven+spring+mybatis从零开始搭建整合详细过程(附demo和搭建过程遇到的问题解决方法)
文章介绍结构一览 一.使用maven创建web项目 1.新建maven项目 2.修改jre版本 3.修改Project Facts,生成WebContent文件夾 4.将WebContent下的两个文 ...
- Android开发:LocationManager获取经纬度及定位过程(附demo)
在Android开发其中.常常须要用到定位功能,尤其是依赖于地理位置功能的应用.非常多人喜欢使用百度地图,高德地图提供的sdk.开放API,可是在只须要经纬度,或者城市,街道地址等信息.并不须要提供预 ...
- 【公开课】【阿里在线技术峰会】魏鹏:基于Java容器的多应用部署技术实践
对于公开课,可能目前用不上这些,但是往往能在以后想解决方案的时候帮助到我.以下是阿里对公开课的整理 摘要: 在首届阿里巴巴在线峰会上,阿里巴巴中间件技术部专家魏鹏为大家带来了题为<基于Java容 ...
- Redis数据库云端最佳技术实践
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB发表于云+社区专栏 邹鹏,腾讯高级工程师,腾讯云数据库Redis负责人,多年数据库.网络安全研发经验. ...
- 让AI简单且强大:深度学习引擎OneFlow技术实践
本文内容节选自由msup主办的第七届TOP100summit,北京一流科技有限公司首席科学家袁进辉(老师木)分享的<让AI简单且强大:深度学习引擎OneFlow背后的技术实践>实录. 北京 ...
- MIT挑战(如何在12个月内自学完成MIT计算机科学的33门课程|内附MIT公开课程资源和学习顺序
译者注:本文译自Scott H. Young的博客,Scott拥有超强的学习能力,曾在12个月内自学完成麻省理工学院计算机科学的33门课程.本文就是他个人对于这次MIT挑战的介绍和总结. 版权声明:本 ...
- 从游击队到正规军(三):基于Go的马蜂窝旅游网分布式IM系统技术实践
本文由马蜂窝技术团队电商交易基础平台研发工程师"Anti Walker"原创分享. 一.引言 即时通讯(IM)功能对于电商平台来说非常重要,特别是旅游电商. 从商品复杂性来看,一个 ...
- 技术沙龙|京东云DevOps自动化运维技术实践
自动化测试体系不完善.缺少自助式的持续交付平台.系统间耦合度高服务拆分难度大.成熟的DevOps工程师稀缺,缺少敏捷文化--这些都是DevOps 在落地过程中,或多或少会碰到的问题,DevOps发展任 ...
- 阿里巴巴微服务与配置中心技术实践之道 配置推送 ConfigurationManagement ConfigDrivenAnyting
阿里巴巴微服务与配置中心技术实践之道 原创: 坤宇 InfoQ 2018-02-08 在面向分布式的微服务系统中,如何通过更高效的配置管理方式,帮助微服务系统架构持续"无痛"的演进 ...
- iBatis.net技术实践
随着大数据技术的兴起和快速发展,人们更多的开始关注HDFS.HBase.Hive等技术.但是谈到强一致性,我们又不得不回归现实,只能继续沿用RDBMS存储强一致性的数据.我们日常接触到的绝大多数的应用 ...
随机推荐
- Excel VBA编程常用语句300句
定制模块行为 1. Option Explicit '强制对模块内所有变量进行声明 Option Private Module '标记模块为私有,仅对同一工程中其它模块有用,在宏对话框中不显示 Opt ...
- 靶机: AdmX_new
靶机: AdmX_new 准备阶段 靶机:https://download.vulnhub.com/admx/AdmX_new.7z 下载后进行 MD5:2948034da23a8acc1285fd4 ...
- Nginx 工作原理简介
在了解Nginx工作原理之前,我们先来了解下几个基本的概念 以及常见的I/O模型. 基本概念 同步:就是指调用方发起一个调用,在没有得到调用结果之前,该调用不返回.换句话说,也就是调用方发起一个调用后 ...
- NOIP2022退役记
我是青岛西海岸新区的一名oier,qxyz(xhayz)的. (其实也不知道算不算得上真正的oier) 已经高二了,是最后一次noip了,必须写点什么记录一下了吧,这样至少可以向世界留下一点痕迹:这个 ...
- 机器学习:详解什么是端到端的深度学习?(What is end-to-end deep learning?)
什么是端到端的深度学习? 深度学习中最令人振奋的最新动态之一就是端到端深度学习的兴起,那么端到端学习到底是什么呢?简而言之,以前有一些数据处理系统或者学习系统,它们需要多个阶段的处理.那么端到端深度学 ...
- 2023/4/17 SCRUM个人博客
1.我昨天的任务 学习了easydict库的基本操作 2.遇到了什么困难 没有找到合适的人脸识别库 3.我今天的任务 初步学习dlib的安装,了解dlib的基础组件
- python none类型
一.python中的数据类型:数值类型.序列类型.散列类型. 1.数值类型:整数型(int).浮点数(float).布尔值(bool) 2.序列类型(有序的):序列类型数据的内部元素是有顺序的,可以通 ...
- 在Ubuntu 18.04 Desktop图形中配置静态和动态IP
在Ubuntu 18.04 图形界面中配置静态和动态IP 设置静态ip 设置为dhcp动态获取ip
- 【RabbitMQ】14 集群搭建
多服务器单实例 -- 参考博客: https://www.cnblogs.com/lixioayi/articles/9993658.html 首先要找到cookie文件,所有实例要保持cookie一 ...
- 【H5】13 表单 其二 如何构造
有了基础知识,我们现在更详细地了解了用于为表单的不同部分提供结构和意义的元素. 前提条件: 基本的计算机能力, 和基本的 对HTML的理解. 目标: 要理解如何构造HTML表单并赋予它们语义,以便它们 ...