Android端实现多人视频语音聊天|音视频开发
1 多人视频通话功能
本文展示了如何使用 即构实时音视频SDK ZEGO Express SDK 构造多人视频通话场景,即实现多对多实时音视频互动。用户可在房间内与其余用户进行实时视频通话,互相推拉流。该场景可用于多人实时视频聊天、视频会议等。

2 多人语音通话的前提条件
在应用多人视频语音通话场景之前,请确保:
- 已在项目中集成 ZEGO Express SDK,实现基本的实时音视频功能,详情请参考 快速开始 - 集成 和 快速开始 - 实现视频通话。
- 已在 ZEGO 控制台 创建项目,并申请有效的 AppID 和 AppSign,详情请参考 控制台 - 项目管理 中的“项目信息”。
3 安卓端多人语音通话的示例源码下载
请参考 下载示例源码 获取源码。
相关源码请查看 “/ZegoExpressExample/Scenes/src/main/java/im/zego/Scenes/VideoForMultipleUsers” 目录下的文件。
4 即构多人语音通话SDK的使用步骤
本节将介绍如何使用 ZEGO Express SDK 实现多人视频通话,流程图如下:

4.1 多人语音聊天SDK创建引擎
定义 SDK 引擎对象,调用 createEngine 接口,将申请到的 AppID 和 AppSign 传入参数 “appID” 和 “appSign”,创建引擎单例对象。
如果需要注册回调代理,可将实现了 IZegoEventHandler 的对象传入参数 “eventHandler”。如果不需要注册回调代理,可将 “null” 传入参数 “eventHandler”,创建引擎后仍需要注册回调时可通过调用 setEventHandler 接口设置回调代理。
/** 定义 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);
4.2 多人视频通话功能开启房间内用户变化通知
开发者需在每位用户登录房间时将 ZegoRoomConfig 中的 “isUserStatusNotify” 设为 “true”,用于接收其他用户进出房间的回调通知。
ZegoRoomConfig RoomConfig = new ZegoRoomConfig();
RoomConfig.isUserStatusNotify = true;
// 登录房间
engine.loginRoom(roomID, user, RoomConfig);
4.3 多人视频通话预览自己的画面,并推送到远端
在用户调用 loginRoom 之后,可以调用 startPublishingStream 接口,传入 “streamID”,将自己的音视频流推送到 ZEGO 音视频云。您可通过回调 setEventHandler 监听 onPublisherStateUpdate 回调知晓推流是否成功。
如果希望看到自己的画面,可调用 startPreview 接口设置预览视图,并启动本地预览。
“streamID” 由您本地生成,但是需要保证:同一个 AppID 下,“streamID” 全局唯一。如果同一个 AppID 下,不同用户各推了一条 “streamID” 相同的流,会导致后推流的用户推流失败。
//进行预览和推流
engine.startPreview(new ZegoCanvas(preview));//preview 为一个View 对象,开发者可以根据业务自定义,一般常用的是TextureView对象
engine.startPublishingStream("YOUR_STREAM_ID");//用户本端的StreamID
4.4 多人视频通话拉取音视频流
4.4.1 多人视频聊天拉取其他用户的音视频
进行视频通话时,我们需要拉取到其他用户的音视频。
onRoomStreamUpdate :在同一房间内的其他用户将音视频流推送到 ZEGO 音视频云时,我们会在此回调中收到音视频流新增的通知。
我们可以在该回调中,调用 startPlayingStream,传入 “streamID” 拉取播放该用户的音视频。您可通过监听 onPlayerStateUpdate 回调知晓是否成功拉取音视频。
4.4.2 多人语音聊天展示用户进出房间的信息
onRoomUserUpdate 回调可以用于监听房间内的用户变化,房间内其他用户进入或退出都会触发该回调。
房间人数大于 500 人的情况下 onRoomUserUpdate 回调不保证有效。若业务场景存在房间人数大于 500 的情况,不应依赖于该回调设计业务逻辑。若有在房间人数大于 500 时使用该回调的需求,请联系 ZEGO 技术支持。
4.4 的代码示例如下:
engine.setEventHandler(new IZegoEventHandler() {
@Override
public void onRoomUserUpdate(String roomID, ZegoUpdateType updateType, ArrayList<ZegoUser> userList) {
super.onRoomUserUpdate(roomID, updateType, userList);
//房间用户变化回调,本示例是以toast为展示示例,实际业务流程需开发者按需设计
if(updateType == ZegoUpdateType.ADD){
// 当 “updateType” 为 “ZegoUpdateTypeADD” 时,用户可以拉取 userList 里的用户进行处理
for(ZegoUser user : userList){
//进行Toast展示
Toast.makeText(myActivity,user.userID+"加入房间",Toast.LENGTH_SHORT).show();//myActivity为一个content对象,若在activity中可使用该Activity为参数
}
}else{
// 当 “updateType” 为 “ZegoUpdateTypeDelete” 时,用户可以拉取 userList 里的用户进行处理
for(ZegoUser user : userList){
//进行Toast展示
Toast.makeText(myActivity,user.userID+"加入房间",Toast.LENGTH_SHORT).show();//myActivity为一个content对象,若在activity中可使用该Activity为参数
}
}
}
@Override
public void onRoomStateUpdate(String roomID, ZegoRoomState state, int errorCode, JSONObject extendedData) {
//房间状态回调
super.onRoomStateUpdate(roomID, state, errorCode, extendedData);
if(state == ZegoRoomState.CONNECTED){
//可以根据实际业务进行设计
}
}
@Override
public void onRoomStreamUpdate(String roomID, ZegoUpdateType
updateType, ArrayList< ZegoStream > streamList, JSONObject extendedData) {
// 流变化回调
super.onRoomStreamUpdate(roomID, updateType, streamList, extendedData);
// 在这里更新 UI 或执行其他操作
if(updateType == ZegoUpdateType.ADD){
// 当 “updateType” 为 “ZegoUpdateTypeADD” 时,用户可以拉取 streamList 里各条音视频流以展示房间内其他用户的画面和声音
for(ZegoStream stream : streamList){
//进行拉流,preview 为一个View 对象,开发者可以根据业务自定义,一般常用的是TextureView对象;在展示多人视频的时候,开发者需要使用不同的 View 承载不同音视频流的画面,保证不同用户的视频不会重叠在一起;此处的示例代码会覆盖当前正在拉流的画面
engine.startPlayingStream( stream.streamID,new ZegoCanvas(preview));
}
}else{
// 当 “updateType” 为 “ZegoUpdateTypeDELETE” 时,用户可以停止拉取相应的音视频流
for(ZegoStream stream : streamList){
//停止拉流
engine.stopPlayingStream( stream.streamID);
}
}
}
});
多人语音聊天SDK的 API 调用时序图参考

5 获取 Java 多人语音聊天SDK 更多帮助
获取本文Java 多人语音聊天SDK的开发文档、技术支持,访问即构文档中心,可实现视频会议和直播场景下多人视频语音聊天功能;
近期有开发规划的开发者可上即构官网查看,恰逢即构七周年全线音视频产品1折的优惠,联系商务获取产品优惠;
Android端实现多人视频语音聊天|音视频开发的更多相关文章
- Android多媒体框架总结(1) - 利用MediaMuxer合成音视频数据流程分析
场景介绍: 设备端通过服务器传向客户端(Android手机)实时发送视频数据(H.264)和音频数据(g711a或g711u), 需要在客户端将音视频数据保存为MP4文件存放在本地,用户可以通过APP ...
- 云-腾讯云-实时音视频:实时音视频(TRTC)
ylbtech-云-腾讯云-实时音视频:实时音视频(TRTC) 支持跨终端.全平台之间互通,从零开始快速搭建实时音视频通信平台 1.返回顶部 1. 腾讯实时音视频(Tencent Real-Time ...
- moviepy音视频剪辑:音视频的加载和输出
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 在本地进行音视频处理时,首先要从视频文件 ...
- Android音视频之MediaRecorder音视频录制
前言: 公司产品有很多地方都需要上传音频视频,今天抽空总结一下音频视频的录制.学习的主角是MediaRecorder类. MediaRecorder类介绍: MediaRecorder类是Androi ...
- Android硬编码——音频编码、视频编码及音视频混合
视频编解码对许多Android程序员来说都是Android中比较难的一个知识点.在Android 4.1以前,Android并没有提供硬编硬解的API,所以之前基本上都是采用FFMpeg来做视频软件编 ...
- 使用PyQt(Python+Qt)+moviepy开发的视频截取、音视频分离、MP4转GIF动图工具免费下载分享
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 在因博文素材需要将软件操作制作成动画时,发现网上相关绿色使用工具都需要 ...
- 直播软件开发之Java音视频解决方案:音视频基础知识
概念 从信息论的观点来看,描述信源的数据是信息和数据冗余之和,即:数据=信息+数据冗余.音频信号在时域和频域上具有相关性,也即存在数据冗余.将音频作为一个信源,音频编码的实质是减少音频中的冗余. 拟信 ...
- cordova使用webrtc与网页端及移动端视频、语音聊天
最近在做一个移动端与移动端.网页端文字.视频.语音聊天的功能.文字聊天使用websocket,在网上很多资料,也没什么难度.但是在视频.语音聊天上遇到了小小的难点.之前一直在找一些SDK想快速开发,例 ...
- Android端IM应用中的@人功能实现:仿微博、QQ、微信,零入侵、高可扩展
本文由“猫爸iYao”原创分享,感谢作者. 1.引言 最近有个需求:评论@人(没错,就是IM聊天或者微博APP里的@人功能),就像下图这样: ▲ 微信群聊界面里的@人功能 ▲ QQ群聊界面里 ...
- iOS 即时视频和聊天(基于环信)
先上效果图: 屏幕快照 2015-07-30 下午5.19.46.png 说说需求:开发一个可以进行即时视频聊天软件. 最近比较忙,考完试回到公司就要做这个即时通信demo.本来是打算用xmpp协议来 ...
随机推荐
- System.Drawing.Point与System.Windows.Point的异同
在C#中,System.Drawing.Point 和 System.Windows.Point 是两个不同的结构,分别属于不同的命名空间,用于表示二维平面中的点.尽管它们的功能相似,但在使用场景和实 ...
- Web前端入门第 58 问:JavaScript 运算符 == 和 === 有什么区别?
运算符 JavaScript 运算符是真的多,尤其是 ES6 之后还在不停的加运算符,其他编程语言看 JS 就像怪物一样,各种骚操作不断~~ 运算符分类 1.算术运算符 算术运算符的作用就是用来基础计 ...
- Qt图像处理技术一:对QImage图片美颜,使用双指数滤波
一.效果图 二.demo源码地址(除了磨皮还有一些基本的滤镜) 如果你觉得有用的话,期待你的小星星 实战应用项目: github :https://github.com/dependon/simple ...
- buck参数工具分享
工具链接:https://cnblogs-img.oss-cn-hangzhou.aliyuncs.com/docs/buck.xls
- 详解鸿蒙Next仓颉开发语言中的动画
大家上午好,今天来聊一聊仓颉开发语言中的动画开发. 仓颉中的动画通常有两种方式,分别是属性动画和显示动画,我们今天以下面的加载动画为例,使用显示动画和属性动画分别实现一下,看看他们有什么区别. 显示动 ...
- 第三次bolg作业
1.前言 在 Java 面向对象程序设计课程的学习之旅中,我经历了知识的积累与思维的蜕变.这门课程通过丰富多样的教学环节,如 Blog 作业.PTA 作业.实验.线上线下课程,帮助我逐步构建起 Jav ...
- 数据安全新战场,EasyMR为企业筑起“安全防线”
2020年1月,时间跨度长达14年的,微软2.5亿条客户服务和支持记录在网上泄露: 同年4月,微盟发生史上最贵"删库跑路"事件,造成微盟市值一夜之间缩水约24亿港币: 今年7月,网 ...
- 使用GcExcel .NET将Excel导出为PDF
使用GcExcel .NET将Excel导出为PDF 引言 在企业级应用开发中,经常需要将Excel数据导出为PDF格式以便于共享和打印.GrapeCity Documents for Excel(简 ...
- C#.Net筑基-泛型T & 协变逆变
01.什么是泛型? 泛型(Generics)是C#中的一种强大的强类型扩展机制,在申明时用"占位符"类型参数"T"定义一个"模板类型",比较 ...
- java基础--StringBuffer类等、线程基础
StringBuffer类 方法: String 增加 append(boolean b) 可以添加任意类型 的数据到容器中 insert(int offset, boolean b) 指定插入的索引 ...