工作流程
事件流程
逻辑问题修正
( 1 )视频通话前:
我方:点击视频通话,弹出呼叫弹窗,并通知对方。对方:接收到信号弹出来电弹窗,选择同意 / 拒绝。
( 2 )视频通话中:
我方:接收到对方同意的信号,切换视频通话中的弹窗,进行视频通话 ; 若对方拒绝,则关闭当前弹窗。对方:若同意则切换视频通话中的弹窗,若拒绝则关闭当前弹窗。
( 3 )结束视频通话:
我方点击结束通话:我方:关闭当前弹窗。对方:接收到信号也关闭当前弹窗。
对方点击结束通话:对方:关闭当前弹窗。我方:接收到信号也关闭当前弹窗。
( 4 )根据不同的操作过程生成不同的通话记录,例如:“对方已拒绝”、“已取消”、“通话时长 02:33” 等。
一、页面层的位置上端对端实时通信元素( peer )的操作:如下图所示:
友情链接: peer 元素使用手册: http://www.wware.org/wide/setup.html#?content=/v/wide/setup/element/peer.html
设置peer元素:点击peer元素设置呼叫类型(音频/视频).选择视频就要填写视频上的对应id值,下图所示;选择音频就应在源码格式下在peer元素上添加 data-remoteaudioid="xx",xx为对应音频播放器的id;
操作:
1.在peer元素上添加属性绑定:{"data-x-wid":dataxwid,"data--call-control":datacallcontrol,"data--call-wid":datacallwid,"data-x-localurl":dataxlocalurl,"data-x-remoteurl":dataxremoteurl} ,并给变量初始化变量初始化:{"dataxlocalurl":"","dataxremoteurl":"","datavsrclocal":"","datavsrcremote":"","dataxwid":"","datacallwid":"","datacallcontrol":"","kaishi":""}。如下图所示(相关参数含义可参考元素手册):
在层上添加权限检查元素(获取摄像头和录音的权限):如下图所示
2. 逻辑操作:
(1)在元素上添加绑定数据编程:选择其他事件: peercalled.video ,添加绑定数据编程:
_vm.laidian0(true); //当收到呼叫请求的时候,打开来电弹窗,及弹窗2
如下图所示:
(2)在peer元素上添加绑定数据编程:选择其他事件:peerconnect.video ,添加绑定数据编程:
//将用户当前的视频流赋给弹窗3中的视频播放器绑定的变量(我方视频播放器窗口)
_vm.datavsrclocal(_vm.dataxlocalurl());
//将对方传回来的视频流赋给弹窗3中的视频播放器绑定的变量(对方视频播放器窗口)
_vm.datavsrcremote(_vm.dataxremoteurl());
//将对方传回来的音频流赋给弹窗3中的音频播放器绑定的变量(音频播放器窗口)
//_vm.datasrc(_vm.dataxremoteurl());_vm.dataplay("play");
var ms=new Date().getTime();
_vm.kaishi(ms);
_vm.huchu0(false); //关闭呼出弹窗,即弹窗
_vm.tonghua0(true ); //开启通话中的弹窗,即弹窗
如下图所示:
(3)在元素上添加绑定数据编程:选择其他事件:peerclose.video ,添加绑定数据编程:
_vm.tonghua0(false); //当连接关闭的时候,关闭通话中的弹窗,即弹窗3
_vm.laidian0(false); //当连接关闭的时候,关闭来电弹窗,即弹窗2
_vm.huchu0(false); //当连接关闭的时候,关闭来电弹窗,即弹窗1
如下图所示:
(4)在 peer元素上添加绑定数据编程:选择其他事件: peercalling.video ,添加绑定数据编程:
_vm.datacallcontrol("waiting"); //当发起呼叫的时候,将peer元素应答状态改为waiting状态,即呼叫等待中,解决第二次主动发起呼叫主叫方不能挂断问题,如下图所示
(5)在peer元素上添加提交数据:选择其他事件:peerinit ,额外逻辑:提交数据,并填写相应视口和参数。如下图所示:
参数说明:
dataxwid : peer 元素绑定的自定义变量,表示: 当前用户的 websocketID
视口处理内容:将获取到的当前用户的 websocketID(dataxwid)存入数据可以用户表的某个字段(用于对方获取我方的dataxwid,才能建立上连接)(具体代码省略)
二、页面点击视频图标进行的操作:如下图所示:
(1)在视频图标上添加提交数据,如下图所示:
视口传入参数说明:kfid :自定义变量,聊天对话中,对方的用户表的_id
视口说明:用来获取到对方的 websocketID(之前已经存入到用户表的某一个字段,可直接查询获取),返回参数中返回如下:即返回对方websocketID值,调整peer元素状态,并将呼出弹窗弹出
function() {
_.extend(finish_data, {
"success": true,
"_runCommand": [{
"command": "updatelv",
"wid": tmp_data.wid, // 对方的 websocketID
"datacallwid":tmp_data.wid, // 对方的 websocketID
"datacallcontrol":"waiting", // 将 peer 元素上绑定的用于控制状态的变量变为等待状态(“ waiting” )
"huchu0":"show" // 弹出呼出弹窗,即弹窗 1
}]
}]
});
},
三、 3 个弹窗的操作:弹窗如下图所示:
呼出弹窗,即弹窗 1 :
来电弹窗,即弹窗 2 :
通话弹窗,即弹窗 3 :
( 1 )弹窗 1 具体操作:
1 )在静音图标处添加绑定数据编程:
if (_vm.datacallcontrol() === "mute") { // 当为静音的时候
_vm.datacallcontrol(""); // 不静音
} else {
_vm.datacallcontrol("mute"); // 否则开启静音
}
如下图所示:
2 )在右侧取消图标处添加绑定数据编程:
_vm.datacallcontrol("cancel"); // 将控制变量改为取消状态(“ cancel” )
_vm.huchu0(false); // 关闭呼出弹窗,即弹窗 1
如下图所示:
( 2 )弹窗 2 具体操作:
1 )显示来电对方的信息,如示例图中的 kiss2 (来电对方的昵称),即绑定变量进行显示,
获取方式在页面读取视口中返回即可(因为是两人聊天,对方昵称可以得到),绑定见下图:
2 )在取消图标处添加提交数据(由于需要创建数据记录,所以此处不使用绑定数据编程的方式):如下图所示:
参数说明:
kfid :自定义变量,对方的用户表的 _id
视口操作说明:
1 》添加数据库相关操作,此处略(按自己项目需求自己添加)
2 》以上逻辑添加完成之后,添加”发送通知消息“代码段,类似如下:
/*INSBEGIN:WSNOTIFY*/
function() {
return reqlib('msgbroker');
},
function(msgbroker) {
function _2Date(value, format) {
try {
if (format) {
return moment.utc(value)
.format(format);
} else {
return moment.utc(value)
.format();
}
} catch (e) {
return value;
}
}
var domain = req.wwdomain();
var uid = inputs.kfid;
var msg = {
"command": "MESSAGE",
"headers": {
"random": Math.random(),
"subscription": "sub-0"
},
"body": ""
};
msg.headers._runCommand = JSON.stringify([{
"command": "vmArrFuc",
"params": ["push", "chattable", {
"headpic": tmp_data.user.headpic,
"nickname": tmp_data.user.nickname,
"chattable7theuserid": inputs.kfid, // 所属用户 id
"chattable7senderid": tmp_data.uid, // 发送人 id
"chattable7recipienti": inputs.kfid, // 接收人 id
"chattable7messagecon": " 对方已拒绝 ",
"chattable7sendingtim": _2Date(),
"chattable7messagetyp": " 视频 ",
"chattable7speechdura": 0,
"chattable7voice": ""
}]
}]);
return msgbroker.notifyuser(domain, uid, msg);
},
//@wweditorinfo:{"id":"a189fffd8eceaebf0c6c516cba3d15c0","editor":{"step1":false,"stepUser":{"domain":{"from":"const","value":"kefu7zxkfb"},"uid":{"from":"tmp_data","value":"0000"},"msg":{"from":"inputs","value":"kefu7zxkfb7ltnr"},"isFilter":false}}}
/*INSEND:WSNOTIFY*/
3 》最后添加输出代码段:类似如下:
/*INSBEGIN:STDOUT*/
function() {
_.extend(finish_data, {
"success": true,
"_runCommand": [{
"command": "updatelv",
"params": [{
"laidian0": "", // 关闭来电弹窗,即弹窗 2
"datacallcontrol": "reject" // 将控制状态改为拒绝(” reject“ )
}]
}, {
"command": "vmArrFuc",
"params": ["push", "chattable", { // 尾部追加我方消息记录
"headpic": tmp_data.user.headpic,
"nickname": tmp_data.user.nickname,
"chattable7theuserid": tmp_data.uid, // 所属用户 id
"chattable7senderid": tmp_data.uid, // 发送人 id
"chattable7recipienti": inputs.kfid, // 接收人 id
"chattable7messagecon": " 已取消 ",
"chattable7sendingtim": moment()
.utc()
.format(),
"chattable7messagetyp": " 视频 ",
"chattable7speechdura": 0,
"chattable7voice": ""
}]
}]
});
},
//@wweditorinfo:{"id":"cf760ed9cbd5d5e99d047f3b7ac9dad0","editor":{"jsonValue":{"success":true,"_runCommand":[{"command":"updatelv","params":[{"a":"newValue"}]},{"command":"vmArrFuc","params":["push"," 数组变量名 ",{" 属性名 1":" 属性值 1"},{" 属性名 2":" 属性值 2"}]}]},"steppurpose":{"purpose":"finishdata"}}}
/*INSEND:STDOUT*/
3 )在接受图标处添加绑定数据编程:
_vm.datacallcontrol("accept"); // 将控制状态改为接受(“ accept” )
_vm.laidian0(""); // 关闭来电弹窗,即弹窗 2
_vm.tonghua0(true); // 打开通话中的弹窗,即弹窗 3
如下图所示:
( 3 )弹窗 3 具体操作:
1) 添加音频播放器或视频播放器:
添加音频播放器,如下图所示,直接添加音频播放器并设置id,添加属性{"data--play":dataplay,"data--src":datasrc},并给变量初始化变量初始化{"dataplay":"pause","datasrc":""}
添加两个视频播放器,分别直接添加一个p标签,在p标签内添加一个video标签,在video标签上设置id和属性 {"src":remotevideo}或 {"src":localvideo} ,具体如下图所示
3 )在静音图标处添加绑定数据编程:
if (_vm.datacallcontrol() === "mute") { // 当控制状态为静音的时候(“ mute” )
_vm.datacallcontrol(""); // 取消静音
} else {
_vm.datacallcontrol("mute"); // 否则开启静音
}
如下图所示:
4 )在取消图标处,添加提交数据,如下图所示:
参数说明:
kfid :自定义变量,对方的用户表的 _id
kaishi :自定义变量,开始视频的时间
视口说明:
1 》其他对数据库的操作逻辑省略,根据项目需求而定 ;
2 》上述逻辑之后加上“发送通知消息”代码段:示例如下:
/*INSBEGIN:WSNOTIFY*/
function() {
return reqlib('msgbroker');
},
function(msgbroker) {
function _2Date(value, format) {
try {
if (format) {
return moment.utc(value)
.format(format);
} else {
return moment.utc(value)
.format();
}
} catch (e) {
return value;
}
}
var domain = req.wwdomain();
var uid = inputs.kfid;
var msg = {
"command": "MESSAGE",
"headers": {
"random": Math.random(),
"subscription": "sub-0"
},
"body": ""
};
msg.headers._runCommand = JSON.stringify([{
"command": "vmArrFuc",
"params": ["push", "chattable", {
"headpic": tmp_data.user.headpic,
"nickname": tmp_data.user.nickname,
"chattable7theuserid": inputs.kfid, // 所属用户 id
"chattable7senderid": tmp_data.uid, // 发送人 id
"chattable7recipienti": inputs.kfid, // 接收人 id
"chattable7messagecon": tmp_data.neirong,
"chattable7sendingtim": _2Date(),
"chattable7messagetyp": " 视频 ",
"chattable7speechdura": 0,
"chattable7voice": "",
"you":"off",
"zuo":"off"
}]
}]);
return msgbroker.notifyuser(domain, uid, msg);
},
//@wweditorinfo:{"id":"a189fffd8eceaebf0c6c516cba3d15c0","editor":{"step1":false,"stepUser":{"domain":{"from":"const","value":"kefu7zxkfb"},"uid":{"from":"tmp_data","value":"0000"},"msg":{"from":"inputs","value":"kefu7zxkfb7ltnr"},"isFilter":false}}}
/*INSEND:WSNOTIFY*/
3 》最后添加返回数据代码段:示例如下:
/*INSBEGIN:STDOUT*/
function() {
_.extend(finish_data, {
"success": true,
"_runCommand": [{
"command": "updatelv",
"params": [{
"tonghua0": "", // 关闭视频通话中的弹窗,即弹窗 3
"datacallcontrol": "hangup" // 使视频状态改为挂断状态(“ hangup” )
}]
}, {
"command": "vmArrFuc",
"params": ["push", "chattable", { // 在当前聊天记录中尾部追加一条记录
"headpic": tmp_data.user.headpic,
"nickname": tmp_data.user.nickname,
"chattable7theuserid": tmp_data.uid, // 所属用户 id
"chattable7senderid": tmp_data.uid, // 发送人 id
"chattable7recipienti": inputs.kfid, // 接收人 id
"chattable7messagecon": tmp_data.neirong,
"chattable7sendingtim": moment()
.utc()
.format(),
"chattable7messagetyp": " 视频 ",
"chattable7speechdura": 0,
"chattable7voice": "",
"you":"off",
"zuo":"off"
}]
}]
});
},
//@wweditorinfo:{"id":"cf760ed9cbd5d5e99d047f3b7ac9dad0","editor":{"jsonValue":{"success":true,"_runCommand":[{"command":"updatelv","params":[{"a":"newValue"}]},{"command":"vmArrFuc","params":["push"," 数组变量名 ",{" 属性名 1":" 属性值 1"},{" 属性名 2":" 属性值 2"}]}]},"steppurpose":{"purpose":"finishdata"}}}
/*INSEND:STDOUT*/
语音聊天测试汇总 | |||||
行:接收方;列:发起方 | 安卓版app | 安卓版微信浏览器 | IOSapp | IOS微信浏览器 | PC |
安卓版app | 1. 语音通话:互相通话无问题. | 1. 语音通话:安卓版app主叫安卓微信浏览器通话无问题. | 由于IOSapp暂时没有麦克风权限,无法测试 | 1. 语音通话:安卓版app主叫IOS微信浏览器有问题,被叫方点击接听时,被叫方会由“收到呼叫请求”直接进入“连接关闭”状态,主叫方由“接收到信号”状态等待30秒后自动进入“连接关闭”状态. | 1. 语音通话:安卓版app主叫PC浏览器通话无问题. |
安卓版微信浏览器 | 1. 语音通话:安卓微信浏览器主叫安卓版app有问题,被叫方点击接听时,主叫方会直接进入“连接关闭”状态,被叫方由“接收到信号”状态等待30秒后自动进入“连接关闭”状态. | 1. 语音通话:互相通话无问题 | 由于IOSapp暂时没有麦克风权限,无法测试 | 1. 语音通话: 安卓版微信浏览器主叫IOS微信浏览器有问题,被叫方点击接听时,被叫方会由“收到呼叫请求”直接进入“连接关闭”状态,主叫方由“接收到信号”状态等待30秒后自动进入“连接关闭”状态.之后主叫方重新呼叫,被叫方无反应(需要双方页面刷新后,被叫方才会有“收到呼叫请求”反应). | 1. 语音通话:安卓版微信浏览器主叫PC浏览器 通话无问题. |
IOSapp | 由于IOSapp暂时没有麦克风权限,无法测试 | 由于IOSapp暂时没有麦克风权限,无法测试 | 由于IOSapp暂时没有麦克风权限,无法测试 | 由于IOSapp暂时没有麦克风权限,无法测试 | 由于IOSapp暂时没有麦克风权限,无法测试 |
IOS微信浏览器 | 1. 语音通话:IOS微信浏览器主叫安卓版app有问题,主叫方点击立即通话后,主叫方会直接进入“连接关闭”状态,被叫方无反应 | 1. 语音通话:IOS微信浏览器主叫安卓版微信浏览器有问题,主叫方点击立即通话后,主叫方会直接进入“连接关闭”状态,被叫方无反应 | 由于IOSapp暂时没有麦克风权限,无法测试 | 1. 语音通话:IOS微信浏览器主叫IOS微信浏览器有问题,主叫方点击立即通话后,主叫方会直接进入“连接关闭”状态,被叫方无反应 | 1. 语音通话:IOS微信浏览器主叫PC浏览器有问题,主叫方点击立即通话后,主叫方会直接进入“连接关闭”状态,被叫方无反应 |
PC | 1. 语音通话:PC浏览器主叫安卓版app有问题,被叫方点击接听时,主叫方会直接进入“连接关闭”状态,被叫方由“接收到信号”状态等待30秒后自动进入“连接关闭”状态. | 1. 语音通话:PC浏览器主叫安卓版微信浏览器通话无问题. | 由于IOSapp暂时没有麦克风权限,无法测试 | 1. 语音通话:PC浏览器主叫IOS微信浏览器有问题,被叫方点击接听时,被叫方会由“收到呼叫请求”直接进入“连接关闭”状态,主叫方由“接收到信号”状态等待30秒后自动进入“连接关闭”状态. | 1. 语音通话:互相通话无问题. |