ball_admin/src/util/webRtc.ts

176 lines
5.6 KiB
TypeScript

import Config from "./config";
class WebRtc {
private mediaStream: MediaStream | Blob | null = null;
private pee: RTCPeerConnection | null = null;
private ws: WebSocket | null = null;
private video: HTMLVideoElement | null = null;
private userToId: string = "";
open = () => {
this.ws?.send(JSON.stringify({
type: "new", "data": {
"name": "admin",
"id": "31283192",
"user_agent": "flutter-webrtc/js"
}
}))
}
async init() {
this.ws = new WebSocket(Config.rtc)
this.ws.addEventListener('open', this.open);
let that = this;
this.createOffer()
this.ws.onmessage = function (evt) {
let msg = JSON.parse(evt.data)
if (!msg) {
return console.log('failed to parse msg')
}
switch (msg.type) {
case 'offer':
let offer = msg.data.description
that.pee?.setRemoteDescription(offer)
that.pee?.createAnswer().then(answer => {
that.pee?.setLocalDescription(answer)
that.ws?.send(JSON.stringify({
type: 'answer', data: {
'to': msg.data.from,
'from': "31283192",
'description': { 'sdp': answer.sdp, 'type': answer.type },
'session_id': msg.data.from + "-31283192",
}
}))
})
return
case 'candidate':
let candidate = msg.data.candidate
if (!candidate) {
return console.log('failed to parse candidate')
}
that.pee?.addIceCandidate(candidate)
break;
case "answer":
that.pee?.setRemoteDescription(msg.data.description)
break;
case "bye":
that.pee?.close()
that.close()
break;
}
}
}
async createOffer() {
var url =
'http://rw.quwanya.cn:12217/api/turn?service=turn&username=flutter-webrtc';
fetch(url)
.then(response => response.json())
.then(data => {
const configuration = {
iceServers: [
{
urls: data.uris[0],
"username": data.username,
"credential": data.password
},
]
}
this.gets(configuration)
})
try {
} catch (error) {
console.log(error);
}
}
async gets(configuration) {
console.log(configuration);
const peerConnection = new RTCPeerConnection(configuration);
this.pee = peerConnection
// 获取远方流添加到页面播放
peerConnection.ontrack = event => {
const remoteVideo = document.querySelector('#remoteVideo') as HTMLVideoElement;
remoteVideo.autoplay = true
remoteVideo.controls = true
remoteVideo.srcObject = event.streams[0];
console.log(event);
event.track.onmute = function () {
remoteVideo.play()
}
};
await this.getMedia(peerConnection)
peerConnection.onicecandidate = e => {
if (!e.candidate) {
return
}
this.ws?.send(JSON.stringify({ type: 'candidate', data: e }))
}
}
sendOffer(userId) {
let that = this;
that.userToId = userId;
that.video = document.getElementById('rtcVideo') as HTMLVideoElement;
if (that.pee?.connectionState === "closed") {
that.createOffer()
}
that.pee?.createOffer().then(function (offer) {
that.pee?.setLocalDescription(offer);
that.ws?.send(JSON.stringify({
type: "offer", "data": {
"to": userId,
"from": "31283192",
"description": offer,
"media": "video",
"session_id": userId + "-31283192",
}
}))
}).catch(function (error) {
// 错误处理
console.error(error);
});
}
addIceCandidate(candidate) {
this.pee?.addIceCandidate(candidate)
}
async getMedia(pee: RTCPeerConnection) {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
this.mediaStream = stream;
stream.getTracks().forEach(track => pee.addTrack(track, stream))
} catch (error) {
console.log(error);
}
}
calls(userId) {
this.sendOffer(userId)
if (this.video) {
this.video.srcObject = this.mediaStream;
this.video.autoplay = true;
}
}
close() {
this.video?.pause();
this.pee?.close();
this.ws?.send(JSON.stringify({
"type": "bye", "data": {
"session_id": this.userToId + "31283192",
"to": this.userToId
}
}
));
(this.mediaStream as MediaStream)?.getTracks().forEach(track => track.stop());
this.ws?.close()
}
}
export const webRTC = new WebRtc()