|
|
@@ -5,70 +5,26 @@ import { useNetworkStore } from '@/store/network';
|
|
|
|
|
|
import { WsMsgTypeEnum } from './webSocket';
|
|
|
|
|
|
-export const frontendErrorCode = {
|
|
|
- rtcStatusErr: {
|
|
|
- // rtcStatus没有100%
|
|
|
- code: 1001,
|
|
|
- msg: '连接错误,是否尝试刷新页面(不影响云手机内应用运行)',
|
|
|
- refresh: true,
|
|
|
- },
|
|
|
- streamStop: {
|
|
|
- // 视频流卡主
|
|
|
- code: 1002,
|
|
|
- msg: '网络似乎不稳定,建议更换网络或刷新页面(不影响云手机内应用运行)',
|
|
|
- refresh: true,
|
|
|
- },
|
|
|
- blackScreen: {
|
|
|
- // 视频流黑屏
|
|
|
- code: 1003,
|
|
|
- msg: '当前浏览器似乎不兼容,建议使用Google Chrome浏览器',
|
|
|
- refresh: false,
|
|
|
- },
|
|
|
- connectionStateFailed: {
|
|
|
- code: 1004,
|
|
|
- msg: '连接错误,是否尝试刷新页面(不影响云手机内应用运行)',
|
|
|
- refresh: true,
|
|
|
- },
|
|
|
- iceConnectionStateDisconnected: {
|
|
|
- code: 1005,
|
|
|
- msg: '连接错误,是否尝试刷新页面(不影响云手机内应用运行)',
|
|
|
- refresh: true,
|
|
|
- },
|
|
|
- getStatsErr: {
|
|
|
- code: 1006,
|
|
|
- msg: '连接错误,是否尝试刷新页面(不影响云手机内应用运行)',
|
|
|
- refresh: true,
|
|
|
- },
|
|
|
- connectLongTime: {
|
|
|
- // 5秒内没有收到loadedmetadata回调
|
|
|
- code: 1007,
|
|
|
- msg: '等待太久,是否刷新页面重试?',
|
|
|
- refresh: true,
|
|
|
- },
|
|
|
-};
|
|
|
-
|
|
|
export class WebRTCClass {
|
|
|
roomId = '-1';
|
|
|
- videoEl;
|
|
|
- peerConnection: RTCPeerConnection | null = null;
|
|
|
- dataChannel: RTCDataChannel | null = null;
|
|
|
|
|
|
- sender?: RTCRtpTransceiver;
|
|
|
+ videoEl: HTMLVideoElement;
|
|
|
|
|
|
- getStatsSetIntervalDelay = 1000;
|
|
|
- getStatsSetIntervalTimer;
|
|
|
-
|
|
|
- // getStatsSetIntervalDelay是1秒的话,forceINumsMax是3,就代表一直卡了3秒。
|
|
|
- forceINums = 0; // 发送forceI次数
|
|
|
- forceINumsMax = 3; // 最多发送几次forceI
|
|
|
+ peerConnection: RTCPeerConnection | null = null;
|
|
|
|
|
|
- preFramesDecoded = -1; // 上一帧
|
|
|
+ sender?: RTCRtpTransceiver;
|
|
|
|
|
|
- maxBitrate: number; // 当前码率
|
|
|
- resolutionRatio: number; // 当前分辨率
|
|
|
+ /** 最大码率 */
|
|
|
+ maxBitrate = -1;
|
|
|
+ /** 最大帧率 */
|
|
|
+ maxFramerate = -1;
|
|
|
+ /** 分辨率 */
|
|
|
+ resolutionRatio = -1;
|
|
|
|
|
|
localStream?: MediaStream;
|
|
|
|
|
|
+ isSRS: boolean;
|
|
|
+
|
|
|
browser: {
|
|
|
device: string;
|
|
|
language: string;
|
|
|
@@ -82,39 +38,35 @@ export class WebRTCClass {
|
|
|
version: string;
|
|
|
};
|
|
|
|
|
|
- rtcStatus = {
|
|
|
- joined: false, // true代表成功,false代表失败
|
|
|
- icecandidate: false, // true代表成功,false代表失败
|
|
|
- createOffer: false, // true代表成功,false代表失败
|
|
|
- setLocalDescription: false, // true代表成功,false代表失败
|
|
|
- answer: false, // true代表成功,false代表失败
|
|
|
- setRemoteDescription: false, // true代表成功,false代表失败
|
|
|
- addStream: false, // true代表成功,false代表失败
|
|
|
- loadstart: false, // true代表成功,false代表失败
|
|
|
- loadedmetadata: false, // true代表成功,false代表失败
|
|
|
- };
|
|
|
-
|
|
|
- localDescription: any;
|
|
|
-
|
|
|
constructor({
|
|
|
roomId,
|
|
|
videoEl,
|
|
|
maxBitrate,
|
|
|
+ maxFramerate,
|
|
|
resolutionRatio,
|
|
|
+ isSRS,
|
|
|
}: {
|
|
|
roomId: string;
|
|
|
videoEl: HTMLVideoElement;
|
|
|
maxBitrate?: number;
|
|
|
+ maxFramerate?: number;
|
|
|
resolutionRatio?: number;
|
|
|
+ isSRS: boolean;
|
|
|
}) {
|
|
|
this.roomId = roomId;
|
|
|
this.videoEl = videoEl;
|
|
|
- this.maxBitrate = maxBitrate || 1000;
|
|
|
- this.resolutionRatio = resolutionRatio || 1080;
|
|
|
+ if (maxBitrate) {
|
|
|
+ this.maxBitrate = maxBitrate;
|
|
|
+ }
|
|
|
+ if (resolutionRatio) {
|
|
|
+ this.resolutionRatio = resolutionRatio;
|
|
|
+ }
|
|
|
+ if (maxFramerate) {
|
|
|
+ this.maxFramerate = maxFramerate;
|
|
|
+ }
|
|
|
+ this.isSRS = isSRS;
|
|
|
this.browser = browserTool();
|
|
|
this.createPeerConnection();
|
|
|
- this.update();
|
|
|
- // this.handleWebRtcError();
|
|
|
}
|
|
|
|
|
|
prettierLog = (msg: string, type?: 'log' | 'warn' | 'error', ...args) => {
|
|
|
@@ -141,6 +93,7 @@ export class WebRTCClass {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ /** 设置分辨率 */
|
|
|
setResolutionRatio = (height: number) => {
|
|
|
console.log('开始设置分辨率', height);
|
|
|
return new Promise((resolve) => {
|
|
|
@@ -152,6 +105,7 @@ export class WebRTCClass {
|
|
|
})
|
|
|
.then(() => {
|
|
|
console.log('设置分辨率成功');
|
|
|
+ this.resolutionRatio = height;
|
|
|
resolve(1);
|
|
|
})
|
|
|
.catch((error) => {
|
|
|
@@ -163,22 +117,25 @@ export class WebRTCClass {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
+ /** 设置最大码率 */
|
|
|
setMaxBitrate = (maxBitrate: number) => {
|
|
|
- console.log('开始设置码率', maxBitrate);
|
|
|
+ console.log('开始设置最大码率', maxBitrate);
|
|
|
return new Promise<number>((resolve) => {
|
|
|
this.peerConnection?.getSenders().forEach((sender) => {
|
|
|
if (sender.track?.kind === 'video') {
|
|
|
const parameters = { ...sender.getParameters() };
|
|
|
if (parameters.encodings[0]) {
|
|
|
- parameters.encodings[0].maxBitrate = 1000 * maxBitrate;
|
|
|
+ const val = 1000 * maxBitrate;
|
|
|
+ parameters.encodings[0].maxBitrate = val;
|
|
|
sender
|
|
|
.setParameters(parameters)
|
|
|
.then(() => {
|
|
|
- console.log('设置码率成功');
|
|
|
+ console.log('设置最大码率成功');
|
|
|
+ this.maxBitrate = val;
|
|
|
resolve(1);
|
|
|
})
|
|
|
.catch((error) => {
|
|
|
- console.error('设置码率失败', error);
|
|
|
+ console.error('设置最大码率失败', error);
|
|
|
resolve(0);
|
|
|
});
|
|
|
}
|
|
|
@@ -187,183 +144,30 @@ export class WebRTCClass {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
- handleWebRtcError = () => {
|
|
|
- this.getStatsSetIntervalTimer = setInterval(() => {
|
|
|
- this.peerConnection
|
|
|
- ?.getStats()
|
|
|
- .then((res) => {
|
|
|
- let isBlack = false;
|
|
|
- let currFramesDecoded = -1;
|
|
|
- res.forEach((report: RTCInboundRtpStreamStats) => {
|
|
|
- // 不能结构report的值,不然如果卡主之后,report的值就一直都是
|
|
|
- // const { type, kind, framesDecoded } = report;
|
|
|
- const data = {
|
|
|
- type: report.type,
|
|
|
- kind: report.kind,
|
|
|
- framesDecoded: report.framesDecoded,
|
|
|
- decoderImplementation: report.decoderImplementation,
|
|
|
- isChrome: false,
|
|
|
- isSafari: false,
|
|
|
- other: '',
|
|
|
- };
|
|
|
- if (this.browser.browser === 'safari') {
|
|
|
- data.isSafari = true;
|
|
|
- } else if (this.browser.browser === 'chrome') {
|
|
|
- data.isChrome = true;
|
|
|
- } else {
|
|
|
- data.other = this.browser.browser;
|
|
|
- }
|
|
|
- const isStopFlag = this.getCurrentFramesDecoded(data);
|
|
|
- const isBlackFlag = this.isBlackScreen(data);
|
|
|
- if (isStopFlag !== false) {
|
|
|
- currFramesDecoded = isStopFlag;
|
|
|
- }
|
|
|
- if (isBlackFlag !== false) {
|
|
|
- isBlack = isBlackFlag;
|
|
|
- }
|
|
|
- });
|
|
|
- /** 处理视频流卡主 */
|
|
|
- const handleStreamStop = () => {
|
|
|
- // console.error(
|
|
|
- // `上一帧:${this.preFramesDecoded},当前帧:${currFramesDecoded},forceINums:${this.forceINums}`
|
|
|
- // );
|
|
|
- if (this.preFramesDecoded === currFramesDecoded) {
|
|
|
- if (this.forceINums >= this.forceINumsMax) {
|
|
|
- this.prettierLog('超过forceI次数,提示更换网络', 'warn');
|
|
|
- this.forceINums = 0;
|
|
|
- } else {
|
|
|
- this.forceINums += 1;
|
|
|
- this.prettierLog(
|
|
|
- `当前视频流卡主了,主动刷新云手机(${this.forceINums}/${this.forceINumsMax})`,
|
|
|
- 'warn'
|
|
|
- );
|
|
|
- }
|
|
|
- } else {
|
|
|
- this.forceINums = 0;
|
|
|
- // console.warn('视频流没有卡主');
|
|
|
- }
|
|
|
- this.preFramesDecoded = currFramesDecoded;
|
|
|
- };
|
|
|
- /** 处理黑屏 */
|
|
|
- const handleBlackScreen = () => {
|
|
|
- if (isBlack) {
|
|
|
- this.prettierLog('黑屏了', 'error');
|
|
|
- }
|
|
|
- // else {
|
|
|
- // console.warn('没有黑屏');
|
|
|
- // }
|
|
|
- };
|
|
|
- /** 处理rtcStatus */
|
|
|
- const handleRtcStatus = () => {
|
|
|
- const res = this.rtcStatusIsOk();
|
|
|
- const length = Object.keys(res).length;
|
|
|
- if (length) {
|
|
|
- this.prettierLog(
|
|
|
- `rtcStatus错误:${Object.keys(res).join()}`,
|
|
|
- 'error'
|
|
|
- );
|
|
|
- }
|
|
|
- // else {
|
|
|
- // console.warn('rtcStatus正常');
|
|
|
- // }
|
|
|
- };
|
|
|
- handleStreamStop();
|
|
|
- handleBlackScreen();
|
|
|
- handleRtcStatus();
|
|
|
- // if (!networkStore.errorCode.length) {
|
|
|
- // networkStore.setShowErrorModal(false);
|
|
|
- // }
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- console.error(new Date().toLocaleString(), 'getStatsErr', err);
|
|
|
- // networkStore.setErrorCode(frontendErrorCode.getStatsErr);
|
|
|
- // networkStore.setShowErrorModal(true);
|
|
|
- });
|
|
|
- }, this.getStatsSetIntervalDelay);
|
|
|
- };
|
|
|
-
|
|
|
- /** rtcStatus是否都是true了 */
|
|
|
- rtcStatusIsOk = () => {
|
|
|
- const res = {};
|
|
|
- const status = this.rtcStatus;
|
|
|
- Object.keys(status).forEach((key) => {
|
|
|
- if (!status[key]) {
|
|
|
- res[key] = false;
|
|
|
- }
|
|
|
+ /** 设置最大帧率 */
|
|
|
+ setMaxFramerate = (maxFramerate: number) => {
|
|
|
+ console.log('开始设置最大帧率', maxFramerate);
|
|
|
+ return new Promise<number>((resolve) => {
|
|
|
+ this.peerConnection?.getSenders().forEach((sender) => {
|
|
|
+ if (sender.track?.kind === 'video') {
|
|
|
+ const parameters = { ...sender.getParameters() };
|
|
|
+ if (parameters.encodings[0]) {
|
|
|
+ parameters.encodings[0].maxFramerate = maxFramerate;
|
|
|
+ sender
|
|
|
+ .setParameters(parameters)
|
|
|
+ .then(() => {
|
|
|
+ console.log('设置最大帧率成功');
|
|
|
+ this.maxFramerate = maxFramerate;
|
|
|
+ resolve(1);
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ console.error('设置最大帧率失败', error);
|
|
|
+ resolve(0);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
});
|
|
|
- return res;
|
|
|
- };
|
|
|
-
|
|
|
- /** 当前是否黑屏,true代表黑屏了,false代表没有黑屏 */
|
|
|
- isBlackScreen = ({
|
|
|
- type,
|
|
|
- kind,
|
|
|
- framesDecoded,
|
|
|
- decoderImplementation,
|
|
|
- isSafari = false,
|
|
|
- isChrome = false,
|
|
|
- }) => {
|
|
|
- // https://blog.csdn.net/weixin_44523653/article/details/127414387
|
|
|
- // console.warn(
|
|
|
- // // eslint-disable-next-line
|
|
|
- // `type:${type},kind:${kind},framesDecoded:${framesDecoded},decoderImplementation:${decoderImplementation}`
|
|
|
- // );
|
|
|
- if (isSafari) {
|
|
|
- if (
|
|
|
- type === 'inbound-rtp' &&
|
|
|
- kind === 'video' &&
|
|
|
- // framesDecoded等于0代表黑屏
|
|
|
- framesDecoded === 0
|
|
|
- ) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- } else if (isChrome) {
|
|
|
- if (
|
|
|
- (type === 'track' || type === 'inbound-rtp') &&
|
|
|
- kind === 'video' &&
|
|
|
- // framesDecoded等于0代表黑屏
|
|
|
- framesDecoded === 0
|
|
|
- ) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (
|
|
|
- (type === 'track' || type === 'inbound-rtp') &&
|
|
|
- kind === 'video' &&
|
|
|
- // framesDecoded等于0代表黑屏
|
|
|
- framesDecoded === 0
|
|
|
- ) {
|
|
|
- // 安卓的qq浏览器适用这个黑屏判断
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- };
|
|
|
-
|
|
|
- /** 获取当前帧 */
|
|
|
- getCurrentFramesDecoded = ({
|
|
|
- type,
|
|
|
- kind,
|
|
|
- framesDecoded = this.preFramesDecoded,
|
|
|
- isSafari = false,
|
|
|
- isChrome = false,
|
|
|
- }) => {
|
|
|
- if (isSafari) {
|
|
|
- if (type === 'inbound-rtp' && kind === 'video') {
|
|
|
- return framesDecoded;
|
|
|
- }
|
|
|
- } else if (isChrome) {
|
|
|
- if ((type === 'track' || type === 'inbound-rtp') && kind === 'video') {
|
|
|
- return framesDecoded;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if ((type === 'track' || type === 'inbound-rtp') && kind === 'video') {
|
|
|
- // 安卓的qq浏览器适用这个卡屏判断
|
|
|
- return framesDecoded;
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
};
|
|
|
|
|
|
// 创建offer
|
|
|
@@ -374,16 +178,7 @@ export class WebRTCClass {
|
|
|
const description = await this.peerConnection.createOffer({
|
|
|
iceRestart: true,
|
|
|
});
|
|
|
- // const description = await this.peerConnection.createOffer({
|
|
|
- // iceRestart: true,
|
|
|
- // offerToReceiveAudio: true,
|
|
|
- // offerToReceiveVideo: true,
|
|
|
- // });
|
|
|
- this.localDescription = description;
|
|
|
- this.rtcStatus.createOffer = true;
|
|
|
- this.update();
|
|
|
this.prettierLog('createOffer成功', 'warn');
|
|
|
- console.log('createOffer', description);
|
|
|
return description;
|
|
|
} catch (error) {
|
|
|
this.prettierLog('createOffer失败', 'error');
|
|
|
@@ -391,32 +186,13 @@ export class WebRTCClass {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- // 设置本地描述
|
|
|
- setLocalDescription = async (description) => {
|
|
|
- if (!this.peerConnection) return;
|
|
|
- this.prettierLog('setLocalDescription开始', 'warn');
|
|
|
- try {
|
|
|
- await this.peerConnection.setLocalDescription(description);
|
|
|
- this.rtcStatus.setLocalDescription = true;
|
|
|
- this.update();
|
|
|
- this.prettierLog('setLocalDescription成功', 'warn');
|
|
|
- console.log(description);
|
|
|
- } catch (error) {
|
|
|
- this.prettierLog('setLocalDescription失败', 'error');
|
|
|
- console.log('setLocalDescription', description);
|
|
|
- console.log(error);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
// 创建answer
|
|
|
createAnswer = async () => {
|
|
|
if (!this.peerConnection) return;
|
|
|
this.prettierLog('createAnswer开始', 'warn');
|
|
|
try {
|
|
|
const description = await this.peerConnection.createAnswer();
|
|
|
- this.update();
|
|
|
this.prettierLog('createAnswer成功', 'warn');
|
|
|
- console.log(description);
|
|
|
return description;
|
|
|
} catch (error) {
|
|
|
this.prettierLog('createAnswer失败', 'error');
|
|
|
@@ -424,71 +200,74 @@ export class WebRTCClass {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ // 设置本地描述
|
|
|
+ setLocalDescription = async (desc: RTCLocalSessionDescriptionInit) => {
|
|
|
+ if (!this.peerConnection) return;
|
|
|
+ this.prettierLog('setLocalDescription开始', 'warn');
|
|
|
+ try {
|
|
|
+ await this.peerConnection.setLocalDescription(desc);
|
|
|
+ this.prettierLog('setLocalDescription成功', 'warn');
|
|
|
+ } catch (error) {
|
|
|
+ this.prettierLog('setLocalDescription失败', 'error');
|
|
|
+ console.error('setLocalDescription', desc);
|
|
|
+ console.error(error);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
// 设置远端描述
|
|
|
- setRemoteDescription = async (description) => {
|
|
|
+ setRemoteDescription = async (desc: RTCSessionDescriptionInit) => {
|
|
|
if (!this.peerConnection) return;
|
|
|
this.prettierLog(`setRemoteDescription开始`, 'warn');
|
|
|
try {
|
|
|
- await this.peerConnection.setRemoteDescription(
|
|
|
- new RTCSessionDescription(description)
|
|
|
- );
|
|
|
- this.rtcStatus.setRemoteDescription = true;
|
|
|
- this.update();
|
|
|
+ await this.peerConnection.setRemoteDescription(desc);
|
|
|
this.prettierLog('setRemoteDescription成功', 'warn');
|
|
|
- console.log(description);
|
|
|
} catch (error) {
|
|
|
this.prettierLog('setRemoteDescription失败', 'error');
|
|
|
- console.log('setRemoteDescription', description);
|
|
|
- console.log(error);
|
|
|
+ console.error('setRemoteDescription', desc);
|
|
|
+ console.error(error);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
addStream = (stream) => {
|
|
|
if (!this.peerConnection) return;
|
|
|
- this.rtcStatus.addStream = true;
|
|
|
- this.update();
|
|
|
console.log('开始addStream', this.videoEl, stream, this.roomId);
|
|
|
this.videoEl.srcObject = stream;
|
|
|
this.prettierLog('addStream成功', 'warn');
|
|
|
};
|
|
|
|
|
|
- handleStream = () => {
|
|
|
+ handleStreamEvent = () => {
|
|
|
+ if (!this.peerConnection) return;
|
|
|
console.warn(`${this.roomId},开始监听pc的addstream`);
|
|
|
- this.peerConnection?.addEventListener('addstream', (event: any) => {
|
|
|
+ this.peerConnection.addEventListener('addstream', (event: any) => {
|
|
|
console.warn(`${this.roomId},pc收到addstream事件`, event, event.stream);
|
|
|
this.addStream(event.stream);
|
|
|
});
|
|
|
|
|
|
console.warn(`${this.roomId},开始监听pc的ontrack`);
|
|
|
- this.peerConnection?.addEventListener('ontrack', (event: any) => {
|
|
|
+ this.peerConnection.addEventListener('ontrack', (event: any) => {
|
|
|
console.warn(`${this.roomId},pc收到ontrack事件`, event);
|
|
|
this.addStream(event.streams[0]);
|
|
|
});
|
|
|
|
|
|
console.warn(`${this.roomId},开始监听pc的addtrack`);
|
|
|
- this.peerConnection?.addEventListener('addtrack', (event: any) => {
|
|
|
+ this.peerConnection.addEventListener('addtrack', (event: any) => {
|
|
|
console.warn(`${this.roomId},pc收到addtrack事件`, event);
|
|
|
});
|
|
|
|
|
|
console.warn(`${this.roomId},开始监听pc的track`);
|
|
|
- this.peerConnection?.addEventListener('track', (event: any) => {
|
|
|
+ this.peerConnection.addEventListener('track', (event: any) => {
|
|
|
console.warn(`${this.roomId},pc收到track事件`, event);
|
|
|
this.addStream(event.streams[0]);
|
|
|
});
|
|
|
};
|
|
|
|
|
|
- // 创建连接
|
|
|
- startConnect = () => {
|
|
|
+ handleConnectionEvent = () => {
|
|
|
if (!this.peerConnection) return;
|
|
|
- this.handleStream();
|
|
|
console.warn(`${this.roomId},开始监听pc的icecandidate`);
|
|
|
this.peerConnection.addEventListener('icecandidate', (event) => {
|
|
|
this.prettierLog('pc收到icecandidate', 'warn');
|
|
|
- this.rtcStatus.icecandidate = true;
|
|
|
- this.update();
|
|
|
if (event.candidate) {
|
|
|
const networkStore = useNetworkStore();
|
|
|
- this.update();
|
|
|
console.log('准备发送candidate', event.candidate.candidate);
|
|
|
const roomId = this.roomId.split('___')[0];
|
|
|
const receiver = this.roomId.split('___')[1];
|
|
|
@@ -586,31 +365,23 @@ export class WebRTCClass {
|
|
|
return;
|
|
|
}
|
|
|
if (!this.peerConnection) {
|
|
|
+ const iceServers = this.isSRS
|
|
|
+ ? []
|
|
|
+ : [
|
|
|
+ // {
|
|
|
+ // urls: 'stun:stun.l.google.com:19302',
|
|
|
+ // },
|
|
|
+ {
|
|
|
+ urls: 'turn:hsslive.cn:3478',
|
|
|
+ username: 'hss',
|
|
|
+ credential: '123456',
|
|
|
+ },
|
|
|
+ ];
|
|
|
this.peerConnection = new RTCPeerConnection({
|
|
|
- iceServers: [
|
|
|
- // {
|
|
|
- // urls: 'stun:stun.l.google.com:19302',
|
|
|
- // },
|
|
|
- {
|
|
|
- urls: 'turn:hsslive.cn:3478',
|
|
|
- username: 'hss',
|
|
|
- credential: '123456',
|
|
|
- },
|
|
|
- ],
|
|
|
+ iceServers,
|
|
|
});
|
|
|
- // this.dataChannel =
|
|
|
- // this.peerConnection.createDataChannel('MessageChannel');
|
|
|
-
|
|
|
- // this.dataChannel.onopen = (event) => {
|
|
|
- // console.warn('dataChannel---onopen', event);
|
|
|
- // };
|
|
|
- // this.dataChannel.onerror = (event) => {
|
|
|
- // console.warn('dataChannel---onerror', event);
|
|
|
- // };
|
|
|
- // this.dataChannel.onmessage = (event) => {
|
|
|
- // console.log('dataChannel---onmessage', event);
|
|
|
- // };
|
|
|
- this.startConnect();
|
|
|
+ this.handleStreamEvent();
|
|
|
+ this.handleConnectionEvent();
|
|
|
this.update();
|
|
|
}
|
|
|
};
|
|
|
@@ -622,10 +393,7 @@ export class WebRTCClass {
|
|
|
this.peerConnection?.removeTrack(this.sender?.sender);
|
|
|
}
|
|
|
this.peerConnection?.close();
|
|
|
- this.dataChannel?.close();
|
|
|
this.peerConnection = null;
|
|
|
- this.dataChannel = null;
|
|
|
- this.update();
|
|
|
};
|
|
|
|
|
|
// 更新store
|