import Config from "./config"; import SocketService from "./socket"; 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.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 = 'https://rw.quwanya.cn/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) }) } // 设置远程offer setRemoteDes(answer) { this.pee?.setRemoteDescription(answer) } addCandidate(candidate) { if (!candidate) { return console.log('failed to parse candidate') } this.pee?.addIceCandidate(candidate) } async gets(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": "admin", "description": offer, "media": "video", "session_id": userId + "-admin", } })) }).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("admin123") if (this.video) { this.video.srcObject = this.mediaStream; this.video.autoplay = true; } } // 发送本地offer setIceOffer(offer, toid) { this.pee?.setRemoteDescription(offer) this.pee?.createAnswer().then(answer => { this.pee?.setLocalDescription(answer) SocketService.getInstance().send({ type: 'answer', data: { 'to': toid, 'from': "admin", 'description': { 'sdp': answer.sdp, 'type': answer.type }, 'session_id': toid + "-admin", } }) }) } close() { this.video?.pause(); this.pee?.close(); this.ws?.send(JSON.stringify({ "type": "bye", "data": { "session_id": this.userToId + "admin", "to": this.userToId } } )); (this.mediaStream as MediaStream)?.getTracks().forEach(track => track.stop()); this.ws?.close() } } export const webRTC = new WebRtc()