176 lines
5.6 KiB
TypeScript
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() |