创建HTML和JS

ofwebrtc.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>HTML5 GetUserMedia Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script src='jquery-1.9.1.min.js'></script>
<script src='strophe.min.js'></script>
<script src='ofwebrtc.js'></script>
</head>
<body> <p id="info"></p>
<p>----------------------------------------------------------------</p> JID:<input type="text" id="input-jid" value="">
<br>
密码:<input type="password" id="input-pwd" value="">
<br>
<button id="btn-login">登录</button><br> <br>
目标JID:
<input type="text" id="input-contacts" value="mytest1@pc-20170308pkrs">
<button id="btn-call">Call</button>
<p>----------------------------------------------------------------</p> Local: <br>
<video id="localVideo" autoplay></video><br>
Remote: <br>
<video id="remoteVideo" autoplay></video>
</body>
</html>

ofwebrtc.js

// XMPP帮助类
// boshService: XMPP服务器BOSH地址
function XMPPHelper(boshService) {
var _this = this; // XMPP服务器BOSH地址
_this.boshService = boshService; // XMPP连接
_this.connection = null; // 当前状态是否连接
_this.connected = false; // 当前登录的JID
_this.jid = ""; // 收到消息后的业务回调方法
_this.messageCallback = null;
_this.setMessageCallback = function (messageCallback) {
_this.messageCallback = messageCallback;
} // 接收到<message>
var onMessage = function (msg) {
console.log('--- msg ---', msg); // 解析出<message>的from、type属性,以及body子元素
var from = msg.getAttribute('from');
var type = msg.getAttribute('type');
var elems = msg.getElementsByTagName('body');
var json = JSON.parse(HtmlUtil.htmlDecodeByRegExp(elems[0].innerHTML));
console.log('--- json ---', json);
json.fromjid = from; if (type === 'chat') {
_this.messageCallback(json);
} return true;
} // 连接状态改变的事件
var onConnect = function (status) {
console.log('status: ' + status)
if (status == Strophe.Status.CONNFAIL) {
$('#info').html("连接失败!");
} else if (status == Strophe.Status.AUTHFAIL) {
$('#info').html("登录失败!");
} else if (status == Strophe.Status.DISCONNECTED) {
$('#info').html("连接断开!");
_this.connected = false;
} else if (status == Strophe.Status.CONNECTED) {
$('#info').html("连接成功!");
_this.connected = true; // 当接收到<message>节,调用onMessage回调函数
_this.connection.addHandler(onMessage, null, 'message', null, null, null); // 首先要发送一个<presence>给服务器(initial presence)
_this.connection.send($pres().tree());
}
}; // 登录
_this.login = function (jid, password) {
_this.connection = new Strophe.Connection(_this.boshService);
_this.connection.connect(jid, password, onConnect);
_this.jid = jid;
}; _this.sendMessage = function (tojid, type, data) {
if (_this.connected === false) {
alert("请先登录!!!");
return;
} var msg = $msg({
to: tojid,
from: _this.jid,
type: 'chat'
}).c("body", null, JSON.stringify({
type: type,
data: data
}));
_this.connection.send(msg.tree());
};
} // WebRTC帮助类
// xmppHelper:XMPP帮助实例
// localVideo:本地视频显示的DOM
// remoteVideo:远端视频显示的DOM
function WebRTCHelper(xmppHelper, localVideo, remoteVideo) {
var _this = this; // 对方用户
_this.tojid = null; // 创建PeerConnection实例 (参数为null则没有iceserver,即使没有stunserver和turnserver,仍可在局域网下通讯)
_this.pc = new webkitRTCPeerConnection(null); _this.hasBindLocalVideo = false; // 发送ICE候选到其他客户端
_this.pc.onicecandidate = function(event){
if (event.candidate !== null && _this.tojid !== null) {
console.log('----------- onicecandidate ------------');
console.log('candidate', event.candidate); xmppHelper.sendMessage(_this.tojid, 'candidate', event.candidate);
}
}; // 如果检测到媒体流连接到本地,将其绑定到一个video标签上输出
_this.pc.onaddstream = function(event){
console.log('----------- onaddstream ------------');
remoteVideo.src = URL.createObjectURL(event.stream);
}; // 发送offer和answer的函数,发送本地session描述
var sendOfferFn = function(desc){
console.log('----------- sendOfferFn ------------');
console.log('desc', desc);
_this.pc.setLocalDescription(desc); xmppHelper.sendMessage(_this.tojid, 'offer', desc);
};
var sendAnswerFn = function(desc){
console.log('----------- sendAnswerFn ------------');
console.log('desc', desc);
_this.pc.setLocalDescription(desc); xmppHelper.sendMessage(_this.tojid, 'answer', desc);
};
var mediaConfig = { video: true };
// 绑定本地视频流
var bindLocalVideo = function (callback) {
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia(mediaConfig).then(function(stream) {
//绑定本地媒体流到video标签用于输出
localVideo.src = window.URL.createObjectURL(stream);
//向PeerConnection中加入需要发送的流
_this.pc.addStream(stream);
callback();
});
} }; // 开始视频通讯
_this.start = function (tojid) {
_this.tojid = tojid; if (_this.hasBindLocalVideo === false) {
bindLocalVideo(function () {
// 发送一个offer信令
_this.pc.createOffer(sendOfferFn, function (error) {
console.log('Failure callback: ' + error);
});
});
_this.hasBindLocalVideo = true;
} else {
// 发送一个offer信令
_this.pc.createOffer(sendOfferFn, function (error) {
console.log('Failure callback: ' + error);
});
}
}; // 收到对方信息后的处理
_this.onMessage = function (json) {
console.log('onMessage: ', json);
console.log('json.data: ', json.data); if (_this.tojid === null) {
_this.tojid = json.fromjid;
} if (json.type === 'candidate') {
_this.pc.addIceCandidate(new RTCIceCandidate(json.data));
} else {
_this.pc.setRemoteDescription(new RTCSessionDescription(json.data));
if (json.type === 'offer') {
if (_this.hasBindLocalVideo === false) {
bindLocalVideo(function () {
_this.pc.createAnswer(sendAnswerFn, function (error) {
console.log('Failure callback: ' + error);
});
});
_this.hasBindLocalVideo = true;
} else {
_this.pc.createAnswer(sendAnswerFn, function (error) {
console.log('Failure callback: ' + error);
});
}
}
}
}
} $(document).ready(function() {
// 实例化XMPP和WebRTC帮助类
var xmppHelper = new XMPPHelper('http://localhost:7070/http-bind/');
var webRTCHelper = new WebRTCHelper(xmppHelper, document.getElementById('localVideo'), document.getElementById('remoteVideo')); // XMPP收到消息后转给WebRTC
xmppHelper.setMessageCallback(webRTCHelper.onMessage); $('#btn-login').click(function() {
console.log('jid: ' + $("#input-jid").val());
console.log('pwd: ' + $("#input-pwd").val());
xmppHelper.login($("#input-jid").val(), $("#input-pwd").val());
}); $('#btn-call').click(function() {
if($("#input-contacts").val() == '') {
alert("请输入目标用户!");
return;
}
tojid = $("#input-contacts").val(); webRTCHelper.start(tojid);
});
}); var HtmlUtil = {
/*1.用浏览器内部转换器实现html转码*/
htmlEncode:function (html){
//1.首先动态创建一个容器标签元素,如DIV
var temp = document.createElement ("div");
//2.然后将要转换的字符串设置为这个元素的innerText(ie支持)或者textContent(火狐,google支持)
(temp.textContent != undefined ) ? (temp.textContent = html) : (temp.innerText = html);
//3.最后返回这个元素的innerHTML,即得到经过HTML编码转换的字符串了
var output = temp.innerHTML;
temp = null;
return output;
},
/*2.用浏览器内部转换器实现html解码*/
htmlDecode:function (text){
//1.首先动态创建一个容器标签元素,如DIV
var temp = document.createElement("div");
//2.然后将要转换的字符串设置为这个元素的innerHTML(ie,火狐,google都支持)
temp.innerHTML = text;
//3.最后返回这个元素的innerText(ie支持)或者textContent(火狐,google支持),即得到经过HTML解码的字符串了。
var output = temp.innerText || temp.textContent;
temp = null;
return output;
},
/*3.用正则表达式实现html转码*/
htmlEncodeByRegExp:function (str){
var s = "";
if(str.length == 0) return "";
s = str.replace(/&/g,"&amp;");
s = s.replace(/</g,"&lt;");
s = s.replace(/>/g,"&gt;");
s = s.replace(/ /g,"&nbsp;");
s = s.replace(/\'/g,"'");
s = s.replace(/\"/g,"&quot;");
return s;
},
/*4.用正则表达式实现html解码*/
htmlDecodeByRegExp:function (str){
var s = "";
if(str.length == 0) return "";
s = str.replace(/&amp;/g,"&");
s = s.replace(/&lt;/g,"<");
s = s.replace(/&gt;/g,">");
s = s.replace(/&nbsp;/g," ");
s = s.replace(/'/g,"\'");
s = s.replace(/&quot;/g,"\"");
return s;
}
};

测试

1、打开Chrome,访问ofwebrtc.html页面,输入JID(如admin@pc-20170308pkrs)、密码,点击登录,提示连接成功。

2、再打开一个Chrome访问ofwebrtc.html页面,输入JID(如mytest1@pc-20170308pkrs),密码,点击登录,提示连接成功。

之后在目标JID输入上个页面的JID(admin@pc-20170308pkrs)点击Call,会提示使用摄像头,选择允许。

3、上个页面也会弹出使用摄像头提示,点击允许

4、效果


后续有时间继续补充优化...

XMPP即时通讯协议使用(十二)——基于xmpp搭建简单的局域网WebRTC的更多相关文章

  1. XMPP即时通讯协议使用(二)——基于Smack相关操作

    package com.test; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator ...

  2. XMPP即时通讯协议使用(前传)——协议详解

    XMPP详解 XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议.在此基础上,XMPP ...

  3. xmpp即时通讯协议的特性---长处和缺点!

    xmpp协议的定义? XMPP是一种基于标准通用标记语言的子集XML的协议,它继承了在XML环境中灵活的发展性. 因此.基于XMPP的应用具有超强的可扩展性.经过扩展以后的XMPP能够通过发送扩展的信 ...

  4. XMPP即时通讯协议使用(十)——好友关系状态

    sub  ask  recv 订阅 询问 接受 含义 substatus -1-  应该删除这个好友          Indicates that the roster item should be ...

  5. XMPP即时通讯协议使用(八)——基于订阅发布实现消息流转业务泳道图

  6. XMPP即时通讯协议使用(六)——开发Openfire聊天记录插件

    转载地址:http://www.cnblogs.com/hoojo/archive/2013/03/29/openfire_plugin_chatlogs_plugin_.html 开发环境: Sys ...

  7. XMPP即时通讯协议使用(七)——利用Strophe实现WebIM及strophe.plugins插件使用

    Strophe简介与Openfire配置 Strophe.js是为XMPP写的一个js类库.因为http协议本身不能实现持久连接,所以strophe利用BOSH模拟实现持久连接. 官方文档: http ...

  8. XMPP即时通讯协议使用(四)——Openfire服务器源码编译与添加消息记录保存

    下载Openfire源码 下载地址:https://www.igniterealtime.org/downloads/index.jsp,当前最新版本为:4.2.3 Eclipse上部署Openfir ...

  9. XMPP即时通讯协议使用(三)——订阅发布、断开重连与Ping

    package com.testV3; import java.util.List; import org.jivesoftware.smack.ConnectionListener; import ...

随机推荐

  1. 2.VUE前端框架学习记录二

    VUE前端框架学习记录二:Vue核心基础2(完结)文字信息没办法描述清楚,主要看编码实战里面,有附带有一个完整可用的Html页面,有需要的同学到脑图里面自取.脑图地址http://naotu.baid ...

  2. Move Over and Click Link

    Move Over and Click Link [Documentation] 等待悬浮菜单中的元素出现并单击元素 [Arguments] ${hover_locator} ${opt_locato ...

  3. mysql小知识

    char(10): 换行符 char(13): 回车符 UPDATE tablename SET field = REPLACE(REPLACE(field, CHAR(10), ”), CHAR(1 ...

  4. 利用jmeter发起java请求调用shell脚本

    1.创建maven项目 在pom文件中加入依赖:     2.在路径src/main/java下创建类,如类名shellclass                     3.      创建jmet ...

  5. golang web

    最简web package main import ( "io" "net/http" "log" ) func HelloServer(w ...

  6. Adblock Plus 添加过滤规则

    过滤掉相关的DIV 如要过滤某网站的 如例1:  home.firefoxchina.cn##div#module-game##元素#名字 过滤掉ID为名字的元素##div.名字 class为名字的D ...

  7. SpringBoot---提供的自动配置

    1.自动配置的ViewResolver 1.1.ContentNegotiatingViewResolver 1.2.BeanNameViewResolver 1.3.InternalResource ...

  8. js中数组Array 详解

    unshift:将参数添加到原数组开头,并返回数组的长度    pop:删除原数组最后一项,并返回删除元素的值:如果数组为空则返回undefined    push:将参数添加到原数组末尾,并返回数组 ...

  9. Ubuntu安装openmpi

    Ubuntu 下安装 openmpi 需要同时安装下面三个包: sudo apt-get install openmpi-bin openmpi-doc libopenmpi-dev 建议更新系统源之 ...

  10. 微信小程序中的自定义组件 以及 相关的坑

    Step1 我们初始化一个小程序(本示例基础版本库为 1.7 ),删掉里面的示例代码,并新建一个 components 文件夹,用于存放我们以后开发中的所用组件,今天我们的目的是实现一个 首页 组件, ...