Aleksmorshen commited on
Commit
da02667
·
verified ·
1 Parent(s): 7472d69

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -66
app.py CHANGED
@@ -172,12 +172,14 @@ def room(token):
172
 
173
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.1/socket.io.js"></script>
174
  <script>
175
- // Используем относительный путь для подключения сокетов
176
  const socket = io();
177
  const token = '{{ token }}';
178
  const username = '{{ session['username'] }}';
179
  let localStream;
180
  const peers = {};
 
 
 
181
 
182
  // Получение локального видео/аудио потока
183
  navigator.mediaDevices.getUserMedia({ video: true, audio: true })
@@ -196,10 +198,8 @@ def room(token):
196
 
197
  const video = document.createElement('video');
198
  video.srcObject = stream;
199
- // Важно для мобильных устройств:
200
  video.setAttribute('playsinline', '');
201
  video.setAttribute('autoplay', '');
202
- // По умолчанию autoplay может блокироваться, поэтому вызываем play() явно
203
  video.addEventListener('loadedmetadata', () => {
204
  video.play().catch(e => console.error('Autoplay error:', e));
205
  });
@@ -209,24 +209,28 @@ def room(token):
209
  document.getElementById('video-grid').appendChild(video);
210
  }
211
 
212
- // Создание соединения с другим пользователем
213
- function connectToUser(user) {
214
- if (user === username || peers[user]) return;
215
- console.log('Инициирую соединение с', user);
216
- const peer = new RTCPeerConnection({
217
- iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
218
- });
219
- peers[user] = peer;
220
 
221
- localStream.getTracks().forEach(track => peer.addTrack(track, localStream));
222
 
223
- peer.ontrack = event => {
 
 
 
 
 
 
 
 
 
 
 
 
224
  console.log('Получен поток от', user);
225
  addVideoStream(event.streams[0], user);
226
  };
227
 
228
- peer.onicecandidate = event => {
229
  if (event.candidate) {
 
230
  socket.emit('signal', {
231
  token: token,
232
  from: username,
@@ -235,82 +239,94 @@ def room(token):
235
  });
236
  }
237
  };
238
-
239
- peer.onnegotiationneeded = () => {
240
- peer.createOffer()
241
- .then(offer => peer.setLocalDescription(offer))
242
- .then(() => {
243
- socket.emit('signal', {
244
- token: token,
245
- from: username,
246
- to: user,
247
- signal: peer.localDescription
248
- });
249
- })
250
- .catch(err => console.error('Ошибка создания предложения:', err));
251
- };
252
  }
253
 
254
- // Обработка входящих сигналов
255
  socket.on('signal', data => {
256
- // Если сигнал пришёл от нас же, игнорируем
257
  if (data.from === username) return;
258
  console.log('Получен сигнал от', data.from, ':', data.signal.type);
259
 
260
- let peer = peers[data.from];
261
- if (!peer) {
262
- peer = new RTCPeerConnection({
263
- iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
264
- });
265
- peers[data.from] = peer;
266
-
267
- localStream.getTracks().forEach(track => peer.addTrack(track, localStream));
268
- peer.ontrack = event => addVideoStream(event.streams[0], data.from);
269
- peer.onicecandidate = event => {
270
- if (event.candidate) {
 
 
271
  socket.emit('signal', {
272
  token: token,
273
  from: username,
274
  to: data.from,
275
- signal: { type: 'candidate', candidate: event.candidate }
276
  });
277
- }
278
- };
279
- }
280
-
281
- if (data.signal.type === 'offer') {
282
- peer.setRemoteDescription(new RTCSessionDescription(data.signal))
283
- .then(() => peer.createAnswer())
284
- .then(answer => peer.setLocalDescription(answer))
285
- .then(() => socket.emit('signal', {
286
- token: token,
287
- from: username,
288
- to: data.from,
289
- signal: peer.localDescription
290
- }))
291
  .catch(err => console.error('Ошибка обработки предложения:', err));
 
292
  } else if (data.signal.type === 'answer') {
293
- peer.setRemoteDescription(new RTCSessionDescription(data.signal))
294
- .catch(err => console.error('Ошибка установки ответа:', err));
 
 
 
 
 
 
 
 
 
 
295
  } else if (data.signal.type === 'candidate') {
296
- peer.addIceCandidate(new RTCIceCandidate(data.signal.candidate))
297
- .catch(err => console.error('Ошибка добавления кандидата:', err));
 
 
 
 
 
 
 
298
  }
299
  });
300
-
301
  socket.on('user_joined', data => {
302
  console.log('Пользователь', data.username, 'присоединился');
303
  document.getElementById('users').innerText = 'Пользователи: ' + data.users.join(', ');
 
304
  if (data.username !== username) {
305
- connectToUser(data.username);
 
 
 
 
 
 
 
 
 
 
 
 
306
  }
307
  });
308
 
 
309
  socket.on('user_left', data => {
310
  console.log('Пользователь', data.username, 'покинул комнату');
311
  document.getElementById('users').innerText = 'Пользователи: ' + data.users.join(', ');
312
  if (peers[data.username]) {
313
- peers[data.username].close();
314
  delete peers[data.username];
315
  const video = document.querySelector(`video[data-user="${data.username}"]`);
316
  if (video) video.remove();
@@ -320,15 +336,16 @@ def room(token):
320
  socket.on('init_users', data => {
321
  console.log('Инициализация пользователей:', data.users);
322
  data.users.forEach(user => {
323
- if (user !== username) connectToUser(user);
 
 
324
  });
325
  });
326
-
327
  function leaveRoom() {
328
  socket.emit('leave', { token: token, username: username });
329
  localStream.getTracks().forEach(track => track.stop());
330
  for (let user in peers) {
331
- peers[user].close();
332
  }
333
  window.location.href = '/dashboard';
334
  }
 
172
 
173
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.1/socket.io.js"></script>
174
  <script>
 
175
  const socket = io();
176
  const token = '{{ token }}';
177
  const username = '{{ session['username'] }}';
178
  let localStream;
179
  const peers = {};
180
+ const iceConfig = {
181
+ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
182
+ };
183
 
184
  // Получение локального видео/аудио потока
185
  navigator.mediaDevices.getUserMedia({ video: true, audio: true })
 
198
 
199
  const video = document.createElement('video');
200
  video.srcObject = stream;
 
201
  video.setAttribute('playsinline', '');
202
  video.setAttribute('autoplay', '');
 
203
  video.addEventListener('loadedmetadata', () => {
204
  video.play().catch(e => console.error('Autoplay error:', e));
205
  });
 
209
  document.getElementById('video-grid').appendChild(video);
210
  }
211
 
 
 
 
 
 
 
 
 
212
 
 
213
 
214
+ // Создание соединения с другим пользователем (используется и при инициации, и при ответе)
215
+ function createPeerConnection(user) {
216
+ if (peers[user]) {
217
+ return peers[user].peerConnection; // Return existing connection
218
+ }
219
+
220
+ console.log('Создание RTCPeerConnection для', user);
221
+ const peerConnection = new RTCPeerConnection(iceConfig);
222
+ peers[user] = { peerConnection: peerConnection, iceCandidates: [] };
223
+
224
+ localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream));
225
+
226
+ peerConnection.ontrack = event => {
227
  console.log('Получен поток от', user);
228
  addVideoStream(event.streams[0], user);
229
  };
230
 
231
+ peerConnection.onicecandidate = event => {
232
  if (event.candidate) {
233
+ console.log('Отправка ICE-кандидата для', user);
234
  socket.emit('signal', {
235
  token: token,
236
  from: username,
 
239
  });
240
  }
241
  };
242
+ return peerConnection;
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  }
244
 
245
+ // Обработка входящих сигналов
246
  socket.on('signal', data => {
 
247
  if (data.from === username) return;
248
  console.log('Получен сигнал от', data.from, ':', data.signal.type);
249
 
250
+ let peerEntry = peers[data.from];
251
+ if (!peerEntry) {
252
+ createPeerConnection(data.from);
253
+ peerEntry = peers[data.from];
254
+ }
255
+ let peerConnection = peerEntry.peerConnection;
256
+
257
+ if (data.signal.type === 'offer') {
258
+ console.log('Обработка предложения от', data.from);
259
+ peerConnection.setRemoteDescription(new RTCSessionDescription(data.signal))
260
+ .then(() => peerConnection.createAnswer())
261
+ .then(answer => peerConnection.setLocalDescription(answer))
262
+ .then(() => {
263
  socket.emit('signal', {
264
  token: token,
265
  from: username,
266
  to: data.from,
267
+ signal: peerConnection.localDescription
268
  });
269
+ //Добавление ICE-кандидатов из буффера
270
+ while (peerEntry.iceCandidates.length > 0) {
271
+ const candidate = peerEntry.iceCandidates.shift();
272
+ peerConnection.addIceCandidate(new RTCIceCandidate(candidate))
273
+ .catch(err => console.error("Error adding ice candidate from buffer", err));
274
+ }
275
+ })
 
 
 
 
 
 
 
276
  .catch(err => console.error('Ошибка обработки предложения:', err));
277
+
278
  } else if (data.signal.type === 'answer') {
279
+ console.log('Обработка ответа от', data.from);
280
+ peerConnection.setRemoteDescription(new RTCSessionDescription(data.signal))
281
+ .then(() => {
282
+ //Добавление ICE-кандидатов из буффера
283
+ while (peerEntry.iceCandidates.length > 0) {
284
+ const candidate = peerEntry.iceCandidates.shift();
285
+ peerConnection.addIceCandidate(new RTCIceCandidate(candidate))
286
+ .catch(err => console.error("Error adding ice candidate from buffer", err));
287
+ }
288
+ })
289
+ .catch(err => console.error('Ошибка установки ответа:', err));
290
+
291
  } else if (data.signal.type === 'candidate') {
292
+ console.log('Обработка ICE-кандидата от', data.from);
293
+ if (peerConnection.remoteDescription) {
294
+ peerConnection.addIceCandidate(new RTCIceCandidate(data.signal.candidate))
295
+ .catch(err => console.error('Ошибка добавления ICE-кандидата:', err));
296
+ } else {
297
+ // Если remote description еще не установлен, добавляем в буфер
298
+ peerEntry.iceCandidates.push(data.signal.candidate);
299
+ console.log("Ice candidate buffered for", data.from)
300
+ }
301
  }
302
  });
 
303
  socket.on('user_joined', data => {
304
  console.log('Пользователь', data.username, 'присоединился');
305
  document.getElementById('users').innerText = 'Пользователи: ' + data.users.join(', ');
306
+
307
  if (data.username !== username) {
308
+ const peerConnection = createPeerConnection(data.username);
309
+ // Создание предложения (offer), только если мы инициатор
310
+ peerConnection.createOffer()
311
+ .then(offer => peerConnection.setLocalDescription(offer))
312
+ .then(() => {
313
+ socket.emit('signal', {
314
+ token: token,
315
+ from: username,
316
+ to: data.username,
317
+ signal: peerConnection.localDescription
318
+ });
319
+ })
320
+ .catch(err => console.error('Ошибка создания п��едложения:', err));
321
  }
322
  });
323
 
324
+
325
  socket.on('user_left', data => {
326
  console.log('Пользователь', data.username, 'покинул комнату');
327
  document.getElementById('users').innerText = 'Пользователи: ' + data.users.join(', ');
328
  if (peers[data.username]) {
329
+ peers[data.username].peerConnection.close();
330
  delete peers[data.username];
331
  const video = document.querySelector(`video[data-user="${data.username}"]`);
332
  if (video) video.remove();
 
336
  socket.on('init_users', data => {
337
  console.log('Инициализация пользователей:', data.users);
338
  data.users.forEach(user => {
339
+ if (user !== username) {
340
+ createPeerConnection(user); // Создаем RTCPeerConnection для всех, *кроме себя*
341
+ }
342
  });
343
  });
 
344
  function leaveRoom() {
345
  socket.emit('leave', { token: token, username: username });
346
  localStream.getTracks().forEach(track => track.stop());
347
  for (let user in peers) {
348
+ peers[user].peerConnection.close();
349
  }
350
  window.location.href = '/dashboard';
351
  }