sip-connector 15.3.1 → 16.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +522 -98
  3. package/dist/@SipConnector-DcaeAFrM.cjs +1 -0
  4. package/dist/{@SipConnector-5Rac5oq2.js → @SipConnector-uiUlVCMv.js} +955 -395
  5. package/dist/CallManager/types.d.ts +2 -0
  6. package/dist/PresentationManager/@PresentationManager.d.ts +5 -3
  7. package/dist/SipConnector/@SipConnector.d.ts +14 -4
  8. package/dist/SipConnector/eventNames.d.ts +1 -1
  9. package/dist/SipConnectorFacade/SipConnectorFacade.d.ts +10 -21
  10. package/dist/VideoSendingBalancer/SenderBalancer.d.ts +3 -1
  11. package/dist/VideoSendingBalancer/TrackMonitor.d.ts +38 -0
  12. package/dist/VideoSendingBalancer/VideoSendingBalancer.d.ts +8 -9
  13. package/dist/VideoSendingBalancer/VideoSendingEventHandler.d.ts +4 -9
  14. package/dist/VideoSendingBalancer/__fixtures__/createMockTrack.d.ts +5 -0
  15. package/dist/VideoSendingBalancer/__fixtures__/index.d.ts +1 -0
  16. package/dist/VideoSendingBalancer/index.d.ts +1 -2
  17. package/dist/VideoSendingBalancer/types.d.ts +0 -1
  18. package/dist/VideoSendingBalancerManager/@VideoSendingBalancerManager.d.ts +47 -0
  19. package/dist/VideoSendingBalancerManager/eventNames.d.ts +20 -0
  20. package/dist/VideoSendingBalancerManager/index.d.ts +3 -0
  21. package/dist/doMock.cjs +1 -1
  22. package/dist/doMock.js +1 -1
  23. package/dist/index.cjs +1 -1
  24. package/dist/index.d.ts +1 -2
  25. package/dist/index.js +281 -748
  26. package/dist/logger.d.ts +0 -1
  27. package/dist/tools/setCodecPreferences.d.ts +5 -0
  28. package/dist/tools/setParametersToSender/index.d.ts +1 -0
  29. package/package.json +5 -5
  30. package/dist/@SipConnector-Bv3-Y4Rz.cjs +0 -1
  31. package/dist/tools/generateSimulcastEncodings.d.ts +0 -7
  32. package/dist/tools/resolveUpdateTransceiver.d.ts +0 -6
  33. package/dist/tools/scaleResolutionAndBitrate.d.ts +0 -10
  34. /package/dist/{PresentationManager → SipConnector}/constants.d.ts +0 -0
package/README.md CHANGED
@@ -3,203 +3,627 @@
3
3
  [![npm](https://img.shields.io/npm/v/sip-connector?style=flat-square)](https://www.npmjs.com/package/sip-connector)
4
4
  ![npm bundle size](https://img.shields.io/bundlephobia/minzip/sip-connector?style=flat-square)
5
5
 
6
- TypeScript SDK для подключения к Vinteo по WebRTC через SIP (на базе `@krivega/jssip`). Предоставляет высокий уровень API для:
6
+ ---
7
7
 
8
- - подключения/регистрации на SIP-сервере;
9
- - исходящих/входящих звонков;
10
- - управления презентацией (share screen/video);
11
- - отправки служебных сообщений (DTMF, каналы, синхронизация медиа-состояния);
12
- - подписки на события платформы.
13
- - сбора и подписки на WebRTC‑статистику (outbound/inbound RTP, битрейты и др.).
8
+ ## 📖 Описание
14
9
 
15
- ## Установка
10
+ **sip-connector** — это TypeScript SDK для интеграции WebRTC-приложений с платформой Vinteo через SIP-протокол. Библиотека построена на базе `@krivega/jssip` и предоставляет высокоуровневый API для создания полнофункциональных видеоконференций.
16
11
 
17
- ```sh
12
+ ### 🎯 Основные возможности
13
+
14
+ SDK предоставляет комплексное решение для:
15
+
16
+ | Категория | Возможности |
17
+ | ---------------------------- | ------------------------------------------------------------- |
18
+ | **SIP-подключения** | Регистрация на сервере (SIP REGISTER), управление сессиями |
19
+ | **WebRTC-коммуникации** | Исходящие/входящие звонки (SIP INVITE/200 OK), медиа-потоки |
20
+ | **Презентации** | Отправка второго потока (screen sharing, демонстрация экрана) |
21
+ | **Системные сообщения** | DTMF, SIP INFO, синхронизация медиа-состояния |
22
+ | **Событийная архитектура** | Подписка на события платформы в реальном времени |
23
+ | **Мониторинг** | WebRTC-статистика (RTCRtpStats, ICE candidate stats) |
24
+ | **Управление конференциями** | Перемещение участников между ролями (участник/зритель) |
25
+ | **Лицензирование** | Мониторинг использования лицензий и состояния презентаций |
26
+
27
+ ### 🏗️ Архитектура
28
+
29
+ SDK построен по принципу **слоистой архитектуры**:
30
+
31
+ - **SipConnector** — низкоуровневый слой с менеджерами (Connection, Call, Presentation, API)
32
+ - **SipConnectorFacade** — высокоуровневый фасад с готовыми сценариями
33
+ - **Специализированные менеджеры** — для статистики, участников, медиа-потоков
34
+
35
+ ---
36
+
37
+ ## 🚀 Установка
38
+
39
+ ### Команды установки
40
+
41
+ ```bash
42
+ # npm
18
43
  npm install sip-connector
19
- # или
44
+
45
+ # yarn
20
46
  yarn add sip-connector
47
+
48
+ # pnpm
49
+ pnpm add sip-connector
21
50
  ```
22
51
 
23
- Минимально требуется передать `JsSIP` из `@krivega/jssip` при создании `SipConnector`.
52
+ ### 📋 Системные требования
53
+
54
+ #### Обязательные зависимости
55
+
56
+ | Компонент | Требование | Описание |
57
+ | ------------------ | -------------------- | ------------------------------ |
58
+ | `@krivega/jssip` | peer dependency | Для SIP-функциональности |
59
+ | WebRTC API | Поддержка в браузере | Стандартные WebRTC возможности |
60
+ | JavaScript runtime | ES2017+ | Современный синтаксис |
61
+
62
+ #### Рекомендуемые зависимости
63
+
64
+ | Компонент | Версия | Назначение |
65
+ | ---------- | ------ | ------------------- |
66
+ | TypeScript | 4.5+ | Полная типизация |
67
+ | Node.js | 16+ | Сборка и разработка |
24
68
 
25
- ## Быстрый старт
69
+ ---
26
70
 
27
- ```ts
71
+ ## 🎯 Быстрый старт
72
+
73
+ ### Шаг 1: Инициализация
74
+
75
+ ```typescript
28
76
  import { UA, WebSocketInterface } from '@krivega/jssip';
29
77
  import { SipConnector, SipConnectorFacade, tools } from 'sip-connector';
30
78
 
31
- // 1) Инициализация низкоуровневого коннектора
32
- const sipConnector = new SipConnector({ JsSIP: { UA, WebSocketInterface } });
79
+ // Создание низкоуровневого коннектора
80
+ const sipConnector = new SipConnector({
81
+ JsSIP: { UA, WebSocketInterface },
82
+ });
33
83
 
34
- // 2) Фасад с готовыми сценариями и проксированием событий/методов
84
+ // Создание фасада с настройками кодеков
35
85
  const facade = new SipConnectorFacade(sipConnector, {
36
- // опционально: приоритезировать/исключить кодеки видео
86
+ // Приоритизация современных кодеков
37
87
  preferredMimeTypesVideoCodecs: ['video/AV1', 'video/VP9'],
38
88
  excludeMimeTypesVideoCodecs: ['video/H264'],
39
89
  });
90
+ ```
91
+
92
+ ### Шаг 2: Подключение к серверу
40
93
 
41
- // 3) Подключение к серверу
94
+ ```typescript
42
95
  await facade.connectToServer({
43
96
  userAgent: tools.getUserAgent({ appName: 'MyApp' }),
44
97
  sipWebSocketServerURL: 'wss://sip.example.com/ws',
45
98
  sipServerUrl: 'sip:example.com',
46
- name: '1001', // пользователь (SIP URI user)
99
+ name: '1001', // SIP URI user part
47
100
  password: 'secret',
48
- isRegisteredUser: true, // включить SIP REGISTER
101
+ isRegisteredUser: true, // Включить SIP REGISTER
49
102
  });
103
+ ```
104
+
105
+ ### Шаг 3: Исходящий звонок
50
106
 
51
- // 4) Исходящий звонок
52
- const localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
107
+ ```typescript
108
+ // Получение локального медиа-потока
109
+ const localStream = await navigator.mediaDevices.getUserMedia({
110
+ audio: true,
111
+ video: true,
112
+ });
113
+
114
+ // Инициация звонка
53
115
  const pc = await facade.callToServer({
54
116
  conference: '12345',
55
117
  mediaStream: localStream,
56
118
  setRemoteStreams: (streams) => {
57
- // отобразите удалённые потоки в плеере
58
- console.log('remote streams', streams);
119
+ // Обработка удаленных потоков
120
+ console.log('Получены удаленные потоки:', streams);
59
121
  },
60
122
  });
61
123
 
62
- // (опционально) Подписка на WebRTC‑статистику
124
+ // Подписка на WebRTC-статистику
63
125
  const unsubscribeStats = facade.onStats(({ outbound, inbound }) => {
64
- console.log('stats outbound', outbound);
65
- console.log('stats inbound', inbound);
126
+ console.log('Исходящая статистика:', outbound);
127
+ console.log('Входящая статистика:', inbound);
66
128
  });
129
+ ```
67
130
 
68
- // 5) Завершение
131
+ ### Шаг 4: Завершение работы
132
+
133
+ ```typescript
69
134
  await facade.disconnectFromServer();
70
135
  unsubscribeStats();
71
136
  ```
72
137
 
73
- ## Входящий звонок (пример)
138
+ ---
139
+
140
+ ## 📞 Входящие звонки
141
+
142
+ ### Обработка входящих вызовов
74
143
 
75
- ```ts
144
+ ```typescript
76
145
  // Подписка на входящие события
77
146
  sipConnector.on('incoming-call:incoming', () => {
78
- // ответить с локальным стримом
147
+ // Автоматический ответ с локальным потоком
79
148
  facade.answerToIncomingCall({
80
149
  mediaStream: localStream,
81
150
  setRemoteStreams: (streams) => {
82
- /* ... */
151
+ // Отображение удаленных потоков
152
+ displayRemoteStreams(streams);
83
153
  },
84
154
  });
85
155
  });
86
156
  ```
87
157
 
88
- ## Управление презентацией
158
+ ### Управление состоянием звонка
159
+
160
+ ```typescript
161
+ // Отслеживание жизненного цикла звонка
162
+ sipConnector.on('call:accepted', () => {
163
+ console.log('Звонок принят');
164
+ });
89
165
 
90
- ```ts
91
- // старт
92
- const displayStream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true });
166
+ sipConnector.on('call:ended', () => {
167
+ console.log('Звонок завершен');
168
+ });
169
+
170
+ sipConnector.on('call:failed', (error) => {
171
+ console.error('Ошибка звонка:', error);
172
+ });
173
+ ```
174
+
175
+ ---
176
+
177
+ ## 🖥️ Управление презентациями
178
+
179
+ ### Запуск презентации
180
+
181
+ ```typescript
182
+ // Получение потока экрана
183
+ const displayStream = await navigator.mediaDevices.getDisplayMedia({
184
+ video: true,
185
+ audio: true,
186
+ });
187
+
188
+ // Запуск презентации с настройками качества
93
189
  await facade.startPresentation({
94
190
  mediaStream: displayStream,
95
- isP2P: false,
96
- contentHint: 'detail',
191
+ isP2P: false, // MCU режим
192
+ contentHint: 'detail', // Оптимизация для детального контента
97
193
  simulcastEncodings: [
98
194
  { width: 1920, height: 1080, scalabilityMode: 'L3T3_KEY' },
99
195
  { width: 1280, height: 720 },
100
196
  ],
101
197
  });
198
+ ```
102
199
 
103
- // обновление (например, смена потока)
104
- await facade.updatePresentation({ mediaStream: displayStream, isP2P: false });
200
+ ### Обновление и остановка
201
+
202
+ ```typescript
203
+ // Обновление потока презентации
204
+ await facade.updatePresentation({
205
+ mediaStream: newDisplayStream,
206
+ isP2P: false,
207
+ });
105
208
 
106
- // стоп
209
+ // Остановка презентации
107
210
  await facade.stopShareSipConnector();
108
211
  ```
109
212
 
110
- ## События
213
+ ---
214
+
215
+ ## 👥 Управление участниками конференции
216
+
217
+ ### Отслеживание перемещений
218
+
219
+ ```typescript
220
+ // Подписка на перемещение в зрители
221
+ const unsubscribeMoveToSpectators = facade.onMoveToSpectators(() => {
222
+ console.log('Участник перемещен в зрители');
223
+ updateParticipantRole('spectator');
224
+ });
225
+
226
+ // Подписка на перемещение в участники
227
+ const unsubscribeMoveToParticipants = facade.onMoveToParticipants(() => {
228
+ console.log('Участник перемещен в участники');
229
+ updateParticipantRole('participant');
230
+ });
231
+
232
+ // Отписка при необходимости
233
+ unsubscribeMoveToSpectators();
234
+ unsubscribeMoveToParticipants();
235
+ ```
236
+
237
+ ### Административные функции
238
+
239
+ ```typescript
240
+ // Принудительная остановка презентации
241
+ facade.onMustStopPresentation(() => {
242
+ console.log('Администратор требует остановить презентацию');
243
+ facade.stopShareSipConnector();
244
+ });
245
+
246
+ // Мониторинг лицензий
247
+ facade.onUseLicense((license) => {
248
+ console.log('Используется лицензия:', license);
249
+ updateLicenseStatus(license);
250
+ });
251
+ ```
252
+
253
+ ---
254
+
255
+ ## 📊 Управление медиа-потоками
256
+
257
+ ### Работа с удаленными потоками
258
+
259
+ ```typescript
260
+ // Получение текущих удаленных потоков
261
+ const remoteStreams = facade.getRemoteStreams();
262
+ if (remoteStreams) {
263
+ console.log('Активные удаленные потоки:', remoteStreams.length);
264
+ remoteStreams.forEach((stream) => {
265
+ displayStream(stream);
266
+ });
267
+ }
268
+ ```
269
+
270
+ ### Обработка готовых потоков
271
+
272
+ ```typescript
273
+ // Обработка с debounce (рекомендуется для UI)
274
+ const handleReadyRemoteStreamsDebounced = facade.resolveHandleReadyRemoteStreamsDebounced({
275
+ onReadyRemoteStreams: (streams) => {
276
+ console.log('Готовые удаленные потоки:', streams);
277
+ updateStreamsDisplay(streams);
278
+ },
279
+ });
280
+
281
+ // Обработка без debounce (для критичных операций)
282
+ const handleReadyRemoteStreams = facade.resolveHandleReadyRemoteStreams({
283
+ onReadyRemoteStreams: () => {
284
+ console.log('Новый поток готов');
285
+ handleNewStream();
286
+ },
287
+ });
288
+ ```
289
+
290
+ ### Управление разрешениями
291
+
292
+ ```typescript
293
+ // Запрос разрешения на камеру
294
+ try {
295
+ await facade.askPermissionToEnableCam();
296
+ console.log('Разрешение на камеру получено');
297
+ } catch (error) {
298
+ console.error('Ошибка получения разрешения:', error);
299
+ }
300
+ ```
301
+
302
+ ---
111
303
 
112
- События агрегируются и отдаются с префиксами менеджеров. Полный перечень смотрите в:
304
+ ## 📡 События и их обработка
113
305
 
114
- - `src/SipConnector/eventNames.ts`
115
- - `src/ApiManager/eventNames.ts`
116
- - `src/StatsManager/eventNames.ts`
306
+ ### Архитектура событий
117
307
 
118
- Примеры часто используемых событий:
308
+ SDK использует **событийно-ориентированную архитектуру** с префиксами для группировки:
119
309
 
120
- - `connection:connected`, `connection:disconnected` состояние подключения;
121
- - `call:accepted`, `call:ended`, `call:failed` жизненный цикл звонка;
122
- - `api:enterRoom`, `api:useLicense`, `api:mustStopPresentation`, `api:newDTMF` — события от сервера;
123
- - `incoming-call:incoming`, `incoming-call:failed` — входящие вызовы;
124
- - `presentation:started`, `presentation:stopped` — презентация.
125
- - `stats:collected` собранная WebRTC‑статистика.
310
+ | Префикс | Описание | Примеры событий |
311
+ | ---------------- | ------------------- | ----------------------------- |
312
+ | `connection:*` | События подключения | `connected`, `disconnected` |
313
+ | `call:*` | События звонков | `accepted`, `ended`, `failed` |
314
+ | `api:*` | События от сервера | `enterRoom`, `useLicense` |
315
+ | `presentation:*` | События презентаций | `started`, `stopped` |
316
+ | `stats:*` | События статистики | `collected` |
126
317
 
127
- Подписка:
318
+ ### Основные события
128
319
 
129
- ```ts
130
- const unsubscribe = sipConnector.on('api:enterRoom', ({ room }) => {
131
- console.log('entered room', room);
320
+ ```typescript
321
+ // Подключение
322
+ sipConnector.on('connection:connected', () => {
323
+ console.log('Подключение установлено');
132
324
  });
133
325
 
134
- // разовая подписка на несколько событий
326
+ sipConnector.on('connection:disconnected', () => {
327
+ console.log('Подключение разорвано');
328
+ });
329
+
330
+ // Звонки
331
+ sipConnector.on('call:accepted', () => {
332
+ console.log('Звонок принят');
333
+ });
334
+
335
+ sipConnector.on('call:ended', () => {
336
+ console.log('Звонок завершен');
337
+ });
338
+
339
+ // API события
340
+ sipConnector.on('api:enterRoom', ({ room }) => {
341
+ console.log('Вход в комнату:', room);
342
+ });
343
+
344
+ sipConnector.on('api:useLicense', (license) => {
345
+ console.log('Лицензия:', license);
346
+ });
347
+ ```
348
+
349
+ ### Продвинутые паттерны
350
+
351
+ ```typescript
352
+ // Ожидание одного из нескольких событий
135
353
  sipConnector.onceRace(['call:ended', 'call:failed'], (_payload, eventName) => {
136
- console.log('call finished by', eventName);
354
+ console.log('Звонок завершен событием:', eventName);
355
+ cleanupCall();
137
356
  });
357
+
358
+ // Ожидание конкретного события
359
+ const roomData = await sipConnector.wait('api:enterRoom');
360
+ console.log('Данные комнаты:', roomData);
361
+ ```
362
+
363
+ ---
364
+
365
+ ## 📈 WebRTC Статистика
366
+
367
+ ### Обзор возможностей
368
+
369
+ SDK предоставляет детальную WebRTC-статистику, основанную на [W3C WebRTC Statistics API](https://www.w3.org/TR/webrtc-stats/), включающую:
370
+
371
+ | Тип статистики | Описание | Метрики |
372
+ | ------------------ | --------------------- | ----------------------------- |
373
+ | **RTP статистика** | Потоковые данные | Пакеты, байты, jitter, loss |
374
+ | **Кодеки** | Параметры кодирования | Параметры, реализация |
375
+ | **ICE кандидаты** | Сетевые соединения | Типы, приоритеты, состояния |
376
+ | **Транспорт** | Защищенные соединения | DTLS, соединения, сертификаты |
377
+
378
+ ### Использование статистики
379
+
380
+ ```typescript
381
+ import { StatsPeerConnection, EStatsTypes, hasAvailableStats } from 'sip-connector';
382
+
383
+ // Проверка доступности
384
+ if (hasAvailableStats()) {
385
+ const statsCollector = new StatsPeerConnection();
386
+
387
+ // Подписка на события статистики
388
+ statsCollector.on('collected', ({ outbound, inbound }) => {
389
+ console.log('Исходящая статистика:', outbound);
390
+ console.log('Входящая статистика:', inbound);
391
+
392
+ // Анализ качества соединения
393
+ analyzeConnectionQuality(outbound, inbound);
394
+ });
395
+ }
138
396
  ```
139
397
 
140
- ## Экспорты
398
+ ### Типы статистики
399
+
400
+ | Категория | Типы | Описание |
401
+ | ---------------------- | --------------------------------- | ------------------------------------------ |
402
+ | **Аудио потоки** | `TInboundAudio`, `TOutboundAudio` | RTP, кодек, jitter buffer, audio level |
403
+ | **Видео потоки** | `TInboundVideo`, `TOutboundVideo` | RTP, кодек, frames, bitrate, resolution |
404
+ | **Сетевая информация** | `TAdditional` | ICE кандидаты, DTLS транспорт, сертификаты |
405
+
406
+ ---
407
+
408
+ ## 🔧 API и экспорты
409
+
410
+ ### Основные классы
141
411
 
142
- ```ts
412
+ ```typescript
143
413
  import {
144
- SipConnector,
145
- SipConnectorFacade,
146
- debug,
147
- enableDebug,
148
- disableDebug,
149
- ECallCause,
150
- hasCanceledCallError,
151
- EUseLicense,
152
- EMimeTypesVideoCodecs,
153
- EStatsTypes,
154
- StatsPeerConnection,
155
- hasAvailableStats,
156
- type TContentHint,
157
- type TCustomError,
158
- type TJsSIP,
159
- tools, // { getUserAgent, getExtraHeaders, hasPurgatory, ... }
414
+ SipConnector, // Низкоуровневый API
415
+ SipConnectorFacade, // Высокоуровневый фасад
416
+ StatsPeerConnection, // Сбор статистики
417
+ // ... другие экспорты
160
418
  } from 'sip-connector';
161
419
  ```
162
420
 
163
- ## Заметки по API
421
+ ### Утилиты и типы
422
+
423
+ ```typescript
424
+ import {
425
+ // Утилиты
426
+ tools, // getUserAgent, getExtraHeaders, hasPurgatory
427
+ hasAvailableStats, // Проверка доступности статистики
428
+
429
+ // Константы
430
+ EStatsTypes, // Типы статистики
431
+ EMimeTypesVideoCodecs, // MIME-типы кодеков
432
+ EUseLicense, // Типы лицензий
433
+
434
+ // Типы
435
+ type TContentHint, // Подсказки для кодирования
436
+ type TInboundStats, // Входящая статистика
437
+ type TOutboundStats, // Исходящая статистика
438
+ } from 'sip-connector';
439
+ ```
440
+
441
+ ---
442
+
443
+ ## 🏗️ Архитектура и паттерны
444
+
445
+ ### Слоистая архитектура
446
+
447
+ ```shell
448
+ ┌─────────────────────────────────────┐
449
+ │ SipConnectorFacade │ ← Высокоуровневый API
450
+ ├─────────────────────────────────────┤
451
+ │ SipConnector │ ← Координация менеджеров
452
+ ├─────────────────────────────────────┤
453
+ │ Connection │ Call │ API │ ← Специализированные менеджеры
454
+ │ Manager │ Manager │ Manager │
455
+ ├─────────────────────────────────────┤
456
+ │ @krivega/jssip │ ← SIP-функциональность
457
+ └─────────────────────────────────────┘
458
+ ```
459
+
460
+ ### Паттерны проектирования
461
+
462
+ | Паттерн | Описание | Применение |
463
+ | --------------- | --------------------------------- | ------------------------ |
464
+ | **Фасад** | Упрощение сложных операций | `SipConnectorFacade` |
465
+ | **Стратегия** | Различные стратегии для звонков | MCU, P2P режимы |
466
+ | **Наблюдатель** | Событийная модель для уведомлений | Event-driven архитектура |
467
+ | **Фабрика** | Создание UA и сессий | `UAFactory` |
468
+
469
+ ---
470
+
471
+ ## 📚 Лучшие практики
472
+
473
+ ### Обработка ошибок
474
+
475
+ ```typescript
476
+ try {
477
+ await facade.connectToServer(config);
478
+ } catch (error) {
479
+ if (error.code === 'CONNECTION_FAILED') {
480
+ // Повторная попытка подключения
481
+ await retryConnection();
482
+ } else {
483
+ // Логирование и уведомление пользователя
484
+ logError(error);
485
+ notifyUser('Ошибка подключения');
486
+ }
487
+ }
488
+ ```
489
+
490
+ ### Управление ресурсами
491
+
492
+ ```typescript
493
+ // Всегда отписывайтесь от событий
494
+ const unsubscribe = facade.onStats(handleStats);
495
+
496
+ // Очистка при размонтировании
497
+ useEffect(() => {
498
+ return () => {
499
+ unsubscribe();
500
+ facade.disconnectFromServer();
501
+ };
502
+ }, []);
503
+ ```
164
504
 
165
- - `SipConnector` — низкоуровневый класс, инкапсулирующий менеджеры подключения/звонков/презентаций. Требует `JsSIP` при создании.
166
- - `SipConnectorFacade` — удобный фасад с готовыми сценариями: `connectToServer`, `callToServer`, `answerToIncomingCall`, `disconnectFromServer`, `replaceMediaStream`, `sendMediaState`, `sendRefusalToTurnOnMic/Cam`, `onUseLicense`, `onMustStopPresentation`, `onMoveToSpectators/Participants` и др. Также проксирует методы `on/once/onceRace/wait/off`, `ping`, `hangUp`, `sendDTMF`, `checkTelephony`, `connection`, `isConfigured`, `isRegistered`.
167
- - Поддерживаются настройки качества: `contentHint`, `degradationPreference`, `simulcastEncodings`, `sendEncodings`, фильтрация кодеков видео через `preferredMimeTypesVideoCodecs`/`excludeMimeTypesVideoCodecs`.
168
- - Статистика: подписка `facade.onStats(handler)` и отписка `facade.offStats(handler)`. Также доступны низкоуровневые инструменты: `StatsPeerConnection`, `EStatsTypes`, `hasAvailableStats`.
505
+ ### Оптимизация производительности
169
506
 
170
- ## Отладка
507
+ ```typescript
508
+ // Используйте debounce для частых событий
509
+ const debouncedStatsHandler = debounce(handleStats, 1000);
510
+ facade.onStats(debouncedStatsHandler);
171
511
 
172
- ```ts
512
+ // Приоритизируйте современные кодеки
513
+ const facade = new SipConnectorFacade(sipConnector, {
514
+ preferredMimeTypesVideoCodecs: ['video/AV1', 'video/VP9'],
515
+ });
516
+ ```
517
+
518
+ ---
519
+
520
+ ## 🐛 Отладка и диагностика
521
+
522
+ ### Включение отладочного режима
523
+
524
+ ```typescript
173
525
  import { enableDebug, disableDebug } from 'sip-connector';
174
526
 
527
+ // Включение детального логирования
175
528
  enableDebug();
176
- // ...
529
+
530
+ // Отключение для продакшена
177
531
  disableDebug();
178
532
  ```
179
533
 
180
- ## Тесты
534
+ ### Мониторинг состояния
535
+
536
+ ```typescript
537
+ // Проверка состояния подключения
538
+ console.log('Подключен:', facade.connection.isConnected());
539
+ console.log('Зарегистрирован:', facade.isRegistered());
540
+
541
+ // Проверка конфигурации
542
+ console.log('Настроен:', facade.isConfigured());
543
+ ```
544
+
545
+ ---
181
546
 
182
- ```sh
547
+ ## 🧪 Тестирование
548
+
549
+ ### Запуск тестов
550
+
551
+ ```bash
552
+ # Все тесты
183
553
  npm test
554
+
555
+ # Тесты с покрытием
556
+ npm run test:coverage
557
+
558
+ # Тесты в watch режиме
559
+ npm run test:watch
184
560
  ```
185
561
 
186
- ## Поддержка браузеров
562
+ ### Тестовые фикстуры
563
+
564
+ SDK включает готовые моки для тестирования:
187
565
 
188
- SDK использует стандартные WebRTC API. Для максимально старых браузеров проверьте поддержку необходимых возможностей (кодеки, Unified Plan, `getDisplayMedia`).
566
+ | Мок | Назначение | Описание |
567
+ | ----------------------- | -------------------- | -------------------------- |
568
+ | `RTCPeerConnectionMock` | WebRTC API | Имитация WebRTC соединений |
569
+ | `UA.mock.ts` | SIP-функциональность | Имитация SIP User Agent |
570
+ | `BaseSession.mock.ts` | Сессии | Имитация SIP сессий |
189
571
 
190
- ## Maintainer
572
+ ---
191
573
 
192
- Krivega Dmitriy
574
+ ## 🌐 Совместимость браузеров
193
575
 
194
- - Website: [krivega.com](https://krivega.com)
195
- - Github: [@Krivega](https://github.com/Krivega)
576
+ ### WebRTC поддержка
196
577
 
197
- ## Contributing
578
+ SDK использует стандартные WebRTC API и совместим с:
579
+
580
+ | Браузер | Версия | Уровень поддержки | Особенности |
581
+ | ----------- | ------ | ----------------- | ------------------------------ |
582
+ | **Chrome** | 67+ | Полная поддержка | Все возможности WebRTC |
583
+ | **Firefox** | 60+ | Полная поддержка | Все возможности WebRTC |
584
+ | **Safari** | 11+ | Базовая поддержка | Ограниченная поддержка кодеков |
585
+ | **Edge** | 79+ | Полная поддержка | Chromium-based |
586
+
587
+ ### Проверка возможностей
588
+
589
+ ```typescript
590
+ // Проверка поддержки WebRTC
591
+ if (!navigator.mediaDevices?.getUserMedia) {
592
+ throw new Error('WebRTC не поддерживается');
593
+ }
594
+
595
+ // Проверка поддержки презентаций
596
+ if (!navigator.mediaDevices?.getDisplayMedia) {
597
+ console.warn('Screen sharing не поддерживается');
598
+ }
599
+ ```
198
600
 
199
- Contributions, issues and feature requests are welcome!
200
- Feel free to check [issues page](https://github.com/Krivega/sip-connector/issues). You can also take a look at the [contributing guide](https://github.com/Krivega/sip-connector/blob/master/CONTRIBUTING.md).
601
+ ---
201
602
 
202
- ## 📝 License
603
+ ## 🤝 Поддержка и сообщество
604
+
605
+ ### Документация
606
+
607
+ - **API Reference**: Полное описание всех методов и типов
608
+ - **Примеры**: Готовые сценарии использования
609
+ - **Архитектура**: Детальное описание внутренней структуры
610
+
611
+ ### Сообщество
612
+
613
+ - **Issues**: [GitHub Issues](https://github.com/Krivega/sip-connector/issues)
614
+ - **Discussions**: Обсуждения и вопросы
615
+ - **Contributing**: Руководство по участию в разработке
616
+
617
+ ## 👨‍💻 Автор
618
+
619
+ **Krivega Dmitriy**
620
+
621
+ - 🌐 Website: [krivega.com](https://krivega.com)
622
+ - 📱 Github: [@Krivega](https://github.com/Krivega)
623
+ - 📧 Email: <mr.krivega@gmail.com>
624
+
625
+ ## 📄 Лицензия
203
626
 
204
627
  Copyright © 2021‑2025 [Krivega Dmitriy](https://github.com/Krivega).
205
- This project is [MIT](https://github.com/Krivega/sip-connector/blob/master/LICENSE) licensed.
628
+
629
+ This project is licensed under the [MIT License](https://github.com/Krivega/sip-connector/blob/master/LICENSE) - see the LICENSE file for details.