<!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;
}
}

  

webRTc实现视频直播的更多相关文章

  1. Android IOS WebRTC 音视频开发总结(六六)-- 三个角度分析美女视频直播这个行业

    本文主要从用户,公司和技术角度分析美女视频直播这个行业,文章最早发表在我们的微信公众号上,支持原创,详见这里, 欢迎关注微信公众号blackerteam,更多详见www.rtc.help 美女视频直播 ...

  2. Android IOS WebRTC 音视频开发总结(五八)-- 图文解说视频直播原理

    本文主要介绍rtmp&hls视频直播原理,文章最早发表在我们的微信公众号上,详见这里,欢迎关注微信公众号blackerteam,更多详见www.blackerteam.com 现在视频直播很火 ...

  3. Vue + WebRTC 实现音视频直播(附自定义播放器样式)

    1. 什么是WebRTC 1.1 WebRTC简介 WebRTC,名称源自网页即时通信(英语:Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频 ...

  4. 10┃音视频直播系统之 WebRTC 中的数据统计和绘制统计图形

    一.数据统计 在视频直播中,还有一项比较重要,那就是数据监控 比如开发人员需要知道收了多少包.发了多少包.丢了多少包,以及每路流的流量是多少,才能评估出目前用户使用的音视频产品的服务质量是好还是坏 如 ...

  5. 12┃音视频直播系统之 WebRTC 实现1对1直播系统实战

    一.搭建 Web 服务器 前面我们已经实现过,但是没有详细说HTTPS服务 首先需要引入了 express 库,它的功能非常强大,用它来实现 Web 服务器非常方便 同时还需要引入 HTTPS 服务, ...

  6. Android IOS WebRTC 音视频开发总结(七六)-- 探讨直播低延迟低流量的粉丝连麦技术

    本文主要探讨基于WebRTC的P2P直播粉丝连麦技术 (作者:郝飞,亲加云CTO,编辑:dora),最早发表在[这里] 支持原创,转载必须注明出处,欢迎关注微信公众号blacker(微信ID:blac ...

  7. 【腾讯bugly干货分享】HTML 5 视频直播一站式扫盲

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1277 视频直 ...

  8. 【腾讯Bugly干货分享】H5 视频直播那些事

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57a42ee6503dfcb22007ede8 Dev Club 是一个交流移动 ...

  9. Android IOS WebRTC 音视频开发总结(八十一)-- WebRTC靠谱吗?有没有适合的SDK推荐?

    作者:blaker,最早发表在我们的微信公众和[编风网],详见[这里] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:blackerteam 或 webrtcorgcn) ...

随机推荐

  1. 如何把一个一般的git库变成“裸库”?

    语法: git clone --bare 「src」 「dest」 e.g. cd ~/Workspace/SourceRepo/ git clone --bare ./ ../Git/bareRep ...

  2. Python文件.py转换为.exe可执行程序,制作.exe文件图标

    当大家想要将自己写的Python程序对别人进行展示的时候,你是否还是打开你的Pycharm进行运行展示? 假如是专业的人士看你的代码,一眼就能看懂你的代码,而其实我们可以不需要给代码,利用pyinst ...

  3. LongAccumulator类的BUG——reset方法并不能保证初始值正确赋值

    LongAccumulator.reset方法并不能重置重置LongAccumulator的identity:初始值正确,使其恢复原来的初始值.当初始值为0是不会发生这个问题,而当我们设置初始值如1时 ...

  4. Python 面试题 字符串 删除多少个字符使得出现做多的字符数量大于等于字符串长度的一半.

    str1 = input() num = {} for i in set(str1): num[i]=str1.count(i) max_value = max(num.values()) n=abs ...

  5. Unity接入多个SDK的通用接口开发与资源管理(三)

    接着上篇,介绍SDK资源的导入.首先介绍一下Android Studio工程. AS工程可以由多个Module组成,我们可以把某个Module作为我们打包的Module,其他的Module当做资源导入 ...

  6. 安装模块中出现的问题:不是内部或外部命令、pip 命令不存在、Unknown or unsupported command 'install'

    #cmd下python.pip不是内部或外部命令——表示环境变量没有加# path中新增1.python的安装目录# 2.python下scripts的目录 #提示 pip 命令不存在——表示环境变量 ...

  7. 刀哥多线程自动释放池autoreleasepool

    自动释放池 作用 自动释放对象的 所有 autorelease 的对象,在出了作用域之后,会被自动添加到最近创建的自动释放池中 自动释放池被销毁或者耗尽时,会向池中所有对象发送 release 消息, ...

  8. 深入分析Linux内核链表

    1. 普通单链表 2. 内核链表 上图是本人从其他博客盗来的,差点被糊弄过去. 下图是本人自己用KeyNote画的(唉!!画图真的是让人心好累啊!!). 差异是不是很明显啊?! Read The Fu ...

  9. Scala的lazy应用

    如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会起作用. 例如:对于特别耗时的的计算操作特别有用,如打开文件IO,网络IO等. import scala.io.Sourc ...

  10. vue简单案例_动态添加删除用户数据

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...