<!DOCTYPE html>
<html>
<head>
<script type='text/javascript' src='https://cdn.scaledrone.com/scaledrone.min.js'></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
body {
display: flex;
height: 100vh;
margin: 0;
align-items: center;
justify-content: center;
padding: 0 50px;
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
}
video {
max-width: calc(50% - 100px);
margin: 0 50px;
box-sizing: border-box;
border-radius: 2px;
padding: 0;
box-shadow: rgba(156, 172, 172, 0.2) 0px 2px 2px, rgba(156, 172, 172, 0.2) 0px 4px 4px, rgba(156, 172, 172, 0.2) 0px 8px 8px, rgba(156, 172, 172, 0.2) 0px 16px 16px, rgba(156, 172, 172, 0.2) 0px 32px 32px, rgba(156, 172, 172, 0.2) 0px 64px 64px;
}
.copy {
position: fixed;
top: 10px;
left: 50%;
transform: translateX(-50%);
font-size: 16px;
color: rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<div class="copy">Send your URL to a friend to start a video call</div>
<video id="localVideo" autoplay muted></video>
<video id="remoteVideo" autoplay></video>
<script src="script.js"></script>
</body>
</html> <script>
// 如果需要,生成随机的房间名称
if (!location.hash) {
location.hash = Math.floor(Math.random() * 0xFFFFFF).toString(16);
}
const roomHash = location.hash.substring(1); console.log(roomHash)
// 用您自己的通道ID替换
const drone = new ScaleDrone('yiS12Ts5RdNhebyM');
//房间名称前须加上“可观察到的-”
const roomName = 'observable-' + roomHash;
const configuration = {
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
};
let room;
let pc; function onSuccess() {};
function onError(error) {
console.error(error);
}; drone.on('open', error => {
if (error) {
return console.error(error);
}
room = drone.subscribe(roomName);
room.on('open', error => {
if (error) {
onError(error);
}
});
// 我们连接到房间并接收到一组“成员”
// 连接到房间(包括我们)。信令服务器准备好了。
room.on('members', members => {
console.log('MEMBERS', members);
// 如果我们是第二个连接到房间的用户,我们将创建offer
const isOfferer = members.length === 2;
startWebRTC(isOfferer);
});
}); // 通过Scaledrone发送信号数据
function sendMessage(message) {
drone.publish({
room: roomName,
message
});
} function startWebRTC(isOfferer) {
pc = new RTCPeerConnection(configuration); // “onicecandidate”在ICE代理需要交付a时通知我们
// 通过信令服务器向另一个对等点发送消息
pc.onicecandidate = event => {
if (event.candidate) {
sendMessage({'candidate': event.candidate});
}
}; // If user is offerer let the 'negotiationneeded' event create the offer
if (isOfferer) {
pc.onnegotiationneeded = () => {
pc.createOffer().then(localDescCreated).catch(onError);
}
} // 当远程流到达时,将其显示在#remoteVideo元素中
pc.ontrack = event => {
const stream = event.streams[0];
if (!remoteVideo.srcObject || remoteVideo.srcObject.id !== stream.id) {
remoteVideo.srcObject = stream;
}
}; navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
}).then(stream => {
// 在#localVideo元素中显示本地视频
localVideo.srcObject = stream;
// 添加要发送到conneting对等点的流
stream.getTracks().forEach(track => pc.addTrack(track, stream));
}, onError); // 听Scaledrone的信号数据
room.on('data', (message, client) => {
// 消息是由我们发出的
if (client.id === drone.clientId) {
return;
} if (message.sdp) {
// 这是在收到来自其他同事的提议或回答后调用的
pc.setRemoteDescription(new RTCSessionDescription(message.sdp), () => {
// 当收到offer时,让我们答复
if (pc.remoteDescription.type === 'offer') {
pc.createAnswer().then(localDescCreated).catch(onError);
}
}, onError);
} else if (message.candidate) {
// 将新的ICE候选项添加到我们的连接远程描述中
pc.addIceCandidate(
new RTCIceCandidate(message.candidate), onSuccess, onError
);
}
});
} function localDescCreated(desc) {
pc.setLocalDescription(
desc,
() => sendMessage({'sdp': pc.localDescription}),
onError
);
} </script>

免费的stun服务器:

stun:stun1.l.google.com:19302
stun:stun2.l.google.com:19302
stun:stun3.l.google.com:19302
stun:stun4.l.google.com:19302
stun:23.21.150.121
stun:stun01.sipphone.com
stun:stun.ekiga.net
stun:stun.fwdnet.net
stun:stun.ideasip.com
stun:stun.iptel.org
stun:stun.rixtelecom.se
stun:stun.schlund.de
stun:stunserver.org
stun:stun.softjoys.com
stun:stun.voiparound.com
stun:stun.voipbuster.com
stun:stun.voipstunt.com
stun:stun.voxgratia.org
stun:stun.xten.com

线上视频必须配置https或者本地localhost  才能实现视频通信

windows配置https

	server {
# HTTPS 默认443端口
listen 443 ssl;
server_name localhost;
# 证书文件配置,指定证书的路径,除了证书路径其他配置都默认
ssl_certificate D:/Dev/https-sll/1_www.deceen.com_bundle.crt;
ssl_certificate_key D:/Dev/https-sll/2_www.deceen.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5:!DH; #设置长连接
keepalive_timeout 70;
#减少点击劫持
add_header X-Frame-Options DENY;
#禁止服务器自动解析资源类型
add_header X-Content-Type-Options nosniff;
#防XSS攻击
add_header X-Xss-Protection 1; # 代码的根目录
root html;
# 默认index
index /video/webrtc/index.html; # 访问日志
#access_log /home/wwwlogs/example.com.log main; # 文件的规则(详见http://seanlook.com/2015/05/17/nginx-location-rewrite/index.html)
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
}
location ~ .*\.(js|css)?$ {
expires 12h;
}
}

  

最新文章

  1. jquery.Callbacks的实现
  2. 清北学堂2017NOIP冬令营入学测试P4749 F’s problem(f)
  3. IT男的”幸福”生活&quot;续3
  4. BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
  5. WEB系统开发
  6. VSS
  7. Shell练习 验证号码
  8. android 实现模拟按键
  9. postgresql sql修改表,表字段
  10. Putty以及adb网络调试
  11. nodejs--express开发个人博客(2)
  12. VS2015在Windows 10 下面安装经验
  13. Android不编译某个模块
  14. 学号:201621123032 《Java程序设计》第14周学习总结
  15. spring boot中使用@Async实现异步调用任务
  16. KafKa记录
  17. EBS CAS SSO测试
  18. P【1012】拼数
  19. .net framework 4.0上跑webapi 1.0
  20. Matplotlib的初次使用

热门文章

  1. 【转】Android DrawingCache
  2. Cassandra使用的各种策略
  3. hadoop不能互相访问和linux防火墙守护进程
  4. 如何《快速搭建LAMP环境》
  5. Linux:使用SecureCRT来上传和下载文件
  6. Redis 6.0.8 紧急发布,请尽快升级!
  7. 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?
  8. Charles的几个用途
  9. xampp安装和使用:windows和linux使用安装微擎小程序
  10. sql注入 --显错注入