client.js
6.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
var pc = null;
function negotiate() {
pc.addTransceiver('video', { direction: 'recvonly' });
pc.addTransceiver('audio', { direction: 'recvonly' });
return pc.createOffer().then((offer) => {
return pc.setLocalDescription(offer);
}).then(() => {
// wait for ICE gathering to complete with timeout
return new Promise((resolve) => {
if (pc.iceGatheringState === 'complete') {
resolve();
} else {
let resolved = false;
// ICE收集超时机制:3秒后强制继续
const timeout = setTimeout(() => {
if (!resolved) {
console.warn('ICE gathering timeout after 3 seconds, proceeding with available candidates');
resolved = true;
resolve();
}
}, 3000);
const checkState = () => {
if (pc.iceGatheringState === 'complete' && !resolved) {
clearTimeout(timeout);
resolved = true;
pc.removeEventListener('icegatheringstatechange', checkState);
console.log('ICE gathering completed successfully');
resolve();
}
};
pc.addEventListener('icegatheringstatechange', checkState);
}
});
}).then(() => {
var offer = pc.localDescription;
return fetch('/offer', {
body: JSON.stringify({
sdp: offer.sdp,
type: offer.type,
}),
headers: {
'Content-Type': 'application/json'
},
method: 'POST'
});
}).then((response) => {
console.log('收到/offer接口响应,状态:', response.status);
if (!response.ok) {
throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
}
return response.json();
}).then((answer) => {
console.log('解析/offer接口响应:', answer);
if(answer.code == -1){
throw new Error(answer.msg);
}
if (!answer.sessionid) {
throw new Error('服务器响应中缺少sessionid字段');
}
document.getElementById('sessionid').value = answer.sessionid;
console.log('SessionID已设置:', answer.sessionid);
console.log('sessionid元素当前值:', document.getElementById('sessionid').value);
// 保存sessionId到本地存储(如果saveSessionId函数存在)
saveSessionId(answer.sessionid);
// 触发WebSocket连接(如果connectWebSocket函数存在)
if (typeof connectWebSocket === 'function') {
console.log('触发WebSocket连接...');
connectWebSocket();
}
return pc.setRemoteDescription(answer);
}).catch((e) => {
console.error('WebRTC连接失败:', e);
console.error('错误详情:', e.message);
// 设置sessionid为0,表示连接失败
document.getElementById('sessionid').value = '0';
// 显示更详细的错误信息
const errorMsg = `WebRTC连接失败: ${e.message}`;
alert(errorMsg);
// 如果存在状态显示元素,更新状态
const statusElement = document.getElementById('overall-status');
if (statusElement) {
statusElement.textContent = `连接失败: ${e.message}`;
}
});
}
function start() {
// 更新连接状态
if (typeof updateConnectionStatus === 'function') {
updateConnectionStatus('connecting', '正在建立WebRTC连接...');
}
var config = {
sdpSemantics: 'unified-plan'
};
if (document.getElementById('use-stun').checked) {
// 优化STUN服务器配置:使用多个快速STUN服务器
config.iceServers = [
{ urls: ['stun:stun.l.google.com:19302'] },
{ urls: ['stun:stun1.l.google.com:19302'] },
{ urls: ['stun:stun2.l.google.com:19302'] }
];
// ICE传输策略和候选者池大小优化
config.iceTransportPolicy = 'all';
config.iceCandidatePoolSize = 10;
}
pc = new RTCPeerConnection(config);
// 添加ICE连接状态监控
pc.addEventListener('iceconnectionstatechange', () => {
console.log('ICE connection state:', pc.iceConnectionState);
const statusElement = document.getElementById('connection-status');
if (statusElement) {
statusElement.textContent = `ICE状态: ${pc.iceConnectionState}`;
}
});
// 添加ICE候选者收集状态监控
pc.addEventListener('icegatheringstatechange', () => {
console.log('ICE gathering state:', pc.iceGatheringState);
const statusElement = document.getElementById('gathering-status');
if (statusElement) {
statusElement.textContent = `ICE收集: ${pc.iceGatheringState}`;
}
});
// 添加连接状态监控
pc.addEventListener('connectionstatechange', () => {
console.log('Connection state:', pc.connectionState);
const statusElement = document.getElementById('overall-status');
if (statusElement) {
statusElement.textContent = `连接状态: ${pc.connectionState}`;
}
});
// connect audio / video
pc.addEventListener('track', (evt) => {
if (evt.track.kind == 'video') {
document.getElementById('video').srcObject = evt.streams[0];
} else {
document.getElementById('audio').srcObject = evt.streams[0];
}
});
document.getElementById('start').style.display = 'none';
negotiate();
document.getElementById('stop').style.display = 'inline-block';
}
function stop() {
document.getElementById('stop').style.display = 'none';
// close peer connection
setTimeout(() => {
pc.close();
}, 500);
}
window.onunload = function(event) {
// 在这里执行你想要的操作
setTimeout(() => {
pc.close();
}, 500);
};
window.onbeforeunload = function (e) {
setTimeout(() => {
pc.close();
}, 500);
e = e || window.event
// 兼容IE8和Firefox 4之前的版本
if (e) {
e.returnValue = '关闭提示'
}
// Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
return '关闭提示'
}