<!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. Redis适配采坑记

    Redis适配采坑记 相对于其他的适配,Redis可以说是非常简单的其中只发现一个坑 问题一: 问题描述: redis认证失败 问题详解: redis连接配置时,本地需要采用password属性,远程 ...

  2. Spring 框架(持续完善中)

    目录标题 一.Spring 框架 Spring 是什么? Spring Framework 核心概念 了解Spring 框架的架构图 二.Spring Framework 之 IOC 开发的步骤流程 ...

  3. 用命令方式启动、停止appium服务和app

    启动appium服务并监听一个端口命令: 命令command==> appium -a {ip} -p {port} -U {deviceName} -g {log} 以shell命令方式执行命 ...

  4. PHP相关的书签内容

    ThinkPHP函数详解 session方法 --ThinkPHP 开源PHP框架 ThinkPHP实现支付宝接口功能 - /折磨 - 博客园 php几个常用的概率算法(抽奖.广告首选) - 懒人技术 ...

  5. sql.表值类型

    表值类型是在sql server 2008中新加入的功能,我个人觉得确实很有用,之前从没用过,自从来到现在的公司后学到很多东西,所以和大家分享一下. ------建表值类型语法------------ ...

  6. Python3使用钉钉机器人推送消息(签名方式)

    import time import hmac import hashlib import base64 import urllib import json import requests impor ...

  7. Redis集群模式(Cluster)部署

    1. 安装依赖包 注意:本节需要使用root用户操作 1.1 安装ruby yum install ruby -y yum install ruby-devel.x86_64 -y 1.2 安装rub ...

  8. JS中call()、apply()、bind()的用法

    其实是一个很简单的东西,认真看十分钟就从一脸懵B 到完全 理解! 先看明白下面: 例1 obj.objAge;  //17 obj.myFun()  //小张年龄undefined 例2 shows( ...

  9. Linux常用命令详解(2)

    aliasunaliasunamesuhostnamehistorywhichwcwwhowhoamipingkillseqdudffreedate 命令详解 1. alias 设置.’查看别名 实例 ...

  10. springboot 配置和使用过滤器

    首先在Application文件中添加注解@ServletComponentScan自动扫描当前类的同包以及子包,这样才能将filter装入bean package com.example.acade ...