WebRTC1-原理探究

1.抛砖引玉

WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流或/和音频流或者其他任意数据的传输
实时查看WebRTC在浏览器中的支持情况: http://caniuse.com/#search=webRTC
FirFox 45+,Chrome 29+,Oprea 36+,Edge 14+,Android Brower 50+支持,其余支持情况有问题。

备注:有的时候会使用adapter.js,这个js文件是为了提高兼容性,可以直接使用API 不用加前缀
使用:
- 下载
- 引用 <script src="adapter.js">

https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/adapter.js

几个概念
- SDP(Session Description Protocol)
SDP是一种会话描述协议,用来描述双方的IP地址和端口号,通信所使用的带宽,会话的名称、标识符、激活时间,双方所要传输的媒体类型(视频、音频、文本)、媒体格式等等。该协议仅包含所要传递的媒体的描述信息,而不直接传递媒体内容。
- ICE(Interactive Connectivity Establishment)
ICE是一种以UDP为基础用于实现穿越NAT网管或者防火墙的协议。
- TURN&&STUN
两种协议都是用来明确自己的外网地址的,差别是如果要服务器辅助进行数据交换则设置TURN服务器,不需要则设置STUN服务。

核心API
- Navigator.getUserMedia
用来获取视频和音频,在浏览器装有摄像头和麦克风的情况下使用.navigator.getUserMedia(constraints, successCallback, errorCallback);constraints是用来控制视频和音频是否获取,一般设为{video:true,audio: true},即视频和音频都获取。
- RTCPeerConnection
RTCPeerConnection是一个表示两个浏览器端的连接的对象,其含有关于这个连接的所有信息和相关方法,是WebRTC的核心API,负责制作建立连接的SDP、ICE等报文,管理连接状态等等。
- RTCDataChannel
RTCDataChannel由RTCPeerConnection创建,需要传递视频、音频以外的数据时使用,它代表浏览器两端间的一个数据通道,和这个数据通道有关的属性和方法都记录在这个对象里。

2.按图索骥


过程:
1. 首先双方都建立一个RTCPeerConnection的实例,其中一方(称为offer方)用RTCPeerConnection.createOffer()创建一个会话描述sessionDescription,该会话描述包含SDP报文信息和该sessionDescription的类型(type)
2. 接下来调用RTCPeerConnection.setLocalDescription()方法将本地的localDescription设置为刚才创建的sessionDescription。之后将创建的sessionDescription发送给对方(称为answer方),发送方式没有规定,可以通过服务器中转,可以通过IM软件发送(这里使用WebSocket信令服务器)。
3. answer端接收到sessionDescription后调用RTCPeerConnection. setRemoteDescription方法设置,然后调用RTCPeerConnection. createAnswer方法产生自己的sessionDescription
4. 再将创建的sessionDescription发送给offfer方,同样发送方式没有规定。offer方接收到sessionDescrip后调用RTCPeerConnection. setRemoteDescription方法设置,这样双方的SDP信息就交换完成了。
5. 在完成SDP的交换后双方还要交换ICE candidate信息。双方首先设置RTCPeerConnection.onicecandidate回调函数,当candidate可用时,双方中的一方将所有icecandidate发送给对方,发送方式同样没有规定,接收方调用RTCPeerConnection.addIceCandidate方法接收candidate信息。经过这些步骤后双方连接就建立完成了。

3.纸上可谈兵

3.1.由简入繁

html文件

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="keywords" content="JavaScript, WebRTC" />
    <meta name="description" content="WebRTC" />
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1">
    <title>获取本地视频</title>
    <link rel="stylesheet" href="simpleVideo.css">
</head>

<body>
    <!-- <video /> -->
    <video></video>
    <p><br></p>
    <script src='../lib/adapter.js'></script>
    <script type="text/javascript" src="simpleVideo.js"></script>
</body>
</html>

js文件:

var constraints = {
    video: true,
    audio:true
};

function successCallback(stream) {
    window.stream = stream; // stream available to console
    console.log(stream);
    console.log(stream.getVideoTracks());
    console.log(stream.getAudioTracks());

    var video = document.querySelector("video");
    video.src = window.URL.createObjectURL(stream);
    video.play();
}

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

getUserMedia(constraints, successCallback, errorCallback);
3.2.顺藤摸瓜

这是个完整的例子,参照2.按图索骥部分理解

<!DOCTYPE html>
<html>

<head>
    <meta name="keywords" content="JavaScript, WebRTC" />
    <meta name="description" content="WebRTC codelab" />
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1">
    <title>WebRTC codelab: step 2</title>
    <link rel="stylesheet" href="css/index.css">
    <!-- css可以使用一些滤镜效果 -->
    <style>

    </style>
    <script src='js/lib/adapter.js'></script>
</head>

<body>
    <video id="localVideo" autoplay muted></video>
    <video id="remoteVideo" autoplay muted></video>
    <div>
        <button id="startButton">Start</button>
        <button id="callButton">Call</button>
        <button id="hangupButton">Hang Up</button>
    </div>
    <script src="index.js">
</body>

</html>

index.js

    <script>
    var localStream, localPeerConnection, remotePeerConnection;

    var localVideo = document.getElementById("localVideo");
    var remoteVideo = document.getElementById("remoteVideo");

    var startButton = document.getElementById("startButton");
    var callButton = document.getElementById("callButton");
    var hangupButton = document.getElementById("hangupButton");
    startButton.disabled = false;
    callButton.disabled = true;
    hangupButton.disabled = true;
    startButton.onclick = start;
    callButton.onclick = call;
    hangupButton.onclick = hangup;

    function trace(text) {
        console.log((performance.now() / 1000).toFixed(3) + ": " + text);
    }

    function gotStream(stream) {
        trace("Received local stream");
        localVideo.src = URL.createObjectURL(stream);
        localStream = stream;
        callButton.disabled = false;
    }

    function start() {
        trace("Requesting local stream");
        startButton.disabled = true;
        getUserMedia({
                audio: true,
                video: true
            }, gotStream,
            function(error) {
                trace("getUserMedia error: ", error);
            });
    }

    function call() {
        callButton.disabled = true;
        hangupButton.disabled = false;
        trace("Starting call");

        if (localStream.getVideoTracks().length > 0) {
            trace('Using video device: ' + localStream.getVideoTracks()[0].label);
        }
        if (localStream.getAudioTracks().length > 0) {
            trace('Using audio device: ' + localStream.getAudioTracks()[0].label);
        }

        var servers = null;//本机测试不用其他服务器

        localPeerConnection = new RTCPeerConnection(servers);//offer方
        trace("Created local peer connection object localPeerConnection");
        localPeerConnection.onicecandidate = gotLocalIceCandidate;//offer方发送ICE
        remotePeerConnection = new RTCPeerConnection(servers);//answe方
        trace("Created remote peer connection object remotePeerConnection");
        remotePeerConnection.onicecandidate = gotRemoteIceCandidate;//answer方发送ICE
        remotePeerConnection.onaddstream = gotRemoteStream;//设置视频流

        localPeerConnection.addStream(localStream);
        trace("Added localStream to localPeerConnection");
        localPeerConnection.createOffer(gotLocalDescription, handleError);//作为offer,产生自己的SessionDescription【SD】信息
    }

    function gotLocalDescription(description) {//description是offer方的SD
        localPeerConnection.setLocalDescription(description);
        trace("Offer from localPeerConnection: \n" + description.sdp);
        remotePeerConnection.setRemoteDescription(description);//answer方接收offer的SD
        remotePeerConnection.createAnswer(gotRemoteDescription, handleError);//answer方发送自己的SD
    }

    function gotRemoteDescription(description) {
        remotePeerConnection.setLocalDescription(description);//anwer方设置本身自己的SD
        trace("Answer from remotePeerConnection: \n" + description.sdp);
        localPeerConnection.setRemoteDescription(description);//offer接收answer方的SD
    }

    function hangup() {
        trace("Ending call");
        localPeerConnection.close();
        remotePeerConnection.close();
        localPeerConnection = null;
        remotePeerConnection = null;
        hangupButton.disabled = true;
        callButton.disabled = false;
    }

    function gotRemoteStream(event) {
        remoteVideo.src = URL.createObjectURL(event.stream);
        trace("Received remote stream");
    }

    function gotLocalIceCandidate(event) {
        if (event.candidate) {
            remotePeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));//answer方接收ICE
            trace("Local ICE candidate: \n" + event.candidate.candidate);
        }
    }

    function gotRemoteIceCandidate(event) {
        if (event.candidate) {
            localPeerConnection.addIceCandidate(new RTCIceCandidate(event.candidate));//offer方接收ICE
            trace("Remote ICE candidate: \n " + event.candidate.candidate);
        }
    }

    function handleError() {}
    </script>

另外加一些CSS可以很容易实现滤镜效果

    video {
    filter: hue-rotate(180deg) saturate(200%);
    -moz-filter: hue-rotate(180deg) saturate(200%);
    -webkit-filter: hue-rotate(180deg) saturate(200%);
}

运行这两段代码,就可以调出来本地视频窗口

参考资料

强烈推荐的WebRTC入门教程
google webRTC
WebRTC官网
WebRTC-W3School
MDN-WebRTC

WebRTC实践教程
使用WebRTC搭建前端视频聊天室——信令篇
可以用WebRTC来做视频直播吗?-知乎
实时猫–WebRTC服务商

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: webrtc-qt-example是一个基于Qt框架开发的WebRTC示例项目。 WebRTC是一种开源的实时通信技术,能够支持音频、视频和数据的实时传输。它通过浏览器之间的端对端连接,实现了高质量的实时通信。 webrtc-qt-example的目的是展示如何使用Qt进行WebRTC开发。Qt是一套跨平台的C++应用程序开发框架,它提供了丰富的工具和库,使开发者能够快速构建可靠的应用程序。 这个示例项目提供了一些基本的功能和界面,使开发者能够了解和学习如何将WebRTC集成到Qt应用程序中。它包含了常见的WebRTC功能,如媒体流捕获、媒体流传输、信令交换等。 通过webrtc-qt-example,开发者可以学习到如何使用Qt的多媒体模块来捕获音频、视频和媒体设备。同时,也可以学习到如何使用Qt的网络模块来进行实时信令交换和流传输。 这个示例项目还提供了一些简单的界面,方便开发者进行测试和调试。开发者可以通过该界面实现与其他WebRTC应用的通信,例如建立视频通话、音频通话等。 总之,webrtc-qt-example是一个非常实用的示例项目,可以帮助开发者快速上手并掌握WebRTC在Qt中的开发。 ### 回答2: webrtc-qt-example是一个基于Qt框架的WebRTC示例应用程序。WebRTC是一种开源项目,它提供了在浏览器之间进行实时通信的能力,包括视频和音频的传输。而webrtc-qt-example则是将这种技术集成到Qt应用程序中的一个示例。 在webrtc-qt-example中,它使用了Qt的多媒体框架和WebRTC提供的API来实现音视频的传输和显示。通过使用WebRTC的API,webrtc-qt-example可以建立点对点的连接,进行音频和视频的实时传输。 webrtc-qt-example中的代码结构清晰,易于理解和扩展。它提供了一些基本的功能,如建立连接、发送和接收音视频流、呼叫取消等。开发者可以根据自己的需求来对这些功能进行定制和扩展。 此外,webrtc-qt-example还支持一些高级特性,如媒体设备的选择、音视频的编码和解码等。开发者可以通过修改代码来选择不同的媒体设备,并且可以使用不同的编码和解码算法来满足自己的需求。 总之,webrtc-qt-example是一个很棒的WebRTC示例应用程序,它可以帮助开发者快速了解和使用WebRTC技术。无论是为了实现实时视频通话、视频会议还是其他需要音视频传输的应用场景,webrtc-qt-example都提供了一个良好的起点,帮助开发者快速上手并实现自己的需求。 ### 回答3: webrtc-qt-example是一个基于Qt框架和WebRTC技术的示例应用。WebRTC是一种用于在Web浏览器上实现实时通信的开源项目,它提供了一套丰富的API和协议,可以实现音视频通话、数据传输以及屏幕共享等功能。 webrtc-qt-example利用Qt框架提供的跨平台能力,结合WebRTC技术,展示了在Qt应用中如何实现实时通信功能。这个示例应用具有以下特点和功能: 1. 界面友好:webrtc-qt-example使用Qt的GUI绘制工具,具有美观、直观的用户界面,便于用户操作和使用。 2. 实时通信:webrtc-qt-example内置了WebRTC的音视频通信功能,可以实现实时的语音和视频通话,支持两个或多个用户之间的通信。 3. 数据传输:除了音视频通话,webrtc-qt-example还支持在通话中传输数据。可以通过编写代码,实现实时文本传输或共享文件等功能。 4. 屏幕共享:webrtc-qt-example还支持屏幕共享功能,可以将自己的屏幕内容分享给其他用户,实现远程协助或在线教育等应用场景。 通过webrtc-qt-example的学习和实践,开发者可以了解并深入理解WebRTC技术的使用方法,以及在Qt框架中的应用。同时,借助webrtc-qt-example提供的示例代码和API文档,开发者可以进一步开发出更加复杂和功能丰富的实时通信应用,满足不同领域的需求。 总之,webrtc-qt-example是一个基于Qt框架和WebRTC技术的示例应用,具备实时音视频通话、数据传输和屏幕共享等功能,适用于开发者学习、实践和开发基于WebRTC的实时通信应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值