差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

后一修订版 两侧同时换到之后的修订记录
im:web:draft:sticker [2019/03/11 06:55]
jk 创建
im:web:draft:sticker [2019/03/11 06:56]
jk
行 1: 行 1:
-====== 多人实时通话 ====== +===== 导入第三方表情包 ​===== 
- +项目下面新文件夹,用于存放表情图片文件。 
----- +了sdk之后执行如下代
- +
-===== 产品简介 ===== +
- +
- ​为满足不同场景需求,[[https://​github.com/​easemob/​webim/​tree/​master/​webrtc/​dist/​EMedia_x1v1.js|EMedia_x1v1.js]]不仅提供了对1v1通话的支持,而且提供了多人通话功能。多人实时音视频会议划分了不同的类型,不同类型对应了不同场景,使你能够轻松地将实时音视频功能集成到你的应用或者网站中。本片将介绍多人音视频使用接入。可参照[[https://​github.com/​easemob/​webim|demo]]。 +
- 在会议时可以传入以下几种类型: +
- +
-      - Communication:普通通信会议,最多支持参会者6人,会议里的每参会者都可以自由说话和发布视频该会议类型在服务器不做语音的再编码,音质最好,适用于远程医疗,在线客服等场景; +
-      - Large Communication:大型通信会议,最多参会者30人,会议里的每个参会者都可以自由说话,最多支持6个人发布视频,该会议模式服务器做混音处理,支持更多的人说话,适于大型会议等场景; +
-      - Live:互动视频会议,会议里支持最多6个主播和600个观众,观众可以通过连麦与主播互动,该会议类型适用于在线教育,互动直播等场景。 +
- +
- +
-==== 产品特性 ==== +
- +
-    *支持现代浏览器:Chrome/​50+、Safari/​11+、Firefox; +
- +
-    *遵守:UMD通用模块规范,支持require导入; +
- +
-    *支持Promise; +
- +
-    *支持手机端和 Web 端互通,极大方便开发者的全平台业务; +
- +
-    *依赖https站点 +
- +
-==== 音视频通信的简要步骤 ==== +
- +
-SDK 能够支持音频和视频通信。创建音视频通信的过程简单来说,可以分为以几步: +
- +
-    1. 初始化 SDK,设置监听理 +
-    2. create: 创建会议 +
-    3. join: 加入会议 +
-    4. pub: 发布音视频数据流 +
-    5. sub: 订阅并播放音视频数据流 +
-    6. leave: 离开会议 +
-==== 基本知识 ==== +
- +
-emedia.mgr.ConfrType多人会议类型 +
-    1. Communication:普通通信会议,最多支持参会者6人,成员都可以自由说话和发布视频,成员角色Speaker +
-    2. Large Communication:大型通信会议,最多参会者30人,成员都可以自由说话和发布视频,成员角色Speaker +
-    3. Live:互动视频会议,会议里支持最多6个主播和600个观众+
 <code javascript>​ <code javascript>​
-emedia.mgr.ConfrType = { +WebIM.Emoji = { 
-   ​COMMUNICATION:​ 10, //​普通会议模式 +    ​path'demo/images/faces/'  ​/*表情包路径*
-   ​COMMUNICATION_MIX:​ 11, //​大会议模式 +    , map: { 
-   LIVE: 12, //​直播模式 +        '[):]''ee_1.png'
-}; +        '​[:D]''ee_2.png'
-</​code>​ +        '​[;)]': 'ee_3.png'
-<code javascript>​ +        ​'[:-o]''​ee_4.png'​
-emedia.mgr.Role ​= { +        ​'[:p]''​ee_5.png'​
-    ​ADMIN7, // 能创建会议,销毁会议,移除会议成员,切换其他成员的角色,订阅流,发布流 +
-    TALKER: 3, // 能上传自己的音视频,能观看收听其他主播的音视频,即能发布流和订阅流) +
-    AUDIENCE: 1 // 观众Audience:只能观看收听音视频,即只能订阅流 +
-}; +
-</​code>​ +
-<code javascript>​ +
-//​conference|confr +
-{ +
-    ​confrId:"​TS_X296786295944036352C27"​, +
-    id:"​TS_X296786295944036352C27",​ +
-    password: "​password123",​  +
-    roleToken:"​roleToken",​ +
-    ticket:"​ticket",​ +
-    type:12 +
-}; +
-</​code>​ +
-<code javascript>​ +
-//member +
-+
-    "​ext":​{ //​emedia.mgr.joinConference(confrId,​ password, {role: ​'admin'​})/* 用户可自定义扩展字段*/​);​ +
-        "​role"​:"​admin"​ +
-    }, +
-    "​id"​:"​MS_X197721744293023744C19M197756407719972865VISITOR",​ +
-    "​globalName":"​easemob-demo#​chatdemoui_yss000@easemob.com"+
-    "​name"​"​yss000"​ +
-+
-</​code>​ +
-<code javascript>​ +
-//stream +
-+
-    "​id"​:"​RTC2__Of_C19M197756407719972865VISITOR",​ +
-    "​voff":​0,​ //1 视频关闭  +
-    "​aoff":​0,​ //1 音频关闭  +
-    "​memId":"​MS_X197721744293023744C19M197756407719972865VISITOR",​ +
-    "​owner":​ member ,//​member对象 +
-    "​rtcId":"​RTC1"​ +
-+
-var islocated = stream.located(); //islocated true 本地媒体流 +
-</​code>​ +
-     +
-    注意: +
-    >> 每个人必须调用join接口成功后,才算是加入会议(即成为会议成员)。会议成员才允许进行其他操作比如订阅流、发布流等 +
-    >> 成员如果想改变自己角色,必须想办法通知管理员,只有管理员才能修改 +
- +
-===== 多人通信会议功能实现 ===== +
- +
-如何使用SDK实现多人实时音视频会议 +
-  +
-Communication和Large Communication除了最大成员数不一样,流程几乎是一样的。以下是从创建会议到离开会议完整的流程讲解: +
- +
-==== 设置SDK回调 ==== +
- +
-进入会议之前,设置SDK回调后,可获知成员加入或离开会议,数据流更新等。 +
- +
-<code javascript>​ +
-//​有人加入会议,其他人调用joinXX等方法,如果加入成功,已经在会议中的人将会收到 +
-emedia.mgr.onMemberJoined = function (member) { +
-     +
-}; +
-</​code>​ +
-<code javascript>​ +
-//​有人退出会议 +
-emedia.mgr.onMemberExited = function (member) { +
-     +
-}; +
-</​code>​ +
-<code javascript>​ +
-//​有媒体流添加;比如 自己调用了publish方法(stream.located() === true时),或其他人调用了publish方法。 +
-emedia.mgr.onStreamAdded = function (memberstream) { +
- +
-}; +
-</​code>​ +
-<code objc> +
-//​有媒体流移除 +
-emedia.mgr.onStreamRemoved = function (member, stream+
- +
-}; +
-</​code>​ +
-<code javascript>​ +
-//​角色改变 +
-emedia.mgr.onRoleChanged = function (role) { +
- +
-}; +
-</​code>​ +
-<code javascript>​ +
-//​会议退出;自己主动退 或 服务端主动关闭; +
-emedia.mgr.onConferenceExit = function (reasonfailed) { +
-    reason = (reason || 0); +
-    switch (reason){ +
-        ​case 0: +
-            reason = "​正常挂断";​ +
-            break; +
-        case 1: +
-            reason = "​没响应";​ +
-            break; +
-        case 2: +
-            reason = "​服务器拒绝";​ +
-            break; +
-        case 3: +
-            reason = "​对方忙";​ +
-            break; +
-        case 4: +
-            reason = "​失败,可能是网络或服务器拒绝";​ +
-            if(failed === -9527){ +
-                reason = "​失败,​网络原因";​ +
-            } +
-            if(failed === -500){ +
-                reason = "​Ticket失效";​ +
-            } +
-            if(failed === -502){ +
-                reason = "​Ticket过期";​ +
-            } +
-            if(failed === -504){ +
-                reason = "​链接已失效";​ +
-            } +
-            if(failed === -508){ +
-                reason = "​会议无效";​ +
-            } +
-            if(failed === -510){ +
-                reason = "​服务端限制";​ +
-            } +
-            break; +
-        ​case 5: +
-            reason = "​不支持";​ +
-            break; +
-        case 10: +
-            reason = "​其他设备登录";​ +
-            break; +
-        case 11: +
-            reason = "​会议关闭";​ +
-            break;+
     }     }
 }; };
 </​code>​ </​code>​
  
 +全局变量WebIM添加一个Emoji属性,path表示你表情图片存放的路径,map里面的key表示代表表情图片的字符,value表示表情图片的文件名。
  
-==== 用户A创建会议 ==== +发送收表情消息与文本消息类似,如果发文本消息中带有表情key字符sdk会将此消息转换表情图片实际路径,如:文本包含"​[):]"​字符串析为WebIM.Emoji.path+WebIM.Emoji.map['[):]']= "demo/images/faces/ee_1.png"。
- +
-<code javascript>​ +
-emedia.mgr.createConference(confrType,​ password).then(function(confr){ +
-}).catch(function(error){ +
-}) +
-</​code>​ +
- +
-    注意: 如果A只单纯的create,没进行join操作,则A不是Conference的成员,没有相应的角色,不能进行其他操作 +
-     +
-==== 用户A进入会议 ==== +
-<code javascript>​ +
-emedia.mgr.joinConferenceWithTicket(confrId,​ ticket, ext).then(function(confr){ +
- +
-}).catch(function(error){ +
- +
-}) +
-</​code>​ +
-==== 管理员A邀请其他人加入会议 ==== +
- +
-SDK没有提供邀请接口,你可以自己实现,比如使用环信IM通过发消息邀请,比如通过发邮件邀请等等。 +
- +
-至于需要发送哪些邀请信息,可以参照SDK中的join口,目前是需要Conference的confrId和password +
- +
-比如用环信IM发消息邀请 +
-<code javascript>​ +
-WebIM.call.inviteConference(confrId,​ password, jid, gid) +
-</​code>​ +
- +
-    注意:使用环信IM邀请多个人时,建议使用群组消息如果使用单聊消息请注意每条消息中间时间间隔,以防触发环信的垃圾消息防御机制 +
-==== 用户B接收到邀请加入会议 ==== +
- +
- +
-用户B解析出邀请消息中带的confrId和password,调用SDK的join接口加入会议,成为会议成员且角色是Speaker. +
- +
-<code javascript>​ +
-//​javascript +
-emedia.mgr.joinConference(confr,​ password, ext).then(function(confr){ +
- +
-}).catch(function(error){ +
- +
-}) +
-</​code>​ +
- +
- +
- +
-用户B成功加入会议后,会议中其他成员会收到回调[emedia.mgr.onMemberJoined(memberB)] +
- +
-==== 成员A发布音视频流 ==== +
- +
- +
-成员A和成员B都发布流权限 +
- +
-<code javascript>​ +
-/** +
- * constaints: {audio: true, video: true} +
- * videoTag 可缺失如果有 此次publish的媒体数据将在这个video上显示 ​会与stream绑定 +
- * ext 用户自定义扩展,其他员可以看到这个字段 +
- *  +
- */ +
-emedia.mgr.publish(constaints,​ videoTag, ext).then(function(pushedStream){ +
-    //stream 对象 +
-}).catch(function(error){ +
- +
-}); +
- +
-/** +
- * videoTag 可缺失时 +
- * +
- */ +
-emedia.mgr.publish(constaints,​ ext).then(function(pushedStream){ +
-    //stream 对象 +
-    //​如果需要将这个stream对象 显示,需要 emedia.mgr.streamBindVideo(videoTag,​ pushedStream) +
-}).catch(function(error){ +
- +
-}); +
-</​code>​ +
-  *** 注意:A推流成功后,onStreamAdded 将被回调 *** +
-==== 其他成员收到通知并订阅流 ====  +
- +
-成员A成功发布数据流后,会议中其他成员会收到监听类回调[emedia.mgr.onStreamAdded],如果成员B想看成员A音视频可以调用subscribe接口进行订阅 +
- +
-<code javascript>​ +
-//​其他成员 +
-emedia.mgr.onStreamAdded = function (member, stream) { +
-   ​if(!stream.located()){ //​stream.located() === true, 是自己发布刚刚发布的流 +
-      emedia.mgr.subscribe(member,​ stream, true, true, video) +
-   } +
-}; +
-</​code>​ +
- +
- +
-==== 成员B取消订阅流 ==== +
- +
-成员B果不想再看成员A的音视频,可以调用SDK接口unsubscribe +
- +
-<code javascript>​ +
-//​emedia.mgr.hungup(stream);​ +
-emedia.mgr.unsubscribe(stream);​ +
-</​code>​ +
- +
-==== 成员A取发布流 ==== +
- +
-成员A可以调用unpublish接口取消自己已经发布的数据流,操作成功后,会议收到回调[emedia.mgr.onStreamRemoved:​removeStream:​] ,将对应的数据流信息移除 +
- +
-<code javascript>​ +
-//​emedia.mgr.hungup(pushedStream)+
-emedia.mgr.unpublish(pushedStream);​ +
-</​code>​ +
- +
-<code javascript>​ +
-emedia.mgr.onStreamRemoved = function (member, stream) { +
-   ​if(stream.located(){ //​自己发布流 +
-   ​}else{ //​会议其他人发布的流 +
-   } +
-}; +
-</​code>​ +
- +
-==== 成员B离开会议 ==== +
- +
-成员B调用SDK接口exitConference离开会议,会议中的其他成员会收到回调[emedia.mgr.onMemberExited:​member:] +
- +
-<code javascript>​ +
-emedia.mgr.exitConference();​ +
-</​code>​ +
- +
- +
-===== 互动视频会议功能实现 ===== +
- +
-互动视频会议的基本操作(创建、邀请人、发布流、取消发布流、订阅流、取消订阅流、更新发布流程、离开)对应的接口和回调同通信会议是一样的。也可以说 互动视频会议是在通信会议的基础上增加了角色管理功能,以下着重讲互动视频会议中的角色管理相关知识点 +
-  +
- 1创建互动视频会议时,接口emedia.mgr.createConference传入的type参数是emedia.mgr.ConfrType.LIVE +
-  +
- 2. 创建者createAndJoin后的角色是Admin,其他成员第一次调用接口[emedia.mgr.joinConference(confrId,​ password, ext)]加入直播后的权限是观众Audience,Audience只能订阅数据流 +
-  +
- 3. 观众Audience如果想发布数据流 即上麦,需要给管理员发申请。SDK没有提供申请接口,你可以自定义。 +
-  +
-管理员如果同意Audience上麦,需要调用接口emedia.mgr.grantRole将角色Audience更改为Speaker +
-  +
-<code javascript>​ +
-emedia.mgr.grantRole(confr, ​[memberName1,​ memberName2],​ emedia.mgr.Role.TALKER) +
-</​code>​  +
-      +
-成员角色改变后,被改变的成员会收到回调 +
- +
-<code javascript>​ +
-emedia.mgr.onRoleChanged = function (role) { +
- +
-}; +
-</​code>​  +
-  +
-4. 角色从Audience变为Speaker,成员就可以发布数据流了 +
- +
-===== 其他接口 ===== +
-==== 获取加入会议ticket ==== +
-<code javascript>​ +
-emedia.mgr.getConferenceTkt(confrType,​ password).then(function(confr){ +
-     +
-}).catch(function(error){ +
- +
-}) +
-</​code>​  +
- +
-==== 销毁会议 ==== +
-<code javascript>​ +
-emedia.mgr.destroyConference(confr).then(function(){ +
-     +
-}).catch(function(error){ +
- +
-}) +
-</​code>​  +
-==== 踢人 ==== +
-<code javascript>​ +
-emedia.mgr.kickMembersById(confr,​ memberNames).then(function(){ +
-     +
-}).catch(function(error){ +
- +
-}) +
-</​code>​  +
-==== 授权 ==== +
-<code javascript>​ +
-emedia.mgr.grantRole(confr,​ memberNames,​ role).then(function(){ +
-     +
-}).catch(function(error){ +
- +
-}) +
-</​code>​  +
- +
-==== 使用用户名密码加入会议,可自定义ext ==== +
-<code javascript>​ +
-emedia.mgr.joinConference(confrId,​ password, ext).then(function(){ +
-     +
-}).catch(function(error){ +
- +
-}) +
-</​code>​  +
- +
-==== 使用ticket加入会议,可自定义ext ==== +
-<code javascript>​ +
-emedia.mgr.joinConference(confrId,​ ticket, ext).then(function(){ +
-     +
-}).catch(function(error){ +
- +
-}) +
-</​code>​  +
- +
-==== 退出会议 ==== +
-<code javascript>​ +
-emedia.mgr.exitConference();​ +
-</​code>​ +
- +
-==== publish 媒体流 ==== +
-<code javascript>​ +
-/** +
- * constaints: {audiotrue, video: true} +
- * videoTag 可缺失,如果有 此次publish的媒体数据将会在这个video上显示 将会与stream绑定 +
- * ext 用户自定义扩展,其他成员可以看到这个字段 +
- *  +
- */ +
-emedia.mgr.publish(constaints,​ videoTag, ext).then(function(pushedStream){ +
-    //stream 对象 +
-}).catch(function(error){ +
- +
-}); +
- +
-/** +
- * videoTag 可缺失时 +
- * +
- */ +
-emedia.mgr.publish(constaints,​ ext).then(function(pushedStream){ +
-    //stream 对象 +
-    //​如果需要将这个stream对象 显示,需要 emedia.mgr.streamBindVideo(videoTag,​ pushedStream) +
-}).catch(function(error){ +
- +
-}); +
-</​code>​ +
- +
-==== 共享桌面,​仅支持PC Chrome或electron平台 ==== +
-<code javascript>​ +
-/** +
- * videoConstaints {screenOptions:​ ['​screen',​ '​window',​ 'tab']} or true +
- * withAudio: true 携带语音,false不携带 +
- * videoTag 可缺失,如果有 此次publish的媒体数据将会在这个video上显示 将会与stream绑定 +
- * ext 用户自定义扩展,其他成员可以看到这个字段 +
- *  +
- */ +
-emedia.mgr.shareDesktopWithAudio(videoConstaints,​ withAudio, videoTag, ext).then(function(pushedStream){ +
-    //stream 对象 +
-}).catch(function(error){ +
- +
-}); +
- +
-//​electron平台 默认选择第一个屏幕,如果需要选择其他,需要重写方法 +
-emedia.chooseElectronDesktopMedia ​function(sources,​ accessApproved){ +
-    var firstSources = sources[0];​ +
-    accessApproved(firstSources);​ +
-+
-</​code>​  +
- +
-==== 取消publish ==== +
-<code javascript>​ +
-emedia.mgr.unpublish(pushedStream);​ +
-或 +
-emedia.mgr.hungup(pushedStream);​ +
-</​code>​  +
- +
-==== 订阅 ==== +
-<code javascript>​ +
-/** +
- * subSVideo 看视频 +
- * subSAudio 看音频 +
- * videoTag 可缺失,如果有 将会与stream绑定,并播放stream +
- */ +
-emedia.mgr.subscribe(member,​ stream, subSVideo, subSAudio, videoTag).then(function(){ +
-    //stream 对象 +
-}).catch(function(error){ +
- +
-}); +
-emedia.mgr.triggerSubscribe(videoTag,​ subSVideo, subSAudio).then(function(){ +
-    //stream 对象 +
-}).catch(function(error){ +
- +
-}); +
-也可以 +
-//​仅订阅音频 +
-emedia.mgr.triggerResumeAudio(videoTag).then(function(){ +
-}).catch(function(error){ +
-}); +
-//​仅暂停订阅音频 +
-emedia.mgr.triggerPauseAudio(videoTag).then(function(){ +
-}).catch(function(error){ +
-}); +
- +
-//​仅订阅视频 +
-emedia.mgr.triggerResumeVideo(videoTag).then(function(){ +
-}).catch(function(error){ +
-}); +
-//​仅暂停订阅视频 +
-emedia.mgr.triggerPauseVideo(videoTag).then(function(){ +
-}).catch(function(error){ +
-}); +
- +
-</​code>​ +
- +
-==== stream video 绑定 ==== +
-<code javascript>​ +
-//stream 与 video绑定后,video才可以播放stream;并且可以通过触发/​监听video上的事件,来达到对stream的便捷操作 +
-emedia.mgr.streamBindVideo(stream,​ videoTag);​ +
-</​code>​ +
- +
-==== 获取stream绑定的video ==== +
-<code javascript>​ +
-emedia.mgr.getBindVideoBy(stream);​ +
-</​code>​ +
- +
-==== 切换摄像头==== +
-<code javascript>​ +
-emedia.mgr.switchCamera().then(function(){ +
- +
-}).catch(function(){ +
- +
-}) +
-</​code>​ +
- +
-==== 暂停/​恢复自己的视频 ==== +
-<code javascript>​ +
-emedia.mgr.pauseVideo(pubS).then(function(){ +
- +
-}).catch(function(){ +
- +
-}) +
-等价于 +
-emedia.mgr.triggerResumeVideo(localVideoTag).then(function(){ +
- +
-}).catch(function(){ +
- +
-}) +
-</​code>​ +
-<code javascript>​ +
-emedia.mgr.pauseVideo(pubS).then(function(){ +
- +
-}).catch(function(){ +
- +
-}) +
-等价于 +
-emedia.mgr.triggerPauseVideo(localVideoTag).then(function(){ +
- +
-}).catch(function(){ +
- +
-}) +
-</​code>​ +
- +
-==== 抓取 video图像,并保存 ==== +
-<code javascript>​ +
-emedia.mgr.captureVideo(videoTag,​ true, filename) +
-等价于 +
-emedia.mgr.triggerCaptureVideo(videoTag,​ true, filename);​ +
-</​code>​ +
- +
-==== 控制远程视频(手机端)定格 ==== +
-<code javascript>​ +
-emedia.mgr.freezeFrameRemote(stream);​ +
-等价于 +
-emedia.mgr.triggerFreezeFrameRemote(videoTag).catch(function(){ +
-    alert("定格失败"​);​ +
-}); +
-</code> +
- +
-==== 控制手机闪光灯打开/关闭 ==== +
-<code javascript>​ +
-/** +
- * torch true 打开,否则 关闭; 可缺失 +
- */ +
-emedia.mgr.torchRemote(stream, torch); +
-等价于 +
-emedia.mgr.triggerTorchRemote(videoTag,​ torch).catch(function(){ +
-    alert("Torch失败"​);​ +
-}); +
-</​code>​ +
- +
-==== 控制手机截屏 ==== +
-<code javascript>​ +
-emedia.mgr.capturePictureRemote(stream);​ +
-等价于 +
-emedia.mgr.triggerCapturePictureRemote(videoTag).catch(function(){ +
-    alert("​抓图失败"​);​ +
-}); +
-</​code>​ +
- +
-==== 控制手机摄像头放大缩小 ==== +
-<code javascript>​ +
-emedia.mgr.zoomRemote(stream,​ multiples);​ +
-等价于 +
-emedia.mgr.triggerZoomRemote(videoTag,​ multiples).catch(function(){ +
-    alert("​zoom失败"​);​ +
-}); +
-</​code>​ +
- +
-==== 控制手机摄像头聚焦曝光 ==== +
-<code javascript>​ +
-/** +
- * clickEvent 为 videoTag的点击事件通过event计算点击的坐标传给sdk进行控制 +
- * +
- */ +
-emedia.mgr.focusExpoRemote(stream,​ videoTag, clickEvent).catch(function(){ +
-    alert("​focusExpoRemote失败"​);​ +
-}); +
-等价于 +
-/** +
- * event string. 如点击 “click” +
- * fail 失败回调;success成功回调 +
- */ +
-emedia.mgr.onFocusExpoRemoteWhenClickVideo(videoTag,​ event, fail, success); +
-</​code>​ +
- +
-==== 取消在videoTag上的事件 ==== +
-<code javascript>​ +
-//​用来对onFocusExpoRemoteWhenClickVideo的撤销 +
-emedia.mgr.offEventAtTag(videoTag);​ +
-</​code>​ +
- +
-==== video监听的事件 ==== +
-<code javascript>​ +
-//​video的音频视频开关,将会触发 +
-emedia.mgr.onMediaChanaged(videoTag,​ function (constaints) { +
-    $div.find("#​aoff"​).html(constaints.audio ? "​有声"​ : "​无声"​);​ +
-    $div.find("#​voff"​).html(constaints.video ? "​有像"​ : "​无像"​);​ +
- +
-    //​可以通过video标签 得知发布方 是否关闭 音频 视频 +
-    console.warn($(videoTag).attr("​easemob_stream"​),​ "​aoff",​ $(videoTag).attr("​aoff"​));​ +
-    console.warn($(videoTag).attr("​easemob_stream"​),​ "​voff",​ $(videoTag).attr("​voff"​));​ +
-}); +
-</​code>​ +
- +
-<code javascript>​ +
-//​video的声音大小出发,比如谁在说话 +
-emedia.mgr.onSoundChanaged(videoTag,,​ function (meterData) { +
-    var $volume = $div.find('#​volume'​);​ +
- +
-    $volume.html(meterData.instant.toFixed(2) +
-        + " " + meterData.slow.toFixed(2) +
-        + " " + meterData.clip.toFixed(2) +
-        + " " + (meterData.trackAudioLevel ? parseFloat(meterData.trackAudioLevel).toFixed(4) : "​--"​) +
-        + " " + (meterData.trackTotalAudioEnergy ? parseFloat(meterData.trackAudioLevel).toFixed(4) : "​--"​) +
-    ); +
-}); +
-</​code>​ +
- +
-<code javascript>​ +
-//​视频收发数据统计 +
-emedia.mgr.onMediaTransmission(videoTag,​ function notify(trackId,​ type, subtype, data) { +
-    var $iceStatsShow = $div.find("#​iceStatsShow"​);​ +
-    var $em = $iceStatsShow.find("#"​+subtype);​ +
-    if(!$em.length){ +
-        $em  = $("<​em></​em>"​).appendTo($iceStatsShow).attr("​id",​ subtype); +
-    } +
- +
-    $em.text(subtype + ":"​ + (data*8/​1000).toFixed(2));​ +
-}); +
-</​code>​ +
- +
-<code javascript>​ +
-//​连接状态变化 +
-emedia.mgr.onIceStateChanged(videoTag,​ function (state) { +
-    console.log(state);​ +
-}); +
-</​code>​ +
- +
- +
----- +
-<WRAP group> +
-<WRAP half column>​ +
-上一页:[[im:​web:​basics:​videocall|实时通话]] +
-</​WRAP>​ +
- +
-<WRAP half column>​ +
-下一页:[[im:​web:​other:​toolrelated|工具类说明]] +
-</​WRAP>​ +
-</​WRAP>​+