webRTC 入门

概念

  • WebRTC基础介绍
    webRTC 的最直接用途是两个浏览器间的p2p,不过加上中转服务器后也可以用来做其他的。
    webRTC 是基于UDP的,作为对比,webSocket 是基于TCP的。
    webRTC 入门_第1张图片

  • Mesh,SFU,MCU 的区别

    • Mesh: p2p
    • SFU: 中心节点只转发
    • MCU:中心节点混流
      webRTC 入门_第2张图片
  • STUN 和 TURN

    • STUN 只处理地址信息
    • TURN 提供转发功能
      webRTC 入门_第3张图片
      webRTC 入门_第4张图片

流程

除了getUserMedia之外,主要是两件事情:

  1. 两端间确定流媒体的格式(SDP)
  2. 两端间确定对方的网络地址(ICE), 由于浏览器极有可能是在内网中的,所以需要有一般的p2p内网穿透的过程

webRTC 入门_第5张图片

调试工具

chrome://webrtc-internals/
https://test.webrtc.org/

代码

官方的例子

getUserMedia


<html lang="zh-CN">
	<head> <meta charset="UTF-8">
		<title>GetUserMedia实例title>
	head>
	<body>
	<video id="video" autoplay>video>
body>
<script type="text/javascript" src="webRTC.js">script>
html>
// simple camera
var constraints = {
    video: true
};

function successCallback(stream) {
    var video = document.querySelector("video");
    //window.URL.createObjectURL is deprecated, so just assign the stream directly
    //video.src=window.URL.createObjectURL(stream);
    video.srcObject = stream;
}

function errorCallback(error) {
    console.log("navigator.getUserMedia error:", error);
}

navigator.getUserMedia(constraints, successCallback, errorCallback);

local


<html>
<head>
    <meta charset="utf-8">
    <title>webrtc案例title>
head>
<body>
    <div class="container">
        <h1>单机版视频呼叫h1>
        <hr>
        <div class="video_container" align="center">
            <video id="local_video" autoplay playsinline muted>video>
            <video id="remote_video" autoplay>video>
        div>
        <hr>
        <div class="button_container">
            <button id="startButton">采集视频button>
            <button id="callButton">呼叫button>
            <button id="hangupButton">关闭button>
        div>
        <script src="main.js">script>
    div>
body>
html>
var startButton = document.getElementById('startButton');
var callButton = document.getElementById('callButton');
var hangupButton = document.getElementById('hangupButton');
callButton.disabled = true;
hangupButton.disabled = true;

startButton.addEventListener('click', startAction);
callButton.addEventListener('click', callAction);
hangupButton.addEventListener('click', hangupAction);

var localVideo = document.getElementById('local_video');
var remoteVideo = document.getElementById('remote_video');
var localStream;
var pc1;
var pc2;

const offerOptions = {
    offerToReceiveVideo: 1,
    offerToReceiveAudio: 1
};

function startAction() {
    //采集摄像头视频
    navigator.mediaDevices.getUserMedia({
            video: true,
            audio: true
        })
        .then(function(mediaStream) {
            localStream = mediaStream;
            localVideo.srcObject = mediaStream;
            startButton.disabled = true;
            callButton.disabled = false;
        }).catch(function(error) {
            console.log(JSON.stringify(error));
        });
}

function callAction() {

    hangupButton.disabled = false;
    callButton.disabled = true;

    pc1 = new RTCPeerConnection();
    pc1.addEventListener('icecandidate', function(event) {
        console.log("p1 ice candidate:", event);
        var iceCandidate = event.candidate;
        if (iceCandidate) {
            // 实际通信中,这里应为pc1 把iceCandidate发送给Signal服务器,Signal服务器(通过websocket?)把p1 candidate的信息告诉p2
            pc2.addIceCandidate(iceCandidate);
        }
    });
    localStream.getTracks().forEach(track => pc1.addTrack(track, localStream));

    pc2 = new RTCPeerConnection();
    pc2.addEventListener('addstream', function(event) {
        console.log("p2 add stream", event)
        remoteVideo.srcObject = event.stream;
    });

    pc1.createOffer(offerOptions).then(function(offer) {
        console.log("p1 createOffer", offer);
        pc1.setLocalDescription(offer);
        // 实际通信中, p1 应该把offer 通过Signal服务器发给p2
        pc2.setRemoteDescription(offer);

        pc2.createAnswer().then(function(description) {

            console.log("p2 createAnswer", description);
            pc2.setLocalDescription(description);
           // 实际通信中, p2 应该把 answer 通过Signal服务器发给p1
            pc1.setRemoteDescription(description);
        });
    });
}

function hangupAction() {
    localStream.getTracks().forEach(track => track.stop());
    pc1.close();
    pc2.close();
    pc1 = null;
    pc2 = null;
    hangupButton.disabled = true;
    callButton.disabled = true;
    startButton.disabled = false;
}

加入socket.io

你可能感兴趣的:(网络,web)