webRTc实现视频直播

本文详细介绍了如何使用WebRTC技术实现实时视频通话,包括生成随机房间名称、使用ScaleDrone进行信令交换、配置ICE服务器、建立RTCPeerConnection、获取用户媒体设备、创建offer与answer以及处理ICE候选等关键步骤。
<!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;
        }
    }

  

转载于:https://www.cnblogs.com/gfweb/p/11252001.html

### 使用 WebRTC 实现视频直播功能 WebRTC 是一种强大的开源项目,旨在支持浏览器和移动应用程序之间的实时通信。通过使用 WebRTC 技术,可以轻松构建一个高效的视频直播系统[^1]。 以下是实现视频直播的关键组件和技术要点: #### 获取音视频流 要启动视频直播过程,首先需要从用户的设备捕获音频和视频数据。这可以通过 `navigator.mediaDevices.getUserMedia` 方法完成。该方法允许访问摄像头和麦克风,并返回媒体流对象。 ```javascript async function getMediaStream() { const constraints = { video: true, audio: true }; try { const stream = await navigator.mediaDevices.getUserMedia(constraints); return stream; } catch (error) { console.error('Error accessing media devices.', error); } } ``` 此代码片段展示了如何请求并获取用户的音视频输入流。 #### 创建 RTCPeerConnection 对象 为了建立点对点连接,需创建一个 `RTCPeerConnection` 对象实例。这个对象负责管理两个端点之间所有的音视频传输以及相关的控制信号传递。 ```javascript const peerConnection = new RTCPeerConnection(); ``` 接着将之前获得的本地媒体流添加到 Peer Connection 中以便发送给远端用户。 ```javascript function addLocalStreamToPeerConnection(stream) { stream.getTracks().forEach(track => { peerConnection.addTrack(track, stream); }); } ``` 上述函数演示了怎样把本地音视频轨道加入到已初始化好的 RTCPeerConnection 当中去。 #### 处理会话描述协议(SDP) 当设置好初始条件之后,下一步就是生成 SDP 并将其传送给对方以协商双方的能力范围。这里涉及到 Offer 和 Answer 的交互流程。 ```javascript async function createOffer() { const offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); sendSignalingData(peerConnection.localDescription); // 发送至信令服务器 } async function handleAnswer(answer) { await peerConnection.setRemoteDescription(new RTCSessionDescription(answer)); } ``` 这些操作确保两端能够理解彼此的技术参数从而顺利开展进一步的数据交换活动。 #### 利用 ICE 候选者机制优化网络性能 除了基本的消息往来之外,还需要考虑 NAT 跨越等问题来提升跨地域间的连通率。ICE 协议正好满足这一需求,它自动寻找最佳路径来进行实际的内容交付工作。 每当发现新的候选地址时都需要及时通知另一方知晓最新情况: ```javascript peerConnection.onicecandidate = event => { if (event.candidate) { sendSignalingData(event.candidate); // 向信令服务器提交新找到的路由选项 } }; ``` 以上部分解释了有关于处理 ICE Candidates 的具体做法。 #### 录制视频通话 如果希望保存整个会议记录下来,则可借助 MediaRecorder API 完成这项任务。下面给出了一段简单的例子说明录制过程是如何运作的。 ```javascript let recordedChunks = []; const recorder = new MediaRecorder(localStream); recorder.ondataavailable = event => { if (event.data.size > 0) { recordedChunks.push(event.data); } }; recorder.start(); // Stop recording after some time or upon user request. setTimeout(() => { recorder.stop(); }, 5 * 60 * 1000); // Example duration of five minutes. // After stopping the recorder... recorder.onstop = () => { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); console.log(`Recorded video available at ${url}`); }; ``` 这段脚本实现了对于正在进行中的呼叫内容进行捕捉存储的功能[^2]。 --- ### 总结 综上所述,利用 WebRTC 构建一套完整的视频直播解决方案涉及到了多个方面的知识点覆盖,包括但不限于采集多媒体资源、配置 P2P 链接环境、制定详细的会话规划书等等环节。每一步都至关重要缺一不可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值