帮助企业构建在线沟通能力
上架难、买量贵?即构 Web 端 1v1 方案全力加速泛娱乐出海
1v1 视频社交以其功能简洁、互动性强、匹配效率高等特点,在陌生人社交玩法中饱受用户欢迎,平台仅需让两个用户通过匹配、选择等形式连通后,用户即可在房内进行 1v1 视频社交,且在社交的同时又极具私密性,满足了用户社交与 dating 的需求,盛行在中东土耳其、印度、南美等一些热门出海地区。 近年来,1v1 视频社交平台也在往更加多元化的方向发展,逐渐搭建起直播间、语聊房,为匹配环节提供更多社交场景,增添玩法形式提升用户留存。另一方面,1v1 场景简单、变现能力强,也是备受社交平台关注的主要原因之一。 然而,企业在布局海外 1v1 视频社交业务的同时,我们发现并没有那么顺利: 应用商店上架困难、审核周期长 平台买量价格高、难以精准转化 应用商店平台税费高达 30% 支持Web 端 1v1 应用,为出海提供另一种选择 面临上述状况时,企业希望找到一种更便捷、低成本、效率高的方式,快速上线 1v1 视频社交,以此抢占产品先机,于是众多企业与开发者将目光转向 Web 端应用开发,Web 端应用开发相比其它客户端形式具备自身的天然优势: 可跨平台运行:可在多个平台和设备上运行,无需为每个平台和设备单独开发应用程序,节省开发成本; 用户访问便利:用户无需安装与下载可以直接通过浏览器访问,提高了用户的使用便利性,这种特性天然适配社交媒体推广渠道,只需 URL 链接,就可让用户即时体验核心卖点服务; 更新快速:无需等待应用商店的审核和发布,可以随时更新和发布新功能; 成本更低:相对于原生应用程序,Web 端应用程序的开发成本更低,开发周期更短; SEO 友好:Web 端应用程序可以被搜索引擎索引,有效提高应用程序的曝光率和搜索排名,从而提升推广变现效率。 即构 1v1 场景可为平台提供 Web 接入方案,帮助平台解决 APP 上架难的问题,并且提升投流转化,让企业快速实现 1v1 场景搭建,为出海全力加速。 即构结合用户的使用体验部署了完备的技术能力和配套功能,从需求方的角度思考并做好 Web 端功能服务的完备性,协助平台提供给用户更好的互动体验,方案高可用,拥有和客户端一样的互动效果,且效果领先与行业友商。 此外,即构还为企业与开发者提供了一套可实现社交场景 1v1 实时通话的体验源码,供接入时参考,使用该 Demo 可以体验到即构稳定可靠的 1v1 实时音视频通话服务。未来,即构也会定期更新此 Demo,增加更多的功能模块,例如赠送礼物、美颜特效、聊天沟通、审核安全等。 更多关于 1v1 源码的详细信息,点击链接了解更多!Chat1v1 - 1v1 视频聊天示例源码 1v1 全链路环节拆分优化,提升转化率 除了完备的 Web 方案助力企业快速实现 1v1 陌生人社交场景搭建之外,即构对 1v1 场景的每个环节均做了优化。 在 1v1 场景中,即构将用户路径拆解为 4 个环节:用户匹配——主播接单——房内互动——成交结算,用户在进行上述路径的每一个阶段转场时,转场间的“丝滑程度”决定了用户是否会完成下单动作,如果各个环节的切换时间过长,用户会选择持续等待、退出应用或者不断切换下一个主播,这之间的任何一种情况最终都会影响用户时长收益及付费订单转化率。 从用户匹配到成交结算,即构针对上述提到的 1v1 场景中的每个环节均做了优化,可提供全链路解决方案,帮助平台精细化运营,减少订单折损率,提升平台内转化率,实现总营收增长。 以接单环节来说,用户的接通并开始订单是非常急迫的,过长的接通时长直接降低订单的开始转化率。如果用户发起通话后在 2s 内没有接通,有很大的概率会直接退出通话,对千万级流水来说,5% 退出率就意味着50 万营收的损失,对业务是非常大的影响。 针对此环节,即构优化全球网络以保障订单成功接通,可实现全网最优秒开方案以及 95% 的用户接通率,让用户享受到更快、更流畅的进房体验!后续我们会发布针对 1v1 每个路径的专项解读文章以及其他出海场景的系列文章,敬请期待! 了解更多欢迎咨询~
2024-05-11 16:48:38326阅读
即构直播PK玩法:如何创造爆款直播内容
直播作为泛娱乐社交出海的典型场景,已发展多年,面临产品同质化愈发严重的问题。社交 APP 在扬帆出海时如何找寻新的突破口,提升业务营收,形成自己的差异化优势?为直播场景增添更多的玩法是重要的方法之一。 PK 玩法 ,为何在直播中备受欢迎? 除了流畅、高清的画质体验外,直播平台内的功能与玩法创新, 也是一些头部直播平台能够脱颖而出的秘诀。比如加入更具吸引力的玩法、邀请网红主播入驻等等。以中东出海市场为例,PK 是中东用户在观看线上直播时最喜爱的互动形式之一,有钱有闲的市场氛围和旺盛的社交需求,让中东土豪们在直播间“一掷千金”。 为何 PK 玩法在一众互动方式中备受欢迎? 对于主播来说,PK 玩法可以带来人气飙升,PK 期间双方主播各自拉票,粉丝会极力为喜欢的主播打榜 PK,刷屏送礼让主播获胜免受惩罚。对于平台内坐拥众多粉丝的大主播 PK时 ,粉丝抱团的力量会体现的更加明显。通过 PK 玩法,主播还可以进行粉丝导流,为自己涨粉,在 PK 过程中,主播之间会互相推荐,让粉丝们去关注对方主播,这也是主播吸粉的好机会。 从用户角度来说,加入 PK 玩法,直播间的内容更加多元化,用户与主播之间的互动形式更丰富。PK 已然不是简单的拉票而已,而是在胜负规则和游戏玩法之下的抱团互动,更具娱乐性。 一些头部出海直播平台在 PK 玩法中还设置了送礼榜、收礼榜、日榜、周榜等等榜单数据,也带来了更多的 PK 属性,令社交性更强,这些平台对内容多样化的玩法有着更深刻的理解。 即构直播方案支持 PK 玩法 人气暴涨 在直播产品同质化愈发严重的今天,如何做好平台内的内容生态、直播间品类、提升用户留存,在竞争越来越大的市场中通过独特优势占据一席之地是一个重要课题。 即构在出海直播解决方案中融入了“ PK 玩法”,可实现跨房间双人 PK、四人 PK、多人 PK 等等,提供多样化玩法形式,用 PK 玩法为直播间创造人气,解决了之前单主播模式下,主播直播内容过于单一、主播圈互动较少的问题。同时,PK 互动也促进了粉丝为自己喜欢的主播打榜,加强了直播间送礼互动的场景卖点。即构出海泛娱乐直播玩法:https://www.zego.im/solution/Global 秒开率达 98%,实现多场景快速转场 即构在出海直播场景中可实现最高 98% 的秒开率,带来更快的进房和转场体验,降低首帧时长。相较于友商,即构底层架构的房间信令服务和流媒体服务解耦特性,可实现“ PK 呼叫信令、RTC 房间、流媒体数据”三个通道一起并行发送和接收,实现同步启动,即实现登录房间的同时立即进行拉流。 大大加快了在直播 PK 连麦时的视频首帧出图速度,可实现多场景快速转场,完美契合“ 1V1 - 直播 - PK - 多人连麦”这四个场景之间的快速切换。 无感切换,支持用户自由选择观看视角 当 A、B 主播发起 PK 时,用户可以无感知从单主播切换到多主播 PK 状态,并可以自由选择观看视角。即构 PK 方案支持跨房间连麦,即同时可在多个房间内实现推流、拉流,并能隔离多个房间的消息及回调,实现更灵活的直播 PK 玩法,也方便主播在 PK 时互相为对方的直播间引流,且用户无需退出房间。 开发者友好,提供 PK 场景的多种推拉流策略 从单主播直播转 PK 时,即构提供了混流转推、保持推单流等多种推流策略,可以让开发者选择成本最优、观众端性能最佳、接入难度最低的方案。 在拉流方式上,提供超低延迟直播、CDN 直播等不同方式,尤其是出海,即构自研超低延迟直播能给用户带来低延迟、更流畅的直播体验,从 CDN 直播切换到即构自研超低延迟直播后,观众端延迟可低至毫秒级别,视频卡顿率可相对降低 75%。 加入 PK 玩法,直播间内容更加多元化,互动形式更加丰富。除 PK 玩法外,针对直播应用在海外面临的首帧加载时间过长、画面模糊、卡顿三大体验痛点,即构可提供畅直播方案,一次接入三种档位直播服务,实现极致秒开、流畅、超高清画质体验,以及一键画质提升方案,能够根据用户的网络状况、手机性能、场景智能调整,实现最佳观看画质,一行代码即可调用。 从玩法到画质,全方位提升用户体验,让用户次留、观看时长、营收等业务指标得到明显增长!
2024-05-11 16:39:58266阅读
WebRTC实现简单音视频通话能力
1 WebRTC音视频通话功能简介 本文介绍如何基于WebRTC快速实现一个简单的实时音视频通话。 在开始之前,您可以先了解一些实时音视频推拉流相关的基础概念: 流:一组按指定编码格式封装的音视频数据内容。一个流可以包含几个轨道,比如视频和音频轨道。 推流:把采集阶段封包好的音视频数据流推送到 ZEGO 实时音视频云的过程。 拉流:从 ZEGO 实时音视频云将已有音视频数据流拉取播放的过程。 房间:是 ZEGO 提供的音视频空间服务,用于组织用户群,同一房间内的用户可以互相收发实时音视频及消息。 用户需要先登录某个房间,才能进行音视频推流、拉流操作。 用户只能收到自己所在房间内的相关消息(用户进出、音视频流变化等)。 更多相关概念可参考即构官网关于音视频SDK的介绍 术语说明。 2 实现WebRTC视频通话的前提条件 在实现基本的WebRTC实时音视频功能之前,请确保: 已在项目中集成 ZEGO Express SDK,详情请参考 快速开始 - 集成。 已在 ZEGO 控制台 创建项目,申请有效的 AppID 和 ServerSecret,详情请参考 控制台 - 项目管理 中的“项目信息”。 3 WebRTC音视频通话示例代码 我们提供了一个实现了WebRTC音视频通话基本流程的完整示例 HTML 文件,可作为WebRTC开发过程中的参考。 Zego RTC Video Call Local video Remote video 4 WebRTC音视频通话实现流程 以用户 A 拉取用户 B 的流为例,一次简单的WebRTC实时音视频通话主要流程如下: 用户 A 创建实例,登录房间。(登录成功后,可预览自己的画面并推流。) 用户 B 创建实例,登录同一个房间。登录成功后,用户 B 开始推流,此时 SDK 会触发 roomStreamUpdate 回调,表示房间内有流的变化。 用户 A 可通过监听 roomStreamUpdate 回调,当回调通知有流新增时,获取用户 B 的流 ID,来拉取播放用户 B 刚刚推送的流。 4.1 创建WebRTC实时音视频通话界面 为方便实现基本的WebRTC实时音视频功能,您可参考WebRTC实时音视频的示例代码和下图实现一个简单实时音视频功能的页面。 打开或新建 “index.html” 页面文件,并拷贝以下代码到文件中。 Zego RTC Video Call Local video Remote video 4.2 创建引擎并监听回调 创建并初始化一个 ZegoExpressEngine 的实例,将您项目的 AppID 传入参数 “appID”,Server 传入参数 “server”。 即构实时音视频SDK 提供如房间连接状态、音视频流变化、用户进出等通知回调。为避免错过任何通知,您需要在创建 ZegoExpressEngine 后立即监听回调。 // 项目唯一标识 AppID,Number 类型,请从 ZEGO 控制台获取 let appID = ; // 接入服务器地址 Server,String 类型,请从 ZEGO 控制台获取(获取方式请参考上文“前提条件”) let server = ""; // 初始化实例 const zg = new ZegoExpressEngine(appID, server); // 房间状态更新回调 zg.on('roomStateChanged', (roomID, reason, errorCode, extendData) => { if (reason == 'LOGINING') { // 登录中 } else if (reason == 'LOGINED') { // 登录成功 //只有当房间状态是登录成功或重连成功时,推流(startPublishingStream)、拉流(startPlayingStream)才能正常收发音视频 //将自己的音视频流推送到 ZEGO 音视频云 } else if (reason == 'LOGIN_FAILED') { // 登录失败 } else if (reason == 'RECONNECTING') { // 重连中 } else if (reason == 'RECONNECTED') { // 重连成功 } else if (reason == 'RECONNECT_FAILED') { // 重连失败 } else if (reason == 'KICKOUT') { // 被踢出房间 } else if (reason == 'LOGOUT') { // 登出成功 } else if (reason == 'LOGOUT_FAILED') { // 登出失败 } }); //房间内其他用户进出房间的通知 //只有调用 loginRoom 登录房间时传入 ZegoRoomConfig,且 ZegoRoomConfig 的 userUpdate 参数为 “true” 时,用户才能收到 roomUserUpdate回调。 zg.on('roomUserUpdate', (roomID, updateType, userList) => { if (updateType == 'ADD') { for (var i = 0; i console.log(userList[i]['userID'], '加入了房间:', roomID) } } else if (updateType == 'DELETE') { for (var i = 0; i console.log(userList[i]['userID'], '退出了房间:', roomID) } } }); zg.on('roomStreamUpdate', async (roomID, updateType, streamList, extendedData) => { // 房间内其他用户音视频流变化的通知 }); 4.3 检测浏览器WebRTC兼容性 考虑到不同的浏览器对 WebRTC 的兼容性不同,在实现实时音视频推拉流功能之前,您需要检测浏览器能否正常运行 WebRTC。 您可以调用 checkSystemRequirements 接口检测浏览器的兼容性,检测结果的含义,请参考 ZegoCapabilityDetection 接口下的参数描述。 const result = await zg.checkSystemRequirements(); // 返回的 result 为兼容性检测结果。 webRTC 为 true 时表示支持 webRTC,其他属性含义可以参考接口 API 文档。 console.log(result); // { // webRTC: true, // customCapture: true, // camera: true, // microphone: true, // videoCodec: { H264: true, H265: false, VP8: true, VP9: true }, // screenSharing: true, // errInfo: {} // } 您还可以通过 ZEGO 提供的实时音视频推拉流在线检测工具 在线检测工具,在需要检测的浏览器中打开,直接检测浏览器的兼容性。请参考 浏览器兼容性说明 获取 音视频SDK 支持的浏览器兼容版本。 4.4 登录房间 1. 生成 Token 登录房间需要用于验证身份的 Token,开发者可直接在 ZEGO 控制台获取临时 Token(有效期为 24 小时)来使用,详情请参考 控制台 - 项目管理 中的 “项目信息”。 临时 Token 仅供调试,正式上线前,请从开发者的业务服务器生成 Token,详情可参考 使用 Token 鉴权。 2. 登录房间 调用 loginRoom 接口,传入房间 ID 参数 “roomID”、“token” 和用户参数 “user”,根据实际情况传入参数 “config”,登录房间。 “roomID”、“userID” 和 “userName” 参数的取值都为自定义。 “roomID” 和 “userID” 都必须唯一,建议开发者将 “userID” 设置为一个有意义的值,可将其与自己的业务账号系统进行关联。 只有调用 loginRoom 接口登录房间时传入 ZegoRoomConfig 配置,且 “userUpdate” 参数取值为 “true” 时,用户才能收到 roomUserUpdate 回调。 // 登录房间,成功则返回 true // userUpdate 设置为 true 才能收到 roomUserUpdate 回调。 let userID = Util.getBrow() + '_' + new Date().getTime(); let userName = "user0001"; let roomID = "0001"; let token = ; // 为避免错过任何通知,您需要在登录房间前先监听用户加入/退出房间、房间连接状态变更、推流状态变更等回调。 zg.on('roomStateChanged', async (roomID, reason, errorCode, extendedData) => { }) zg.loginRoom(roomID, token, { userID, userName: userID }, { userUpdate: true }).then(result => { if (result == true) { console.log("login success") } }); 您可以监听 roomStateChanged 回调实时监控自己与房间的连接状态。只有当房间状态是连接成功时,才能进行推流、拉流等操作。 4.5 预览自己的画面,并推送到 ZEGO 音视频云 创建流并预览自己的画面 开始推流前需要创建本端的音视频流,调用 createStream 接口获取媒体流对象,默认会采集摄像头画面和麦克风声音。媒体流对象可以使用 createLocalStreamView 创建本地媒体流播放组件进行播放,也可以通过 video 元素 srcObject 属性赋值进行播放。 2 .需等待 createStream 接口返回流媒体对象后,再将自己的音视频流推送到 ZEGO 音视频云。 调用 startPublishingStream 接口,传入 “streamID” 和创建流得到的流对象 “localStream”,向远端用户发送本端的音视频流。 “streamID” 由您本地生成,但是需要保证同一个 AppID 下,“streamID” 全局唯一。如果同一个 AppID 下,不同用户各推了一条 “streamID” 相同的流,会导致后推流的用户推流失败。 // 此处在登录房间成功后,立即进行推流。在实现具体业务时,您可选择其他时机进行推流,只要保证当前房间连接状态是连接成功的即可。 zg.loginRoom(roomID, token, { userID, userName: userID }, { userUpdate: true }).then(async result => { if (result == true) { console.log("login success") // 创建流、预览 // 调用 createStream 接口后,需要等待 ZEGO 服务器返回流媒体对象才能执行后续操作 const localStream = await zg.createStream(); // 创建媒体流播放组件对象,用于预览本地流 const localView = zg.createLocalStreamView(localStream); // 将播放组件挂载到页面,"local-video" 为组件容器 DOM 元素的 id 。 localView.play("local-video"); // 开始推流,将自己的音视频流推送到 ZEGO 音视频云 let streamID = new Date().getTime().toString(); zg.startPublishingStream(streamID, localStream) } }); (可选)设置音视频采集参数 通过属性设置相关采集参数 可根据需要通过 createStream 接口中的如下属性设置音视频相关采集参数,详情可参考 自定义视频采集: camera:摄像头麦克风采集流相关配置 screen:屏幕捕捉采集流相关配置 custom:第三方流采集相关配置 4.6 拉取其他用户的音视频 进行视频通话时,我们需要拉取到其他用户的音视频。 房间内有其他用户加入时,SDK 会触发 roomStreamUpdate 回调,通知房间内有流新增,基于此可获取其他用户的 “streamID”。此时,调用 startPlayingStream 接口根据传入的其他用户的 “streamID”,拉取远端已推送到 ZEGO 服务器的音视频画面。若需要从 CDN 拉流,可参考 使用 CDN 直播。 // 流状态更新回调 zg.on('roomStreamUpdate', async (roomID, updateType, streamList, extendedData) => { // 当 updateType 为 ADD 时,代表有音视频流新增,此时可以调用 startPlayingStream 接口拉取播放该音视频流 if (updateType == 'ADD') { // 流新增,开始拉流 // 这里为了使示例代码更加简洁,我们只拉取新增的音视频流列表中第的第一条流,在实际的业务中,建议开发者循环遍历 streamList ,拉取每一条音视频流 const streamID = streamList[0].streamID; // streamList 中有对应流的 streamID const remoteStream = await zg.startPlayingStream(streamID); // 创建媒体流播放组件对象,用于播放远端媒体流 。 const remoteView = zg.createRemoteStreamView(remoteStream); // 将播放组件挂载到页面,"remote-video" 为组件容器 DOM 元素的 id 。 remoteView.play("remote-video"); } else if (updateType == 'DELETE') { // 流删除,停止拉流 } }); 部分浏览器因自动播放限制策略问题,使用 ZegoStreamView 媒体流播放组件进行播放媒体流可能受阻,SDK 默认会在界面上弹窗提示恢复播放。 您可以将 ZegoStreamView.play() 方法的第二个参数 options.enableAutoplayDialog 设置为 false 关闭自动弹窗,通过在 autoplayFailed 事件回调中,在页面上显示一个按钮,引导用户点击恢复播放。 至此,您已经成功实现了简单的实时音视频通话,可在浏览器中打开 “index.html”,体验实时音视频功能。 5 实时音视频SDK常用功能 5.1 常用通知回调 // 房间连接状态更新回调 // 本地调用 loginRoom 加入房间时,您可通过监听 roomStateChanged 回调实时监控自己在本房间内的连接状态。 zg.on('roomStateChanged', (roomID, reason, errorCode, extendData) => { if (reason == 'LOGINING') { // 登录中 } else if (reason == 'LOGINED') { // 登录成功 //只有当房间状态是登录成功或重连成功时,推流(startPublishingStream)、拉流(startPlayingStream)才能正常收发音视频 //将自己的音视频流推送到 ZEGO 音视频云 } else if (reason == 'LOGIN_FAILED') { // 登录失败 } else if (reason == 'RECONNECTING') { // 重连中 } else if (reason == 'RECONNECTED') { // 重连成功 } else if (reason == 'RECONNECT_FAILED') { // 重连失败 } else if (reason == 'KICKOUT') { // 被踢出房间 } else if (reason == 'LOGOUT') { // 登出成功 } else if (reason == 'LOGOUT_FAILED') { // 登出失败 } }); //房间内其他用户推送的音视频流新增/减少的通知 //自己推送的流不能在这里接收到通知 zg.on('roomStreamUpdate', async (roomID, updateType, streamList, extendedData) => { if (updateType == 'ADD') { // 流新增 for (var i = 0; i console.log('房间',roomID,'内新增了流:', streamList[i]['streamID']) } const message = "其他用户的视频流streamID: " + streamID.toString(); } else if (updateType == 'DELETE') { // 流删除 for (var i = 0; i console.log('房间',roomID,'内减少了流:', streamList[i]['streamID']) } } }); //房间内其他用户进出房间的通知 //只有调用 loginRoom 登录房间时传入 ZegoRoomConfig,且 ZegoRoomConfig 的 userUpdate 参数为 “true” 时,用户才能收到 roomUserUpdate回调。 zg.on('roomUserUpdate', (roomID, updateType, userList) => { if (updateType == 'ADD') { for (var i = 0; i console.log(userList[i]['userID'], '加入了房间:', roomID) } } else if (updateType == 'DELETE') { for (var i = 0; i console.log(userList[i]['userID'], '退出了房间:', roomID) } } }); //用户推送音视频流的状态通知 //用户推送音视频流的状态发生变更时,会收到该回调。如果网络中断导致推流异常,SDK 在重试推流的同时也会通知状态变化。 zg.on('publisherStateUpdate', result => { // 推流状态更新回调 var state = result['state'] var streamID = result['streamID'] var errorCode = result['errorCode'] var extendedData = result['extendedData'] if (state == 'PUBLISHING') { console.log('成功推送音视频流:', streamID); } else if (state == 'NO_PUBLISH') { console.log('未推送音视频流'); } else if (state == 'PUBLISH_REQUESTING') { console.log('请求推送音视频流:', streamID); } console.log('错误码:', errorCode,' 额外信息:', extendedData) }) //推流质量回调。 //成功推流后,您会定时收到回调音视频流质量数据(如分辨率、帧率、码率等)。 zg.on('publishQualityUpdate', (streamID, stats) => { // 推流质量回调 console.log('流质量回调') }) //用户拉取音视频流的状态通知 //用户拉取音视频流的状态发生变更时,会收到该回调。如果网络中断导致拉流异常,SDK 会自动进行重试。 zg.on('playerStateUpdate', result => { // 拉流状态更新回调 var state = result['state'] var streamID = result['streamID'] var errorCode = result['errorCode'] var extendedData = result['extendedData'] if (state == 'PLAYING') { console.log('成功拉取音视频流:', streamID); } else if (state == 'NO_PLAY') { console.log('未拉取音视频流'); } else if (state == 'PLAY_REQUESTING') { console.log('请求拉取音视频流:', streamID); } console.log('错误码:', errorCode,' 额外信息:', extendedData) }) //拉取音视频流时的质量回调。 //成功拉流后,您会定时收到拉取音视频流时的质量数据通知(如分辨率、帧率、码率等)。 zg.on('playQualityUpdate', (streamID,stats) => { // 拉流质量回调 }) //收到广播消息的通知 zg.on('IMRecvBroadcastMessage', (roomID, chatData) => { console.log('广播消息IMRecvBroadcastMessage', roomID, chatData[0].message); alert(chatData[0].message) }); //收到弹幕消息的通知 zg.on('IMRecvBarrageMessage', (roomID, chatData) => { console.log('弹幕消息IMRecvBroadcastMessage', roomID, chatData[0].message); alert(chatData[0].message) }); //收到自定义信令消息的通知 zg.on('IMRecvCustomCommand', (roomID, fromUser, command) => { console.log('自定义消息IMRecvCustomCommand', roomID, fromUser, command); alert(command) }); 5.2 停止音视频通话 1. 停止推流、销毁流 调用 stopPublishingStream 接口停止向远端用户发送本端的音视频流。调用 destroyStream 接口销毁创建的流数据,销毁流后开发需自行销毁 video(停止采集)。 // 根据本端 streamID 停止推流 zg.stopPublishingStream(streamID) // localStream 是调用 createStream 接口获取的 MediaStream 对象 zg.destroyStream(localStream) 2. 停止拉流 调用 stopPlayingStream 接口停止拉取远端推送的音视频流。 // 流状态更新回调 zg.on('roomStreamUpdate', async (roomID, updateType, streamList, extendedData) => { if (updateType == 'ADD') { // 流新增,开始拉流 } else if (updateType == 'DELETE') { // 流删除,通过流删除列表 streamList 中每个流的 streamID 进行停止拉流。 const streamID = streamList[0].streamID; zg.stopPlayingStream(streamID) } }); 3. 退出房间 调用 logoutRoom 接口退出房间。 6 调试视频通话功能 在真机中运行项目,运行成功后,可以看到本端视频画面。 为方便体验,ZEGO 提供了一个 Web 端调试示例 ,在该页面下,输入相同的 AppID、RoomID,输入一个不同的 UserID,即可加入同一房间与真机设备互通。当成功开始音视频通话时,可以听到远端的音频,看到远端的视频画面。 7 获取音视频SDK更多支持 获取本文的Demo、开发文档、技术支持,访问即构文档中心 近期有开发规划的开发者可上即构官网查看,恰逢即构七周年全线音视频产品1折的优惠,联系商务获取RTC产品优惠;
2024-05-11 16:22:00272阅读
如何轻松实现在线K歌房,在家也能线上合唱
与好友线上合唱在家也能线上K歌 如果能开发一个在线K歌应用,能跟好友一起线上合唱在家也能嗨皮。 如何快速实现合唱功能?即构科技提供了实时合唱一站式解决方案和技术实现流程。 目前行业内普遍采用的合唱方案为“串行合唱”。在“串行合唱”方案中,合唱各方串行加入,伴奏由主唱端混入。从本质上来说,这是一种“伪实时合唱”。 主唱体验缺失:副唱、听众合唱同步效果良好,但主唱无法实时听到副唱的歌声 合唱人数有限制:三人或以上的合唱实现复杂,延迟高,难以真正落地 为了突破这两个限制,同时不影响副唱和听众端的体验,即构对方案架构进行了重构,克服了多个技术挑战,实现了合唱者之间的实时互动,也满足了三人及以上的合唱需求。 本文将分享如何基于ZEGO SDK轻松实现在线K歌房,适合想极速搭建在线 K 歌房的开发者。也适合想清晰听到王心凌歌声的男粉们。近期即构七周年庆全线产品1折起,有需要的开发者可点击详情了解:https://www.zego.im/activity/2100005 在线K歌技术方案 通过 ZEGO Express SDK,可极速搭建含 正版曲库 的在线 KTV 场景: 在线K歌场景下实时合唱方案 针对实时合唱的场景,ZEGO 提供了一站式解决方案,让开发者极速搭建能够真正进行“合唱”的在线 K 歌房。 各端在连麦的基础上同时播放歌曲伴奏,然后上麦进行合唱,双人模式下主唱和副唱可以互相听到对方声音,多人模式下合唱者之间都能听到彼此声音,几乎感受不到延迟,达到了真正意义上的实时合唱。 在媒体流方面,合唱者互相进行推拉流,同时会由一名合唱者推出歌曲伴奏,其他合唱者在本地播放伴奏,经过 NTP 进行时间同步。另外,歌曲伴奏和所有合唱者的声音都通过 ZEGO RTC 进行混流服务处理形成一条流,观众只需拉一条流即可听到各端同步的声音,完美实现多人合唱的效果。 该方案的优点在于: 降低了端到端的时延。 提供了用户中途加入合唱的解决方案。 精准同步不同端之间的伴奏、歌词、人声。 改善各端设备性能和本地时间不精准的情况,降低网络环境造成的时延影响。 实时合唱方案技术实现流程 1 概述 搭建一个完整的在线 KTV 需要实时语音(RTC)、点歌(歌曲的获取与分享)、歌词展示等基础能力,并通过以上基础能力实现合唱、麦位管理、房间管理、歌词展示与同步等业务系统。 2 基本流程介绍 以下介绍实现一个完整在线 KTV 的基本流程,可帮助您从整体上理解在线 KTV 的核心业务。 2.1基础业务模块 在线 KTV 整体方案包含房间管理、麦位管理、点歌系统、合唱同步管理、歌词同步管理 5 个业务模块,基本业务流程如下: 在线 K 歌房内的用户有多种角色,包括房主、合唱者、观众。 不同角色在本方案中的基本实现流程如下: 房主 房主创建并加入房间。 发起混流任务(包括房主的人声流、房主伴奏流以及所有合唱者的人声流)。 通过发送 SEI 信息同步房间内所有人的歌曲播放进度。 房主退出房间,房间内所有成员自动退房。 房主创建及离开 RTC 房间,均需由业务服务器创建房间获取对应的 roomID 和 userID 后,然后通过调用 Express 接口 loginRoom 登录房间和 logoutRoom 接口退出房间。 房主通过调用 Express 相关接口进行点歌、下载歌曲和歌词、播放歌曲和发送 SEI 信息等操作,中间则由业务服务器监听房间内歌曲、麦位的信息变更,并通知房间内所有成员。歌词下载完毕后,通过歌词 UI 组件进行逐行或者逐字歌词的展示。 合唱者 观众获取房间列表并加入房间后,上麦成为合唱者。 推送自己的人声流,拉取所有合唱者的人声流,但不拉取混流。 接收并解析房主发送的 SEI 信息,校准本端播放器进度和歌词。 观众加入 RTC 房间上麦成为合唱者,通过获取由业务服务器创建房间对应的 roomID 和 userID 后,然后通过调用 Express 接口 loginRoom 登录房间。 合唱者通过调用 Express 相关接口下载歌曲和歌词、播放歌曲、接收和解析房主发送的 SEI 信息、同步伴奏/歌词等操作,中间则由业务服务器监听房间内歌曲、麦位的信息变更,并通知房间内所有成员。歌词下载完毕后,通过歌词 UI 组件进行逐行或者逐字歌词的展示。 观众 观众获取房间列表并加入房间。 监听房间歌曲变化,并加载歌词。 拉取房主发送的混流。 解析房主发送的 SEI 信息同步歌词。 观众加入 RTC 房间,通过获取由业务服务器创建房间对应的 roomID 和 userID 后,然后通过调用 Express 接口 loginRoom 登录房间。 观众通过调用 Express 相关接口下载歌词、拉取混流、接收和解析房主发送的 SEI 信息等操作,中间则由业务服务器监听房间内歌曲、麦位的信息变更,并通知房间内所有成员。歌词下载完毕后,通过歌词 UI 组件进行逐行或者逐字歌词的展示。 3.2 重要业务模块 以下对房间管理、点歌(获取与分享歌曲)、合唱、歌词展示四个重要模块进行简单介绍。 房间管理 在线 KTV 中,一般不同的用户会在一个房间内进行 K 歌,并且还提供了一个当前的房间列表,这两部分共同构成了我们的房间管理系统,我们需搭配业务服务器和 Express SDK 来实现这个功能。 房主需在业务服务器创建房间获取对应的 roomID 和 userID 后,再创建 RTC 房间,然后通过调用 Express 接口 loginRoom 登录房间和 logoutRoom 接口退出房间。 API 调用时序可参考下图: 点歌(获取与分享歌曲) 点歌系统是在线 KTV 中关键部分,使用 Express SDK 提供的点歌能力,通过获取正版曲库中的音乐资源,并分享给房间内的其他用户进行合唱。详情请参考 点歌(获取和分享歌曲)。 点歌操作可以在榜单列表或者歌曲搜索结果进行。所点的歌曲将会进入已点队列,按照点歌时间逐首依次播放。 点歌人使用 songID 请求歌曲资源会触发一次计费,房间内其余人使用 token 请求歌曲资源则不会触发计费。 API 调用时序可参考下图: 合唱 在线 KTV 房间中的用户在合唱的过程中,人声和伴奏都要保持多端同步。 对于合唱者而言,歌曲的各端同步主要通过 SEI 消息实现。SEI 携带当前播放歌曲的 songID 以及歌曲播放进度 progress等,用于多端同步播放的信息。SEI 的发送时间间隔可以与播放器进度回调的时间间隔保持一致。 对于观众而言,歌曲和人声的同步通过Express SDK 提供的精准混流功能实现。 流管理是多人实时合唱中非常重要的一部分。房主、合唱者、观众的推拉流策略需要互相配合以达到较好的合唱效果。 通过 Express SDK 的精准网络时间获取接口,以及麦上其他合唱者约定合唱的精确时间,来进行播放伴奏和合唱,达到各合唱者之间的高度同步。详情请参考 合唱同步实现流程。 API 调用时序可参考下图: 合唱 流管理 歌词展示 我们提供了开箱即用的歌词 UI 组件,开发者可与 Express SDK(含版权音乐功能)搭配使用,快速展示歌词效果。详情可参考 歌词展示与同步。 集成ZEGO SDK 1 准备环境 在开始集成 ZEGO Express SDK 前,请确保开发环境满足以下要求: Android Studio 2020.3.1 或以上版本。 Android Studio 版本编号系统的变更请参考 Android Studio 版本说明。 Android SDK 25、Android SDK Build-Tools 25.0.2、Android SDK Platform-Tools 25.x.x 或以上版本。 Android 4.4 或以上版本,且支持音视频的 Android 设备。 Android 设备已经连接到 Internet。 2 项目准备 2.1 创建项目 进入即构官网,在【ZEGO控制台】创建项目,并申请有效的 AppID,这一步很关键,appid为应用的唯一标识,如身份证号,是应用的身份证明,用于明确你的项目及组织身份。zego提供的服务也是基于APP ID; App ID的获取方式很简单,只需3~5分钟,在即构官网-我的项目-创建即可。创建的项目信息可用于SDK的集成和配置; 2.2 Token 鉴权 登录房间时必须 使用 Token 鉴权 ,可参考 Token 鉴权教程 为了方便开发阶段的调试,开发者可直接在 ZEGO 控制台获取临时 Token(有效期为 24 小时) 来使用,详情请参考 控制台(新版) - 项目管理 中的 “项目信息”。 3 集成 SDK 3.1 项目设置 开始集成前,可参考如下步骤设置你的项目; 如已有项目,本步骤可忽略。 如需新建项目,可按照以下步骤创建你的新项目: 1.打开 Android Studio,选择 “File > New > New Project” 菜单。 2.填写项目名及项目存储路径。 3.其它按照默认设置,单击 “Next”,最后单击 “Finish” 完成新工程创建。 3.2 导入 SDK 目前支持的平台架构包括:armeabi-v7a、arm64-v8a、x86、x86_64。 在实现基本的实时音视频功能之前,需确保获取的sdk为最新版本,保证音视频功能体验为最优; 使用 JitPack 自动集成 SDK 进入项目根目录,打开 “build.gradle” 文件,在 “allprojects” 中加入如下代码。 ... allprojects { repositories { maven { url 'https://www.jitpack.io' } google() jcenter() } } 进入 “app” 目录,打开 “build.gradle” 文件,在 “dependencies” 中添加 implementation 'com.github.zegolibrary:express-video:2.+',这样能获取到最新的版本,如果需要下载指定版本,请从 https://jitpack.io/#zegolibrary/express-video 查询具体版本号,并将 2.+ 修改为指定的版本号。 ... dependencies { ... implementation 'com.github.zegolibrary:express-video:2.+' } 1. 从 **2.7.0** 版本开始,Zego 将使用 JitPack 代替 JCenter 作为 SDK 托管服务器,因此开发者需手动将 `build.gradle` 里的配置变更为 `'com.github.zegolibrary:express-video:2.+'` 2. JCenter **2021-03-31** 之后停止上传新版本 SDK,该服务将于 **2021-05-01 停用**,详情请参考 [Service End for JCenter](https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/)。 3. 从 **1.11.0** 版本开始,依赖的命令从 `implementation 'im.zego:express-engine-video:x.y.z'` 改为 `implementation 'im.zego:express-video:x.y.z'`。使用 **1.11.0 以下** 的版本不受影响,但后续不再从 “express-engine-video” 里更新,建议所有使用旧版本的开发者切换到 **1.11.0 或以上** 的版本进行集成。 4 设置权限 以上步骤集成已完成,为保证SDK运行效果更佳,需要在应用中设置所需的权限,步骤如下: 进入 “app/src/main” 目录,打开 “AndroidManifest.xml” 文件,添加权限。 android:glEsVersion="0x00020000" android:required="true" /> 因为 Android 6.0 在一些比较重要的权限上要求必须申请动态权限,不能只通过 “AndroidMainfest.xml” 文件申请静态权限。因此还需要参考执行如下代码,其中 “requestPermissions” 是 “Activity” 的方法。 String[] permissionNeeded = { "android.permission.CAMERA", "android.permission.RECORD_AUDIO"}; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) { requestPermissions(permissionNeeded, 101); } } 具体的权限说明如下: 其中非必要权限 “android.permission.READ_PHONE_STATE” 仅用于实现 SDK 的打断事件处理,因此只需在 AndroidMainfest.xml 文件中进行声明即可,不需要动态申请(业务方有需求则另外处理)。 5 防止混淆代码 在 “proguard-rules.pro” 文件中,为 SDK 添加 -keep 类的配置,防止混淆 SDK 公共类名称。 1 -keep class **.zego.**{*;} 与王心凌合唱在线K歌房实现了!!! 恭喜,王心凌在线K歌房实时合唱功能已完成,可下载甜心教主的热门歌曲:《爱你》《睫毛弯弯》,或者翻唱的《山海》。实现追星自由,也可与好友一起多人实时合唱畅享线上K歌体验。 获取更多文档、Demo、技术帮助 获取 SDK 开发文档、demo,可访问即构文档中心。 获取更多商务活动热门产品,可提交信息联系商务。 注册即构ZEGO开发者帐号,快速开始。
2024-05-10 17:08:54306阅读
基于ZEGO即构 SDK 实现iOS一对一音视频聊天应用
1 准备环境 在开始集成 ZEGO Express SDK 前,请确保开发环境满足以下要求: Xcode 12.0 或以上版本。 iOS 9.0 或以上版本且支持音视频的 iOS 设备。 iOS 设备已经连接到 Internet。 2 项目准备 2.1 创建项目 进入即构官网,在【ZEGO控制台】创建项目,并申请有效的 AppID,这一步很关键,appid为应用的唯一标识,如身份证号,是应用的身份证明,用于明确你的项目及组织身份。zego提供的服务也是基于APP ID; App ID的获取方式很简单,只需3~5分钟,在即构官网-我的项目-创建即可。创建的项目信息可用于SDK的集成和配置; 2.2 Token 鉴权 登录房间时必须 使用 Token 鉴权 ,可参考 Token 鉴权教程 为了方便开发阶段的调试,开发者可直接在 ZEGO 控制台获取临时 Token(有效期为 24 小时) 来使用,详情请参考 控制台(新版) - 项目管理 中的 “项目信息”。 3 集成 3.1 项目设置 开始集成前,可参考如下步骤设置你的项目; 如已有项目,本步骤可忽略。 如需新建项目,可按照以下步骤创建你的新项目: 启动 Xcode,在 “Welcome to Xcode” 窗口中单击 “Create a new Xcode project” 或选择 “File > New > Project” 菜单。在出现的表单中,选择 iOS 平台,并在 “Application” 下选择 “App” 2.填写表单并选取各个选项来配置项目,完成后,单击 “Next”。 必须提供 “Product Name” 和 “Organization Identifier”,用于创建 App 的唯一标识 “Bundle Identifier”。 3.选择项目存储路径,单击 “Create” 创建项目。 3.2 导入 SDK 使用 CocoaPods 自动集成 安装 CocoaPods 打开终端,进入项目根目录,执行 pod init 命令创建 Podfile 文件。 打开 Podfile 文件,在 “target” 下添加 po``d``'``Z``ego``E``xpress``Engine/V``ideo',需要将 “MyProject” 替换为开发者的 Target 名称。 target 'MyProject' do use_frameworks! pod 'ZegoExpressEngine/Video' end 4.执行 pod repo update 命令更新本地索引,确保能安装最新版本的 SDK,最新版本号请参考 下载 SDK 包 中的发布历史。 5.执行 pod install 命令安装 SDK。 4 实现流程 用户通过 ZEGO Express SDK 进行视频通话的基本流程为: 用户 A、B 加入房间,用户 B 预览并将音视频流推送到 ZEGO 云服务(推流),用户 A 收到用户 B 推送音视频流的通知之后,在通知中播放用户 B 的音视频流(拉流)。 整个音视频通话推拉流过程的 API 调用时序如下图: 4.1 初始化 1. 创建界面 根据场景需要,为你的项目创建视频通话的用户界面。我们推荐你在项目中添加如下元素: 本地视频窗口 远端视频窗口 结束通话按钮 2.引入头文件,准备基础工作 // 引入 ZegoExpressEngine.h 头文件 #import @interface ViewController () //拉取播放其他用户音视频流的 view @property (strong, nonatomic) UIView *remoteUserView; //开始视频通话的按钮 @property (strong, nonatomic) UIButton *startVideoTalkButton; //停止视频通话的按钮 @property (strong, nonatomic) UIButton *stopVideoTalkButton; @end - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; } - (void)setupUI { self.remoteUserView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 180, 250)]; self.remoteUserView.backgroundColor = [UIColor lightGrayColor]; [self.view addSubview:self.remoteUserView]; self.startVideoTalkButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:self.startVideoTalkButton]; self.startVideoTalkButton.frame = CGRectMake(100, self.view.bounds.size.height - 280, 150, 50); [self.startVideoTalkButton.titleLabel setFont:[UIFont systemFontOfSize:32]]; [self.startVideoTalkButton setTitle:@"开始通话" forState:UIControlStateNormal]; [self.startVideoTalkButton addTarget:self action:@selector(startVideoTalk:) forControlEvents:UIControlEventTouchUpInside]; self.stopVideoTalkButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:self.stopVideoTalkButton]; self.stopVideoTalkButton.frame = CGRectMake(100, self.view.bounds.size.height - 200, 150, 50); [self.stopVideoTalkButton.titleLabel setFont:[UIFont systemFontOfSize:32]]; [self.stopVideoTalkButton setTitle:@"停止通话" forState:UIControlStateNormal]; [self.stopVideoTalkButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; [self.stopVideoTalkButton addTarget:self action:@selector(stopVideoTalk:) forControlEvents:UIControlEventTouchUpInside]; } - (void)startVideoTalk:(UIButton *)button { [self createEngine]; [self loginRoom]; [self startPublish]; } 3. 创建引擎 调用 createEngineWithProfile 接口,将申请到的 AppID 传入参数 “appID”,创建引擎单例对象。 注册回调,可将实现了 ZegoEventHandler 的对象(例如 “self”)传入参数 “eventHandler”。 - (void)createEngine { ZegoEngineProfile *profile = [[ZegoEngineProfile alloc] init]; // 请通过官网注册获取,格式为:1234567890 profile.appID = ; //通用场景接入 profile.scenario = ZegoScenarioGeneral; // 创建引擎,并注册 self 为 eventHandler 回调。不需要注册回调的话,eventHandler 参数可以传 nil,后续可调用 "-setEventHandler:" 方法设置回调 [ZegoExpressEngine createEngineWithProfile:profile eventHandler:self]; } 6.2 登录房间 调用 loginRoom 接口登录房间。roomID 和 user 的参数由您本地生成,但是需要满足以下条件: 同一个 AppID 内,需保证 “roomID” 全局唯一。 同一个 AppID 内,需保证 “userID” 全局唯一,建议开发者将 “userID” 与自己业务的账号系统进行关联。 - (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 由用户自己的服务端生成,为了更快跑通流程,也可以通过即构控制台 https://console.zego.im/dashboard 获取临时的音视频 token roomConfig.token = @""; 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(@"房间登录失败"); } }]; } 登录状态(房间连接状态)回调 调用登录房间接口之后,您可通过监听 onRoomStateUpdate 回调实时监控自己在本房间内的连接状态。 3.3 预览自己的画面,并推送到 ZEGO 音视频云 1. 预览自己的画面 如果希望看到本端的画面,可调用 startPreview 接口设置预览视图,并启动本地预览。 2. 将自己的音视频流推送到 ZEGO 音视频云 在用户调用 loginRoom 接口后,可以直接调用 startPublishingStream 接口,传入 “streamID”,将自己的音视频流推送到 ZEGO 音视频云。您可通过监听 onPublisherStateUpdate 回调知晓推流是否成功。 “streamID” 由您本地生成,但是需要保证: 同一个 AppID 下,“streamID” 全局唯一。如果同一个 AppID 下,不同用户各推了一条 “streamID” 相同的流,后推流的用户推流失败。 - (void)startPublish { // 设置本地预览视图并启动预览,视图模式采用 SDK 默认的模式,等比缩放填充整个 View [[ZegoExpressEngine sharedEngine] startPreview:[ZegoCanvas canvasWithView:self.view]]; // 用户调用 loginRoom 之后再调用此接口进行推流 // 在同一个 AppID 下,开发者需要保证 “streamID” 全局唯一,如果不同用户各推了一条 “streamID” 相同的流,后推流的用户会推流失败。 [[ZegoExpressEngine sharedEngine] startPublishingStream:@"stream1"]; } 3.4 拉取其他用户的音视频 进行视频通话时,我们需要拉取到其他用户的音视频。 在同一房间内的其他用户将音视频流推送到 ZEGO 音视频云时,我们会在 onRoomStreamUpdate 回调中收到音视频流新增的通知,并可以通过 ZegoStream 获取到某条流的 “streamID”。 我们可以在该回调中,调用 startPlayingStream ,传入 “streamID” 拉取拉取播放该用户的音视频。您可通过监听 onPlayerStateUpdate 回调知晓是否成功拉取音视频。 // 房间内其他用户推流/停止推流时,我们会在这里收到相应流增减的通知 - (void)onRoomStreamUpdate:(ZegoUpdateType)updateType streamList:(NSArray *)streamList extendedData:(NSDictionary *)extendedData roomID:(NSString *)roomID { //当 updateType 为 ZegoUpdateTypeAdd 时,代表有音视频流新增,此时我们可以调用 startPlayingStream 接口拉取播放该音视频流 if (updateType == ZegoUpdateTypeAdd) { // 开始拉流,设置远端拉流渲染视图,视图模式采用 SDK 默认的模式,等比缩放填充整个View // 如下 remoteUserView 为 UI 界面上 View.这里为了使示例代码更加简洁,我们只拉取新增的音视频流列表中第的第一条流,在实际的业务中,建议开发者循环遍历 streamList ,拉取每一条音视频流 NSString *streamID = streamList[0].streamID; [[ZegoExpressEngine sharedEngine] startPlayingStream:streamID canvas:[ZegoCanvas canvasWithView:self.remoteUserView]]; } } 7 运行效果 音视频的基础功能已完成,接下来我们运行下效果,1步快速检验成果。 step1 , 与好友一起安装编译好的App,在手机上可以看到对方并进行通话互动。 完成以上,说明你成功啦! Enjoy与好友的欢乐时光! 获取更多文档、Demo、技术帮助 获取本文的Demo、开发文档、技术支持。 获取SDK的商务活动、热门产品。 注册即构ZEGO开发者帐号,快速开始。
2024-05-08 16:48:58332阅读
30分钟快速搭建秀场直播间
1 架构设计 秀场直播场景的主要架构如下图所示(以多人连麦直播互动为例): 2 准备环境 在开始集成 ZEGO Express SDK 前,请确保开发环境满足以下要求: Android Studio 2020.3.1 或以上版本。 Android Studio 版本编号系统的变更请参考Android Studio 版本说明。 Android SDK 25、Android SDK Build-Tools 25.0.2、Android SDK Platform-Tools 25.x.x 或以上版本。 Android 4.4 或以上版本,且支持音视频的 Android 设备。 Android 设备已经连接到 Internet。 3 集成 SDK 3.1 (可选)新建项目 此步骤以如何创建新项目为例,如果是集成到已有项目,可忽略此步。 打开 Android Studio,选择 “File > New > New Project” 菜单。 2.填写项目名及项目存储路径。 3.其它按照默认设置,单击 “Next”,最后单击 “Finish” 完成新工程创建。 3.2 导入 SDK 目前支持的平台架构包括:armeabi-v7a、arm64-v8a、x86、x86_64。 开发者可通过以下任意一种方式实现集成 SDK。 方式一:使用 JitPack 自动集成 SDK 进入项目根目录,打开 “build.gradle” 文件,在 “allprojects” 中加入如下代码。 ... allprojects { repositories { maven { url 'https://www.jitpack.io' } google() jcenter() } } 2.进入 “app” 目录,打开 “build.gradle” 文件,在 “dependencies” 中添加implementation 'com.github.zegolibrary:express-video:2.+',这样能获取到最新的版本,如果需要下载指定版本,请从https://jitpack.io/#zegolibrary/express-video查询具体版本号,并将2.+修改为指定的版本号。 ... dependencies { ... implementation 'com.github.zegolibrary:express-video:2.+' } 从2.7.0版本开始,Zego 将使用 JitPack 代替 JCenter 作为 SDK 托管服务器,因此开发者需手动将build.gradle里的配置变更为'com.github.zegolibrary:express-video:2.+' JCenter2021-03-31之后停止上传新版本 SDK,该服务将于2021-05-01 停用,详情请参考Service End for JCenter。 从1.11.0版本开始,依赖的命令从implementation 'im.zego:express-engine-video:x.y.z'改为implementation 'im.zego:express-video:x.y.z'。使用1.11.0 以下的版本不受影响,但后续不再从 “express-engine-video” 里更新,建议所有使用旧版本的开发者切换到1.11.0 或以上的版本进行集成。 方式二:复制 SDK 文件手动集成 请参考下载 SDK 包,下载最新版本的 SDK。 解压 SDK 至项目目录,如 “app/libs”。 3.添加 SDK 引用,进入到 “app” 目录,打开 “build.gradle” 文件。 在 “defaultConfig” 节点添加 “ndk” 节点,指定支持的平台类型。 ndk { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } 在 “android” 节点添加 “sourceSets” 节点,指定 “libs” 所在目录。 示例代码中 “libs” 目录仅为举例,开发者可根据实际路径填写。 ```gradle sourceSets { main { jniLibs.srcDirs = ['libs'] } } ``` * 在 “dependencies” 节点引入 “libs” 下所有的 jar。 implementation fileTree(dir: 'libs', include: ['*.jar']) 4 设置权限 根据实际应用需要,设置应用所需权限。 进入 “app/src/main” 目录,打开 “AndroidManifest.xml” 文件,添加权限。 android:glEsVersion="0x00020000" android:required="true" /> 因为 Android 6.0 在一些比较重要的权限上要求必须申请动态权限,不能只通过 “AndroidMainfest.xml” 文件申请静态权限。因此还需要参考执行如下代码,其中 “requestPermissions” 是 “Activity” 的方法。 String[] permissionNeeded = { "android.permission.CAMERA", "android.permission.RECORD_AUDIO"}; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) { requestPermissions(permissionNeeded, 101); } } 具体的权限说明如下: 其中非必要权限 “android.permission.READ_PHONE_STATE” 仅用于实现 SDK 的打断事件处理,因此只需在 AndroidMainfest.xml 文件中进行声明即可,不需要动态申请(业务方有需求则另外处理)。 5 防止混淆代码 在 “proguard-rules.pro” 文件中,为 SDK 添加-keep类的配置,防止混淆 SDK 公共类名称。 -keep class **.zego.**{*;} 6 实现流程 秀场直播场景的整体流程如下: 主播、观众均通过信令模块进行连接,信令模块可以控制当前业务房间内的直播流程,同步并通知各端当前的直播状态。 无论是否有连麦观众, 主播和观众均通过 ZEGO 音视频云服务进行推拉流。 观众请求与主播连麦后,信令模块会通知主播,并同步连麦者的个人信息。 主播接受连麦申请后,连麦观众开始推流,房间内所有成员将会接收到流更新通知,并拉取连麦观众的音视频流。 若连麦观众不再需要连麦,则向业务后台发起下麦请求。收到信令模块的下麦通知后,连麦观众停止推流,主播停止拉取该观众流,房间内的其他观众也停止拉流。 单主播推流,观众拉流、申请连麦、推流、下麦的详细流程图如下: 6.1 初始化 SDK 在使用 Express Video SDK 进行视频通话之前,需要初始化 SDK。由于初始化操作 SDK 时,内部处理的操作较多,建议开发者在 App 启动的时候进行。 /** 定义 SDK 引擎对象 */ ZegoExpressEngine engine; ZegoEngineProfile profile = new ZegoEngineProfile(); /** 请通过官网注册获取,格式为 123456789L */ profile.appID = appID; /** 64个字符,请通过官网注册获取,格式为"0123456789012345678901234567890123456789012345678901234567890123" */ profile.appSign = appSign; /** 通用场景接入 */ profile.scenario = ZegoScenario.GENERAL; /** 设置app的application 对象 */ profile.application = getApplication(); /** 创建引擎 */ engine = ZegoExpressEngine.createEngine(profile, null); 更多初始化 SDK 的细节请参考:快速开始 - 实现流程的 “3.1 创建引擎”。 6.2 登录直播房间 主播开始直播或观众观看直播前,需要先登录到直播房间,在收到登录房间成功的回调之后可以直接调用 SDK 的接口进行推拉流操作。 /** 创建用户 */ ZegoUser user = new ZegoUser("Anchor1"); /** 开始登录房间 */ engine.loginRoom("LiveRoom", user); 更多使用 SDK 实现登录直播房间的细节请参考:快速开始 - 实现流程的 “3.2 登录房间”。 6.3 单主播直播 6.3.1 主播开启预览并推流 主播向 ZEGO 音视频云服务推流,需要自己生成唯一的 “StreamID”,然后开始预览并推流。 // 开启预览 engine.startPreview(new ZegoCanvas(preview_view)); // 推流 engine.startPublishingStream("Anchor1"); 更多使用 SDK 实现预览和推流的细节请参考:快速开始 - 实现流程的 “3.3 推流”。 6.3.2 观众拉流 观众进入房间后,会收到 SDK 的流更新通知,从中筛选出主播流的 “StreamID” 进行拉流。 // 观众拉流 ZegoCanvas zegoCanvas = new ZegoCanvas(view); zegoCanvas.viewMode = ZegoViewMode.ASPECT_FILL; engine.startPlayingStream("Anchor1",zegoCanvas); 更多使用 SDK 实现拉流的细节请参考:快速开始 - 实现流程的 “3.4 拉流”。 6.4 观众连麦 6.4.1 观众推流 观众调用业务后台请求连麦接口,调用成功后,业务后台向主播发送请求连麦自定义信令。主播收到信令后,调用业务后台同意连麦接口,调用成功后,业务后台向房间内所有成员发送连麦成功的广播信令,连麦观众收到信令后,开始推流。 // 连麦观众推流 engine.startPublishingStream("Audience1"); 6.4.2 主播拉流 连麦观众推流后,房间内所有成员会收到 SDK 的流更新通知,主播获取连麦观众流的 StreamID 进行拉流。 房间内其他观众也在收到流更新回调时,获取连麦观众流的 StreamID 进行拉流。 // 主播拉流 ZegoCanvas zegoCanvas = new ZegoCanvas(view); zegoCanvas.viewMode = ZegoViewMode.ASPECT_FILL; engine.startPlayingStream("Audience1",zegoCanvas); 6.4.3 观众下麦 连麦观众调用业务后台的下麦接口,调用成功后,业务后台向房间内所有成员发送该观众下麦的广播信令。连麦观众收到信令后停止推流,房间内其他观众收到信令后停止拉流。 // 观众停止预览和结束推流 engine.stopPreview(); engine.stopPublishingStream(); // 房间内其他成员结束拉流 engine.stopPlayingStream("Audience1"); 更多使用 SDK 实现停止推拉流的细节请参考:快速开始 - 实现流程的 “3.6 停止推拉流”。 7 更多功能 7.1 美颜美型 基于 AI 视觉服务,提供美白、磨皮、锐化、红润等基础的美颜功能,支持大眼、瘦脸、小嘴、亮眼、白牙、瘦鼻等美型效果,打造独特自然的直播效果。详情请参考美颜、美型。 7.2 音乐音效 支持通过获取正版曲库资源,播放背景音乐,并展示变声混响多种趣味效果。详情请参考在线 KTV、变声/混响/立体声。 7.3 实时消息互动 通过 ZEGO 即时通讯服务,实时展示房间内的消息,例如发消息、进退房提示、互动通知等。详情请参考即时通讯。 7.4 送礼物 用户可向房间内主播或其他指定用户赠送礼物。详情请参考即时通讯。 获取优惠活动 近期有开发规划的开发者可上即构官网查看,恰逢即构七周年全线音视频产品1折的优惠,适合有预算要求的企业和个人开发工作室。 获取更多商务活动热门产品,也可提交信息联系商务;
2024-05-08 16:33:49308阅读
使用VUE+WebRTC快速实现简单的音视频通话
1 功能简介 本文将介绍如何快速使用 Vue 实现一个简单的实时音视频通话。 相关概念解释: ZEGO Express SDK:由 ZEGO 提供的实时音视频 SDK,能够为开发者提供便捷接入、高清流畅、多平台互通、低延迟、高并发的音视频服务。 推流:把采集阶段封包好的音视频数据流传输到 ZEGO 实时音视频云的过程。 拉流:从 ZEGO 实时音视频云将已有音视频数据流进行拉取的过程。 2 前提条件 在实现基本的实时音视频功能之前,请确保: 已在项目中集成 ZEGO Express SDK,详情请参考 快速开始 - 集成。 已在 ZEGO 控制台 创建项目,申请有效的 AppID 和 AppSign,详情请参考 控制台 - 项目管理。 3 示例源码下载 请参考 下载示例源码 获取源码。 相关源码请查看 “/express-demo-web/src/Examples/Framework/Vue” 目录下的文件。 4 使用步骤 当前项目使用的 Node 版本为 14.17.3,Vue 版本为 2.4.2。 以用户 A 拉取用户 B 的流为例,流程如下图: 整个推拉流过程的 API 调用时序如下图: 4.1 创建引擎 1. 创建界面 在创建引擎之前,推荐开发者添加以下界面元素,方便实现基本的实时音视频功能。 本地预览窗口 远端视频窗口 结束按钮 2. 创建引擎 创建 ZegoExpressEngine 引擎实例,将申请到的 AppID 传入参数 “appID”,将接入服务器地址传入参数 “server”。 “server” 为接入服务器地址,获取方式如下: 登录 ZEGO 控制台。 在对应项目下单击“查看”。 进入“项目配置”界面,在“项目信息”页签的“配置信息”中,单击 “ServerSecret” 后面的小眼睛按钮即可获取对应的接入服务器地址。 在 “/express-demo-web/src/Examples/Framework/Vue/index.html” 文件中引入 vue.js。 // 引入 vue.js 初始化实例。 new Vue({ el:'#page-wrapper', data: { zg: null }, methods:{ createZegoExpressEngine() { this.zg = new ZegoExpressEngine(appID, server); } } }) 3. 监听事件回调 如果需要注册回调,开发者可根据实际需要,实现 ZegoEvent(包含 ZegoRTCEvent 和 ZegoRTMEvent)中的某些方法,创建引擎后可通过调用 on 接口设置回调。 this.zg.on('roomStateChanged', (roomID, reason, errorCode, extendData) => { if (reason == ZegoRoomStateChangedReason.Logining) { // 登录中 } else if (reason == ZegoRoomStateChangedReason.Logined) { // 登录成功 //只有当房间状态是登录成功或重连成功时,推流(startPublishingStream)、拉流(startPlayingStream)才能正常收发音视频 //将自己的音视频流推送到 ZEGO 音视频云 } else if (reason == ZegoRoomStateChangedReason.LoginFailed) { // 登录失败 } else if (reason == ZegoRoomStateChangedReason.Reconnecting) { // 重连中 } else if (reason == ZegoRoomStateChangedReason.Reconnected) { // 重连成功 } else if (reason == ZegoRoomStateChangedReason.ReconnectFailed) { // 重连失败 } else if (reason == ZegoRoomStateChangedReason.Kickout) { // 被踢出房间 } else if (reason == ZegoRoomStateChangedReason.Logout) { // 登出成功 } else if (reason == ZegoRoomStateChangedReason.LogoutFailed) { // 登出失败 } }); 4.2 检测兼容性 在实现推拉流功能之前,开发者可以调用 checkSystemRequirements 接口检测浏览器的兼容性。 SDK 支持的浏览器兼容版本,请参考 下载示例源码 中的 “1 准备环境”。 const result = await this.zg.checkSystemRequirements(); // 返回的 result 为兼容性检测结果。 webRTC 为 true 时表示支持 webRTC,其他属性含义均可参考接口 API 文档 console.log(result); // { // webRTC: true, // customCapture: true, // camera: true, // microphone: true, // videoCodec: { H264: true, H265: false, VP8: true, VP9: true }, // screenSharing: true, // errInfo: {} // } 返回结果的各参数含义,请参考 ZegoCapabilityDetection 接口下的参数描述。 4.3 登录房间 1. 生成 Token 登录房间需要用于验证身份的 Token,获取方式请参考 使用 Token 鉴权。如需快速调试,可使用控制台生成临时 Token。 2. 登录房间 调用 loginRoom 接口,传入房间 ID 参数 “roomID”、“token” 和用户参数 “user”,根据实际情况传入参数 “config”,登录房间。 在登录房间之前,请先注册登录房间后需要监听的所有回调。成功登录房间后,即可接收相关的回调。 “roomID”、“userID” 和 “userName” 参数的取值都为自定义。 “roomID” 和 “userID” 都必须唯一,建议开发者将 “userID” 设置为一个有意义的值,可将其与业务账号系统进行关联。 // 登录房间,成功则返回 true // userUpdate 设置为 true 会开启监听 roomUserUpdate 回调,默认情况下不会开启该监听 const result = await this.zg.loginRoom(roomID, token, {userID, userName}, {userUpdate: true}); 3. 监听登录房间后的事件回调 根据实际应用需要,在登录房间前监听想要关注的事件通知,比如房间状态更新、用户状态更新、流状态更新等。 roomStateChanged:房间状态更新回调。登录房间后,当房间连接状态发生变更(如出现房间断开、登录认证失败等情况),SDK 会通过该回调通知。 roomUserUpdate:用户状态更新回调。登录房间后,当房间内有用户新增或删除时,SDK 会通过该回调通知。 只有调用 loginRoom 接口登录房间时传入 ZegoRoomConfig 配置,且 “userUpdate” 参数取值为 “true” 时,用户才能收到 roomUserUpdate 回调。 roomStreamUpdate:流状态更新回调。登录房间后,当房间内有用户新推送或删除音视频流时,SDK 会通过该回调通知。 只有调用 loginRoom 接口登录房间时传入 ZegoRoomConfig 配置,且 “userUpdate” 参数取值为 “true” 时,用户才能收到 roomUserUpdate 回调。 通常情况下,如果某个用户想要播放其他用户推送的视频,可以在收到流状态更新(新增)的回调中,调用 startPlayingStream 接口拉取远端推送的音视频流。 // 房间状态更新回调 this.zg.on('roomStateChanged', (roomID, reason, errorCode, extendData) => { if (reason == ZegoRoomStateChangedReason.Logining) { // 登录中 } else if (reason == ZegoRoomStateChangedReason.Logined) { // 登录成功 //只有当房间状态是登录成功或重连成功时,推流(startPublishingStream)、拉流(startPlayingStream)才能正常收发音视频 //将自己的音视频流推送到 ZEGO 音视频云 } else if (reason == ZegoRoomStateChangedReason.LoginFailed) { // 登录失败 } else if (reason == ZegoRoomStateChangedReason.Reconnecting) { // 重连中 } else if (reason == ZegoRoomStateChangedReason.Reconnected) { // 重连成功 } else if (reason == ZegoRoomStateChangedReason.ReconnectFailed) { // 重连失败 } else if (reason == ZegoRoomStateChangedReason.Kickout) { // 被踢出房间 } else if (reason == ZegoRoomStateChangedReason.Logout) { // 登出成功 } else if (reason == ZegoRoomStateChangedReason.LogoutFailed) { // 登出失败 } }); // 用户状态更新回调 this.zg.on('roomUserUpdate', (roomID, updateType, userList) => { console.warn( `roomUserUpdate: room ${roomID}, user ${updateType === 'ADD' ? 'added' : 'left'} `, JSON.stringify(userList), ); }); // 流状态更新回调 this.zg.on('roomStreamUpdate', async (roomID, updateType, streamList, extendedData) => { if (updateType == 'ADD') { // 流新增,开始拉流 } else if (updateType == 'DELETE') { // 流删除,停止拉流 } }); 4.4 推流 1. 创建流 a. 开始推流前需要创建本端的音视频流,调用 createStream 接口,默认会采集摄像头画面和麦克风声音。 调用 createStream 接口后,需要等待 ZEGO 服务器返回流媒体对象才能执行后续操作。 HTML 上创建媒体流播放组件的容器 。 创建流后播放媒体流。 // 调用 createStream 接口后,需要等待 ZEGO 服务器返回流媒体对象才能执行后续操作 const localStream = await this.zg.createStream(); // 创建媒体流播放组件 const localView = this.zg.createLocalStreamView(localStream); // "local-video" 为容器 DOM 元素 ID。 localView.play("local-video", {enableAutoplayDialog:true}); b. 设置音视频采集参数 可根据需要通过 createStream 接口中的如下属性设置音视频相关采集参数,详情可参考 自定义视频采集: camera:摄像头麦克风采集流相关配置 screen:屏幕捕捉采集流相关配置 custom:第三方流采集相关配置 2. 开始推流 调用 startPublishingStream 接口,传入流 ID 参数 “streamID” 和创建流得到的流对象 “localStream”,向远端用户发送本端的音视频流。 “streamID” 参数的取值为自定义,需要在整个 AppID 内全局唯一。 若需要推多条流,则多次调用 startPublishingStream 接口即可,需确保每条流的 “streamID” 不相同。 // localStream 为创建流获取的 MediaStream 对象 this.zg.startPublishingStream(streamID, localStream) 3. 监听推流后的事件回调 根据实际应用需要,在推流后监听想要关注的事件通知,比如推流状态更新、推流质量等。 publisherStateUpdate:推流状态更新回调。调用推流接口成功后,当推流状态发生变更(如出现网络中断导致推流异常等情况),SDK 在重试推流的同时,会通过该回调通知。 publishQualityUpdate:推流质量回调。调用推流接口成功后,定时回调音视频流质量数据(如分辨率、帧率、码率等)。 this.zg.on('publisherStateUpdate', result => { // 推流状态更新回调 // ... }) this.zg.on('publishQualityUpdate', (streamID, stats) => { // 推流质量回调 // ... }) 4.5 拉流 1. 开始拉流 调用 startPlayingStream 接口,根据传入的流 ID 参数 “streamID”,拉取远端已推送到 ZEGO 服务器的音视频画面。 远端用户推送的 “streamID” 可以从 roomStreamUpdate 回调中获得。 HTML 上创建媒体流播放组件的容器 。 将拉取到远端流在界面播放。 const remoteStream = await this.zg.startPlayingStream(streamID); // 创建媒体流播放组件 const remoteView = this.zg.createRemoteStreamView(remoteStream); remoteView.play("remote-video", {enableAutoplayDialog:true}); “streamID” 需要在整个 AppID 内全局唯一。 2. 监听拉流后的事件回调 根据实际应用需要,在拉流后监听想要关注的事件通知,如拉流状态变更、拉流质量等。 playerStateUpdate:拉流状态更新回调。调用拉流接口成功后,当拉流状态发生变更(如出现网络中断导致推流异常等情况),SDK 在重试推流的同时,会通过该回调通知。 playQualityUpdate:拉流质量回调。调用拉流接口成功后,定时回调音视频流质量数据(如分辨率、帧率、码率等)。 this.zg.on('playerStateUpdate', result => { // 拉流状态更新回调 // ... }) this.zg.on('playQualityUpdate', (streamID,stats) => { // 拉流质量回调 }) 4.6 体验实时音视频功能 在真机中运行项目,运行成功后,可以看到本端视频画面。 为方便体验,ZEGO 提供了一个 Web 端调试示例,在该页面下,输入相同的 AppID、RoomID,输入一个不同的 UserID,即可加入同一房间与真机设备互通。当成功开始音视频通话时,可以听到远端的音频,看到远端的视频画面。 4.7 停止推拉流 1. 停止推流 调用 stopPublishingStream 接口停止向远端用户发送本端的音视频流。 this.zg.stopPublishingStream(streamID) 2. 销毁流 调用 destroyStream 接口销毁创建的流数据,销毁流后开发需自行销毁 video(停止采集)。 // localStream 是调用 createStream 接口获取的 MediaStream 对象 this.zg.destroyStream(localStream) 3. 停止拉流 调用 stopPlayingStream 接口停止拉取远端推送的音视频流。 this.zg.stopPlayingStream(streamID) 4.8 退出房间 调用 logoutRoom 接口退出房间。 this.zg.logoutRoom(roomID) 获取更多支持 获取本文的Demo、开发文档、技术支持,访问即构文档中心 近期有开发规划的开发者可上即构官网查看,恰逢即构七周年全线音视频产品1折的优惠,联系商务获取RTC产品优惠;
2024-05-08 16:12:26452阅读
音视频解决方案(二):直播电商场景最佳实践
功能实现流程 本文介绍使用ZEGO SDK 开发电商场景的小程序,具备音视频直播、IM互动、商品列表推送、美颜等功能,可满足商家多种直播卖货需求,可参考该组件实现自己的需求。 若小程序具备符合live-pusher、live-player的类目,则可以使用live-pusher和live-player,live-room 的isNative属性传入true。详细流程可参考 快速开始 除此之外,若具备“电商平台”或“教育”类目,则可以使用插件“即构直播助手”的zego-pusher 和 zego-player,isNative 属性传入false。插件的使用详见 小程序直播插件 音视频直播:提供高清低延时的直播体验,支持设置最大、最小码率,自动适配标清、高清、超清分辨率,直播流媒体可采用低延迟,直播延时远低于CDN分发,实现主播语音画面、商品列表、观众IM消息三端同步; IM互动:提供IM消息互动功能,观众发送文字消息与主播互动,支持消息实时滚动刷新;消息的使用可参考 IM 商品列表:提供商品列表推送功能,商家可以自定义商品的相关信息(简介、图片、列表、链接等),生成商品列表,主播直播时可同步推送列表中的商品链接,引导观众下单购买; 美颜滤镜:支持美颜功能,帮助改善非专用直播间的光线、清晰度等难题。 设备控制:支持切换摄像头、麦克风。 集成SDK + 插件 详见 集成SDK + 插件 推拉流 推流步骤如下: 触发推流 调用 SDK 的 startPublishingStream 获取 streamID 对应的推流地址 在 SDK 的回调 onStreamUrlUpdate 中获推流地址 将步骤 3 中获取的推流地址设置为 zego-pusher 的 url 获取推流组件实例,然后调用实例 的 start() 录制视频 在 bindstatechange 绑定的回调函数中,调用 SDK 提供的 API updatePlayerState 将推流事件透传给 SDK 在 SDK 提供的 publisherStateUpdate 回调中处理推流的开始、失败状态 拉流步骤如下: 触发拉流 调用 SDK 的 startPlayingStream 获取 streamID 对应的播放地址 在 SDK 的回调 onStreamUrlUpdate 中获取拉流地址 将步骤 3 中获取的推流地址设置为 zego-player 的 url, 流ID设置为sid 获取拉流组件实例,然后调用实例 的 play() 播放视频 或者设置拉流组件的autoplay 属性为true,实现自动拉流。 在 bindstatechange 绑定的回调函数中,调用 SDK 提供的 API updatePlayerState 将推流事件透传给 SDK 在 SDK 提供的 onPlayStateUpdate 回调中处理播推、拉流的开始、失败状态 商品推送 提供商品列表推送功能,商家可以自定义商品的相关信息(简介、图片、列表、链接等),生成商品列表,主播直播时可同步推送列表中的商品链接,引导观众下单购买; 在page/room/index.js中,有一个商品列表,客户可以自定义商品的相关信息(简介、图片、价格、链接等),并提供符合相应数据格式的接口。商品链接可以跳到小程序内的商品详情页,也可以使用web-view链接到自己的域名下的商品页面。 商品结构如下: 1 2 3 4 5 6 7 8 9 10 11 12 { name: 'Givenchy/纪梵希高定香榭天鹅绒唇膏', img: '../../resource/m0.png', price: '345', id: 0, link: { path: "../web/index", extraDatas: { url: 'https://shop-ecommerce.yunyikao.com/product.html' } } }, 注意: 使用webview需要在小程序管理后台配置业务域名,此时需要下载一个校验文件,将该文件放置于域名根目录下。 域名配置路径:微信公众平台 -> 设置 -> 开发设置 -> 业务域名。如图所示: IM 提供IM消息互动功能,观众发送文字消息与主播互动,支持消息实时滚动刷新;消息的使用可参考 IM 美颜 支持美颜功能,通过属性beauty、whiteness控制,详见 API文档 设备控制 支持切换摄像头、麦克风。 demo 中相关功能在组件components/live-room中,在pages/room 页面中引入了live-room。 live-room 组件的相关属性如下: 登录房间需要token,在开发者的业务服务器实现token逻辑,详见房间登录安全。 示例demo 中有房间列表只是demo展示用的,客户需要根据业务逻辑在自己的服务端实现。 获取更多ZEGO SDK技术支持,欢迎扫码了解~
2024-05-08 15:37:03374阅读
音视频解决方案(一):直播电商场景方案
1 场景介绍 1.1 场景说明 即构电商直播解决方案包含即构电商助手及相关业务组件,提供音视频直播、主播美颜、房间消息、商品推送等功能,帮助开发者快速构建自有电商直播小程序。 1.2 场景优势 即构小程序电商直播提供高清低延时的直播体验,支持设置最大、最小码率,自动适配标清、高清、超清分辨率,直播流媒体可采用低延迟,直播延时远低于CDN分发,实现主播语音画面、商品列表、观众IM消息三端同步。 2 功能列表 主要功能 功能描述 音视频直播 高清低延迟的直播体验,可采用低延迟分发和CDN分发两种模式 IM消息 直播间内的主播和观众可使用文字进行互动交流 房间人数 实时展示直播间人数 商品推送 主播向观众推送商品信息 获取更多ZEGO SDK技术支持,扫码了解更多详情~
2024-05-08 15:26:28327阅读
基于 即构 ZIM SDK 实现APP实时聊天功能
ZEGO 提供 ZIM + RTC 服务联动的场景解决方案,公开语聊房、秀场直播等业务场景搭建的示例源码,帮助开发者能在极短的时间内搭建完美的业务场景。 ZIM SDK 提供了如下接入方案: 在此方案中,您需要通过您自己的业务系统实现以下业务逻辑: 搭建客户端的用户管理逻辑,并下发用户 ID 用于客户端登录。 鉴权 Token,建议由您的业务后台自行实现,保证鉴权数据安全。 2 前提条件 在使用 ZIM SDK 前,请确保: 开发环境满足以下要求: Android Studio 2.1 或以上版本。 Android SDK 25、Android SDK Build-Tools 25.0.2、Android SDK Platform-Tools 25.x.x 或以上版本。 Android 9.0 或以上版本,且支持音视频的 Android 设备或模拟器(推荐使用真机)。 已在 ZEGO 控制台 创建项目,获取到了接入 ZIM SDK 服务所需的 AppID 和 ServerSecret。ZIM 服务权限不是默认开启的,使用前,请先在 ZEGO 控制台 自助开通 ZIM 服务(详情请参考 项目管理 - 即时通讯)、或联系 ZEGO 技术支持开通。 已获取登录 SDK 所需的 Token,详情请参考 使用 Token 鉴权。 3 集成 SDK 3.1 新建项目 打开 Android Studio,选择 “File > New > New Project” 菜单。 2.填写项目名及项目存储路径。 3.其它按照默认设置,单击 “Next”,最后单击 “Finish” 完成新工程创建。 3.2 导入 SDK 目前支持的平台架构包括:arm64-v8a、armeabi-v7a、x86、x86_64。 开发者可通过以下任意一种方式实现集成 SDK。 方式一:使用 JitPack 自动集成 SDK 进入项目根目录,打开 “build.gradle” 文件,在 “allprojects” 中加入如下代码。 ... allprojects { repositories { maven { url 'https://www.jitpack.io' } google() jcenter() } } 2.进入 “app” 目录,打开 “build.gradle” 文件,在 “dependencies” 中添加 implementation 'com.github.zegolibrary:zim:x.y.z'。“x.y.z” 为 SDK 的版本号,请参考 发布日志 中的发布历史获取。 ... dependencies { ... // x.y.z 请填写具体版本号,如:1.2.0 // 可通过 SDK 发布历史取得最新版本号 implementation 'com.github.zegolibrary:zim:x.y.z' } 方式二:复制 SDK 文件手动集成 请参考 下载 SDK,下载最新版本的 SDK。 将 SDK 包解压至项目目录下,例如 “app/libs”。 3.添加 SDK 引用。进入到 “app” 目录,打开 “build.gradle” 文件。 在 “defaultConfig” 节点添加 “ndk” 节点,指定支持的平台类型。 ndk { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64', 'x86' } 2.在 “android” 节点添加 “sourceSets” 节点,指定 “libs” 所在目录。 示例代码中 “libs” 目录仅为举例,开发者可根据实际路径填写。 ```gradle sourceSets { main { jniLibs.srcDirs = ['libs'] } } ``` 在 “dependencies” 节点引入 “libs” 下所有的 jar。 ```gradle implementation fileTree(dir: 'libs', include: ['*.jar']) ``` 3.3 设置权限 开发者可以根据实际应用需要,设置应用所需权限。 进入 “app/src/main” 目录,打开 “AndroidManifest.xml” 文件,添加权限。 3.4 防止混淆代码 在 “proguard-rules.pro” 文件中,为 SDK 添加 -keep 类的配置,防止混淆 SDK 公共类名称。 -keep class **.zego.**{*;} 4 实现基本收发消息 以下流程中,我们以客户端 A 和 B 的消息交互为例: 4.1 实现流程 请参考 跑通示例源码 获取源码,相关功能的源码请查看 “app/src/main/java/im/zego/zimexample/ui/room/ZIMPeerSessionActivity” 目录下的文件。 1. 导入类文件 在项目文件中引入类文件。 import im.zego.zim.ZIM; 2. 创建 ZIM 实例 首先我们需要在 SDK 中创建 ZIM 实例,一个实例对应的是一个用户,表示一个用户以客户端的身份登录系统。 例如,客户端 A、B 分别调用 create 接口,传入在 2 前提条件 中获取到的 AppID,创建了 A、B 的实例: // 创建 ZIM 对象,传入 APPID 与 Android 中的 Application zim = ZIM.create(appID, application); ZIM 创建单例的示例 由于大多数开发者,在整个流程中,只需要将 ZIM 实例化一次,因此 ZEGO 建议您将 ZIM 单例化并保存。 创建一个 SDKManager 类,在该类中声明并实现了一个 “sharedInstance” 静态方法,该方法将会在首次调用时创建并返回一个 SDKManager 的对象,在该对象中调用 ”create“,此后在项目的任意位置导入 SDKManager 类,调用 “SDKManager.sharedInstance().zim” 将会返回 zim 对象。 public class SDKManager { private static SDKManager sdkManager; public ZIM zim; public static SDKManager sharedInstance() { if (sdkManager == null) { synchronized (SDKManager.class) { if (sdkManager == null) { sdkManager = new SDKManager(); } } } return sdkManager; } public void create(Application application) { zim = ZIM.create(ZegoAppID.appID, application); } } 3. 设置 setEventHandler 回调 在客户端登录前,开发者可以通过调用 setEventHandler 接口,自定义 ZIM 中的事件回调,接收到 SDK 异常、消息通知回调等的通知。 zim.setEventHandler(new ZIMEventHandler() { @Override public void onReceivePeerMessage(ZIM zim, ArrayList messageList, String fromUserID) { // 收到“单聊”通信的消息回调 } }); 4. 登录 ZIM 创建实例后,客户端 A 和 B 需要登录 ZIM,只有登录成功后才可以开始发送、接收消息、更新 Token 等。 客户端需要使用各自的用户信息和 Token 进行登录。调用 login 接口进行登录,传入用户信息 ZIMUserInfo 对象,以及在 2 前提条件 中获取到的 Token 进行鉴权,鉴权通过后才能登录成功。 “userID”、“userName” 支持开发者自定义规则生成。建议开发者将 “userID” 设置为一个有意义的值,可将其与自己的业务账号系统进行关联。 如果 Token 过期,需要在 tokenWillExpire 即将过期回调接口中,调用 renewToken 接口,更新 Token 后才能正常使用 SDK。 // 登录时,需要开发者 按照 "使用 Token 鉴权" 文档生成 token 即可 // userID 和 userName,最大 32 字节的字符串。仅支持数字,英文字符 和 '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '=', '-', '`', ';', '’', ',', '.', '', '/', '\'。 ZIMUserInfo zimUserInfo = new ZIMUserInfo(); zimUserInfo.userID = userID; zimUserInfo.userName = userName; zim.login(zimUserInfo, token, new ZIMLoggedInCallback() { @Override public void onLoggedIn(ZIMError error) { // 开发者可根据 ZIMError 来判断是否登录成功。 } }); 5. 发送单聊消息 客户端 A 登录成功后,可以向客户端 B 发送消息。 目前 ZIM 支持的消息类型如下: 客户端 A 可以调用 sendPeerMessage 接口,传入客户端 B 的 userID、消息内容等信息,即可发送一条消息到 B 的客户端,同时可以通过 onMessageSent 接口的回调信息,判断消息是否发送成功。 // 发送“单聊”通信的信息 String toUserID = "xxxx"; ZIMTextMessage zimMessage = new ZIMTextMessage(); zimMessage.message = "消息内容"; ZIMMessageSendConfig config = new ZIMMessageSendConfig(); // 消息优先级,取值为 低:1 默认,中:2,高:3 config.priority = ZIMMessagePriority.LOW; // 设置消息的离线推送配置 ZIMPushConfig pushConfig = new ZIMPushConfig(); pushConfig.title = "离线推送的标题"; pushConfig.content= "离线推送的内容"; pushConfig.extendedData = "离线推送的扩展信息"; config.pushConfig = pushConfig; zim.sendPeerMessage(zimMessage, toUserID, config, new ZIMMessageSentCallback() { @Override public void onMessageSent(ZIMMessage zimMessage, ZIMError error) { // 开发者可以通过该回调监听消息是否发送成功。 } }); 6. 接收单聊消息 客户端 B 登录 ZIM 后,将会收到在 setEventHandler 回调中设置的 onReceivePeerMessage 监听接口,收到客户端 A 发送过来的消息。 收到消息时,由于类型是基类,首先需要判断消息类型是 Text 还是 Command,开发者需要强转基类为具体的子类,然后从 message 字段获取消息内容。 zim.setEventHandler(new ZIMEventHandler() { @Override public void onReceivePeerMessage(ZIM zim, ArrayList messageList, String fromUserID) { for (ZIMMessage zimMessage : messageList) { if (zimMessage instanceof ZIMTextMessage) { ZIMTextMessage zimTextMessage = (ZIMTextMessage) zimMessage; Log.e(TAG, "收到的消息:"+ zimTextMessage.message); } } } }); 7. 退出登录 如果客户端需要退出登录,直接调用 logout 接口即可。 zim.logout(); 8. 销毁 ZIM 实例 如果不需要 ZIM 实例,可直接调用 destroy 接口,销毁实例。 zim.destroy(); 4.2 API 时序图 通过以上的实现流程描述,API 接口调用时序图如下: 获取更多ZEGO SDK技术支持: ZIM不仅具备全平台互动、消息海量并发、合规安全可靠等产品特性。同时还可结合即构 RTC SDK实现各类音视频场景的用户互动,满足Avatar , 直播,语聊房等实时互动场景,扫码了解更多~
2024-04-17 18:04:25320阅读
VUE实现Web端多人语音视频聊天
1 多人语音聊天功能介绍 本文展示了如何使用 ZEGO Express SDK 构造多人音视频通话场景,即实现多对多实时音视频聊天互动。用户可在房间内与其余用户进行实时音视频通话,互相推拉流。该场景可用于多人实时音视频聊天、多人视频会议等。 2 Web端实现多人语音聊天准备工作 在应用多人音视频通话场景之前,请确保: 已在项目中集成 ZEGO Express SDK,实现基本的实时音视频功能,详情请参考 快速开始 - 集成 和 快速开始 - 实现流程。 已在 ZEGO 控制台 创建项目,并申请有效的 AppID,详情请参考 控制台 - 项目管理 中的“项目信息”。 3 vue集成语音聊天示例源码下载 请参考 下载示例源码 获取源码。 相关源码请查看ZEGO Express SDK “src/Examples/Scenes/VideoForMultipleUsers” 目录下的文件。 4 ZEGO音视频SDK使用步骤 本节将介绍如何使用 ZEGO Express SDK 实现多人视频通话。 流程图如下: API 调用时序图如下: ZEGO Express SDK 可支持多人视频通话,如上时序图以 2 名房间成员间的实时视频通话为例,建议开发者参考上述流程设计自己的多人实时视频通话场景。 4.1 创建多人音视频聊天引擎实例 创建 ZegoExpressEngine 引擎实例,将申请到的 AppID 传入参数 “appID”,将接入服务器地址传入参数 “server”。 “server” 为接入服务器地址,获取方式如下: 登录 ZEGO 控制台。 在对应项目下单击“查看”。 进入“项目配置”界面,在“项目信息”页签的“配置信息”中,单击 “ServerSecret” 后面的小眼睛按钮即可获取对应的接入服务器地址。 const zg = new ZegoExpressEngine(appID, server); 4.2 多人语音聊天开启房间内用户变化通知 开发者需在每位用户调用 loginRoom 接口登录房间时,将 ZegoRoomConfig 中的 “userUpdate” 设置为 “true” ,用于接收其他用户进出房间的回调通知(即 roomUserUpdate。 const isLogin = await zg.loginRoom( roomID, token, { userID }, { userUpdate: true } ); 4.3 监听回调事件 为实现多人视频通话功能,需要监听房间内用户和流的增减并做出相应处理,开发者可根据实际需要,实现 ZegoEvent(包含 ZegoRTCEvent 和 ZegoRTMEvent)中的某些方法,创建引擎后可通过调用 on) 接口设置回调。 4.3.1 监听房间内的用户变化 只有调用 loginRoom 登录房间时设置了关注用户变化,即 ZegoRoomConfig 中的 “userUpdate” 设置为 “true”(默认值为 “false”)时,才能监听 roomUserUpdate 回调。 为了监听房间内的用户变化,需注册 roomUserUpdate 回调,已登录房间内用户的新增和删除都会触发该回调,开发者可以根据实际需要在回调中实现自己的业务逻辑。 回调中 “updateType” 参数指明了房间内用户变化的类型,该参数取值如下: 用户首次登录房间时,若此房间内已存在其他用户,该新登录用户会通过此回调接收到新增类型的用户列表,即 “updateType” 为 “ADD” 的回调,该用户列表为房间内已存在的用户。 zg.on('roomUserUpdate', (roomID, updateType, userList) => { console.log('roomUserUpdate roomID ', roomID, streamList); if (updateType === 'ADD') { // update view } else if(updateType == 'DELETE') { // update view } }); 4.3.2 多人语音聊天监听房间内的流变化 当某条流被删除时,如果开发者正在调用 startPlayingStream 接口拉取该流,请调用 stopPlayingStream 接口停止拉流,否则 SDK 会报拉流错误。 为监听房间内的流变化,需注册 roomStreamUpdate 回调,已登录房间内流的新增和删除都会触发该回调,开发者可以根据实际需要在回调中实现自己的业务逻辑。 回调中 “updateType” 参数指明了房间内流变化的类型,该参数取值如下: 用户首次登录房间时,若此房间内存在其他用户正在推流,会接收到流新增列表,即 “updateType” 为 “ADD” 的回调。 zg.on('roomStreamUpdate', (roomID, updateType, streamList) => { console.log('roomStreamUpdate roomID ', roomID, streamList); if(updateType === 'ADD') { // update view } else if(updateType == 'DELETE') { // update view } }); 4.3 推流、拉流、登录房间其他操作 请参考 快速开始 - 实现流程 依次完成登录房间、推流和拉流相关操作。 5 API 参考列表 6 获取音视频SDK更多帮助 获取本文的Demo、开发文档、技术支持,访问即构文档中心 近期有开发规划的开发者可上即构官网查看,恰逢即构七周年全线音视频产品1折的优惠,联系商务获取RTC产品优惠,或者扫码在线咨询~
2024-04-12 17:06:31382阅读
预约专家解决问题
提交后鲸选型专家顾问会联系您
您的问题是?
您的联系方式
商务咨询
运营咨询
电话沟通