p2p 通信 但是占用性能
const config = {
iceServers: [{ urls: "stun:global.stun.twilio.com:3478?transport=udp" }],
}; 采用穿透技术
localStream 存储本地视频源的地方
获取本地视频源
const constraints = {
audio: {
mandatory: {
chromeMediaSource: "desktop",
},
},
video: {
mandatory: {
chromeMediaSource: "desktop",
},
},
};
let constraints = {
video: true,
audio: {
// 设置降噪
noiseSuppression: true,
// 设置回音消除
echoCancellation: true,
},
logicalSurface: false,
};
await navigator.mediaDevices
.getUserMedia(constraints)
.then((mediaStream) => {
this.gotLocalMediaStream(mediaStream);
})
.catch((err) => {
console.log("getUserMedia 错误", err);
//创建点对点连接对象
});
创建 createOffer 并监听ice变化
createConnection() {
peerConnection = new RTCPeerConnection(null);
console.log(localStream);
if (localStream) {
// 视频轨道
const videoTracks = localStream.getVideoTracks();
// 音频轨道
const audioTracks = localStream.getAudioTracks();
// 判断视频轨道是否有值
if (videoTracks.length > 0) {
console.log(videoTracks);
console.log(`使用的设备为: ${videoTracks[0].label}.`);
}
// 判断音频轨道是否有值
if (audioTracks.length > 0) {
console.log(`使用的设备为: ${audioTracks[0].label}.`);
}
localStream.getTracks().forEach((track) => {
peerConnection.addTrack(track, localStream);
});
}
// 监听返回的 Candidate
peerConnection.addEventListener("icecandidate", function (event) {
// 获取到触发 icecandidate 事件的 RTCPeerConnection 对象
// 获取到具体的Candidate
console.log("handleConnection:" + event.target);
});
// 监听 ICE 状态变化
peerConnection.addEventListener(
"iceconnectionstatechange",
function (event) {
const peerConnection = event.target;
console.log("ICE state change event: ", event);
console.log(`ICE state: ` + `${peerConnection.iceConnectionState}.`);
}
);
},
//创建发起方会话描述对象(createOffer),设置本地SDP(setLocalDescription),并通过信令服务器发送到对等端,以启动与远程对等端的新WebRTC连接。
startConnection() {
// 发送offer
peerConnection
.createOffer()
.then((offer) => {
// console.log(`本地创建offer返回的sdp:\n${offer.sdp}`);
// 将 offer 保存到本地
peerConnection
.setLocalDescription(offer)
.then(() => {
console.log("local 设置本地描述信息成功");
// 本地设置描述并将它发送给远端
this.pushStreamConnection(offer);
})
.catch((err) => {
console.log("local 设置本地描述信息错误", err);
});
})
.catch((err) => {
console.log("createdOffer 错误", err);
});
},
本地推流
pushStreamConnection(offer) {
let self = this;
let res = this.videoSrc
var webRtcUrl;
// var webRtcUrl 设置推流线上地址
var urlParams = JSWebrtc.ParseUrl(webRtcUrl);
var port = urlParams.port || 80;
// @see https://github.com/rtcdn/rtcdn-draft
var api = urlParams.user_query.play || "/rtc/v1/publish";
if (api.lastIndexOf("/") != api.length - 1) {
api += "/";
}
var url = "http://" + urlParams.server + ":" + port + api;
for (var key in urlParams.user_query) {
if (key != "api" && key != "play") {
url += "&" + key + "=" + urlParams.user_query[key];
}
}
// @see https://github.com/rtcdn/rtcdn-draft
var data = {
api: url,
streamurl: urlParams.url,
clientip: null,
sdp: offer.sdp,
};
console.log("offer: " + JSON.stringify(data));
JSWebrtc.HttpPost(url, JSON.stringify(data)).then(
function (res) {
console.log(res.code);
if (res.code == 400) {
// self.$message.error("请求不正确,URL 或者 参数不正确");
return;
}
console.log("answer: " + JSON.stringify(res));
peerConnection.setRemoteDescription(
new RTCSessionDescription({ type: "answer", sdp: res.sdp })
);
// resolve(res.sdp);
},
function (rej) {
console.log(rej);
}
);
},
清空链接
hangupHandle() {
// 关闭连接并设置为空
peerConnection.close();
peerConnection = null;
localStream.getTracks().forEach((track) => {
track.stop();
});
},
加班万岁!