熟悉webrtc
WebRTC用来协助建立p2p通讯的。主要用于协商双方通讯过程,传递基本信息,如:会话控制信息,用来开始和结束通话,即开始视频、结束视频这些操作指令;处理错误的消息;元数据,如各自的音视频解码方式、带宽;网络数据,对方的公网IP、端口、内网IP及端口。但是WebRTC的API并没有实现信令通信机制,所以使用者需要自己去实现。常见的信令交互图如下
- Amy、Bob均实例化一个RTCPeerConnection(以下简称rpcA和rpcB),调用rpcA的
createOffer()
方法建立一个offer信令,并且拿到A的SDP - 通过rpcA的
setLocalDescription()
方法设置A机器的本地描述 - A通过服务器将offer信令发给B
- B接收到A的offer信令,通过rpcB的
setRemoteDescription()
方法设置远程机器(即A)的描述 - B调用rpcB的
createAnswer()
方法建立一个answer信令,并且拿到B的SDP - 通过rpcB的
setLocalDescription()
方法设置B机器的本地描述 - B通过服务器将answer信令发送给A
- A接收到B的answer信令,通过rpcA的
setRemoteDescription()
方法设置远程机器B的描述
sdp(Session Description Protocol)是一种会话描述协议,属于文本协议,即WebRTC中常说的信令(Signalling),是WebRTC用来协助建立p2p通讯的。主要用于协商双方通讯过程,传递基本信息,如:会话控制信息,用来开始和结束通话,即开始视频、结束视频这些操作指令;处理错误的消息;元数据,如各自的音视频解码方式、带宽;网络数据,对方的公网IP、端口、内网IP及端口。但是WebRTC的API并没有实现信令通信机制,所以使用者需要自己去实现。常见的信令交
现在看一个关于屏幕分享的小案例
案例展示
用到的是vue-webrtc
代码展示(父组件)
<template>
<div class="container">
<div class="row">
<div class="col-md-12 my-3">
<h2>Room</h2>
<input v-model="roomId" />
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class>
<vue-webrtc
ref="webrtc"
width="100%"
:roomId="roomId"
v-on:joined-room="logEvent"
v-on:left-room="logEvent"
v-on:opened-room="logEvent"
v-on:share-started="logEvent"
v-on:share-stopped="logEvent"
@error="onError"
/>
</div>
<div class="row">
<div class="col-md-12 my-3">
<button type="button" class="btn btn-primary" @click="onJoin">Join</button>
<button type="button" class="btn btn-primary" @click="onLeave">Leave</button>
<button type="button" class="btn btn-primary" @click="onCapture">Capture Photo</button>
<button type="button" class="btn btn-primary" @click="onShareScreen">Share Screen</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h2>Captured Image</h2>
<figure class="figure">
<img :src="img" class="img-responsive" />
</figure>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { WebRTC } from 'plugin';
import { find, head } from 'lodash';
Vue.component(WebRTC.name, WebRTC);
export default {
name: 'app',
components: {
},
data () {
return {
img: null,
roomId: "public-room"
};
},
computed: {
},
watch: {
},
methods: {
onCapture () {
this.img = this.$refs.webrtc.capture();
},
onJoin () {
this.$refs.webrtc.join();
},
onLeave () {
this.$refs.webrtc.leave();
},
onShareScreen () {
this.img = this.$refs.webrtc.shareScreen();
},
onError (error, stream) {
console.log('On Error Event', error, stream);
},
logEvent (event) {
console.log('Event : ', event);
},
}
};
</script>
子组件接收
点击分享按钮
shareScreen () {
var that = this;
if (navigator.getDisplayMedia || navigator.mediaDevices.getDisplayMedia) {
function addStreamStopListener (stream, callback) {
console.log(stream, 'stream')
var streamEndedEvent = 'ended';
if ('oninactive' in stream) {
streamEndedEvent = 'inactive';
}
stream.addEventListener(streamEndedEvent, function () {
callback();
callback = function () { };
}, false);
}
function onGettingSteam (stream) {
that.rtcmConnection.addStream(stream);
that.$emit('share-started', stream.streamid);
addStreamStopListener(stream, function () {
that.rtcmConnection.removeStream(stream.streamid);
that.$emit('share-stopped', stream.streamid);
});
}
function getDisplayMediaError (error) {
console.log('Media error: ' + JSON.stringify(error));
}
// 出现弹框
if (navigator.mediaDevices.getDisplayMedia) {
// 异步请求
navigator.mediaDevices.getDisplayMedia({ video: true, audio: false }).then(stream => {
onGettingSteam(stream);
}, getDisplayMediaError).catch(getDisplayMediaError);
}
else if (navigator.getDisplayMedia) {
debugger
navigator.getDisplayMedia({ video: true }).then(stream => {
onGettingSteam(stream);
}, getDisplayMediaError).catch(getDisplayMediaError);
}
}
}