sip-connector 15.3.0 → 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.
- package/LICENSE +1 -1
- package/README.md +526 -88
- package/dist/@SipConnector-DcaeAFrM.cjs +1 -0
- package/dist/{@SipConnector-Gt9XLkRE.js → @SipConnector-uiUlVCMv.js} +962 -401
- package/dist/CallManager/types.d.ts +2 -0
- package/dist/PresentationManager/@PresentationManager.d.ts +5 -3
- package/dist/SipConnector/@SipConnector.d.ts +14 -4
- package/dist/SipConnector/eventNames.d.ts +1 -1
- package/dist/SipConnectorFacade/SipConnectorFacade.d.ts +10 -21
- package/dist/StatsPeerConnection/StatsPeerConnection.d.ts +1 -1
- package/dist/StatsPeerConnection/__fixtures__/callStaticsState.d.ts +3 -3
- package/dist/StatsPeerConnection/eventNames.d.ts +3 -3
- package/dist/StatsPeerConnection/index.d.ts +1 -0
- package/dist/StatsPeerConnection/parseStatsReports.d.ts +3 -3
- package/dist/StatsPeerConnection/requestAllStatistics.d.ts +1 -1
- package/dist/StatsPeerConnection/{typings.d.ts → types.d.ts} +2 -2
- package/dist/VideoSendingBalancer/SenderBalancer.d.ts +3 -1
- package/dist/VideoSendingBalancer/TrackMonitor.d.ts +38 -0
- package/dist/VideoSendingBalancer/VideoSendingBalancer.d.ts +8 -9
- package/dist/VideoSendingBalancer/VideoSendingEventHandler.d.ts +4 -9
- package/dist/VideoSendingBalancer/__fixtures__/createMockTrack.d.ts +5 -0
- package/dist/VideoSendingBalancer/__fixtures__/index.d.ts +1 -0
- package/dist/VideoSendingBalancer/index.d.ts +1 -2
- package/dist/VideoSendingBalancer/types.d.ts +0 -1
- package/dist/VideoSendingBalancerManager/@VideoSendingBalancerManager.d.ts +47 -0
- package/dist/VideoSendingBalancerManager/eventNames.d.ts +20 -0
- package/dist/VideoSendingBalancerManager/index.d.ts +3 -0
- package/dist/doMock.cjs +1 -1
- package/dist/doMock.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +281 -748
- package/dist/logger.d.ts +0 -1
- package/dist/tools/setCodecPreferences.d.ts +5 -0
- package/dist/tools/setParametersToSender/index.d.ts +1 -0
- package/package.json +5 -5
- package/dist/@SipConnector-DV4Ywba-.cjs +0 -1
- package/dist/tools/generateSimulcastEncodings.d.ts +0 -7
- package/dist/tools/resolveUpdateTransceiver.d.ts +0 -6
- package/dist/tools/scaleResolutionAndBitrate.d.ts +0 -10
- /package/dist/{PresentationManager → SipConnector}/constants.d.ts +0 -0
package/README.md
CHANGED
|
@@ -3,189 +3,627 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/sip-connector)
|
|
4
4
|

|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
---
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- исходящих/входящих звонков;
|
|
10
|
-
- управления презентацией (share screen/video);
|
|
11
|
-
- отправки служебных сообщений (DTMF, каналы, синхронизация медиа-состояния);
|
|
12
|
-
- подписки на события платформы.
|
|
8
|
+
## 📖 Описание
|
|
13
9
|
|
|
14
|
-
|
|
10
|
+
**sip-connector** — это TypeScript SDK для интеграции WebRTC-приложений с платформой Vinteo через SIP-протокол. Библиотека построена на базе `@krivega/jssip` и предоставляет высокоуровневый API для создания полнофункциональных видеоконференций.
|
|
15
11
|
|
|
16
|
-
|
|
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
|
|
17
43
|
npm install sip-connector
|
|
18
|
-
|
|
44
|
+
|
|
45
|
+
# yarn
|
|
19
46
|
yarn add sip-connector
|
|
47
|
+
|
|
48
|
+
# pnpm
|
|
49
|
+
pnpm add sip-connector
|
|
20
50
|
```
|
|
21
51
|
|
|
22
|
-
|
|
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+ | Сборка и разработка |
|
|
23
68
|
|
|
24
|
-
|
|
69
|
+
---
|
|
25
70
|
|
|
26
|
-
|
|
71
|
+
## 🎯 Быстрый старт
|
|
72
|
+
|
|
73
|
+
### Шаг 1: Инициализация
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
27
76
|
import { UA, WebSocketInterface } from '@krivega/jssip';
|
|
28
77
|
import { SipConnector, SipConnectorFacade, tools } from 'sip-connector';
|
|
29
78
|
|
|
30
|
-
//
|
|
31
|
-
const sipConnector = new SipConnector({
|
|
79
|
+
// Создание низкоуровневого коннектора
|
|
80
|
+
const sipConnector = new SipConnector({
|
|
81
|
+
JsSIP: { UA, WebSocketInterface },
|
|
82
|
+
});
|
|
32
83
|
|
|
33
|
-
//
|
|
84
|
+
// Создание фасада с настройками кодеков
|
|
34
85
|
const facade = new SipConnectorFacade(sipConnector, {
|
|
35
|
-
//
|
|
86
|
+
// Приоритизация современных кодеков
|
|
36
87
|
preferredMimeTypesVideoCodecs: ['video/AV1', 'video/VP9'],
|
|
37
88
|
excludeMimeTypesVideoCodecs: ['video/H264'],
|
|
38
89
|
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Шаг 2: Подключение к серверу
|
|
39
93
|
|
|
40
|
-
|
|
94
|
+
```typescript
|
|
41
95
|
await facade.connectToServer({
|
|
42
96
|
userAgent: tools.getUserAgent({ appName: 'MyApp' }),
|
|
43
97
|
sipWebSocketServerURL: 'wss://sip.example.com/ws',
|
|
44
98
|
sipServerUrl: 'sip:example.com',
|
|
45
|
-
name: '1001', //
|
|
99
|
+
name: '1001', // SIP URI user part
|
|
46
100
|
password: 'secret',
|
|
47
|
-
isRegisteredUser: true, //
|
|
101
|
+
isRegisteredUser: true, // Включить SIP REGISTER
|
|
48
102
|
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Шаг 3: Исходящий звонок
|
|
49
106
|
|
|
50
|
-
|
|
51
|
-
|
|
107
|
+
```typescript
|
|
108
|
+
// Получение локального медиа-потока
|
|
109
|
+
const localStream = await navigator.mediaDevices.getUserMedia({
|
|
110
|
+
audio: true,
|
|
111
|
+
video: true,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Инициация звонка
|
|
52
115
|
const pc = await facade.callToServer({
|
|
53
116
|
conference: '12345',
|
|
54
117
|
mediaStream: localStream,
|
|
55
118
|
setRemoteStreams: (streams) => {
|
|
56
|
-
//
|
|
57
|
-
console.log('
|
|
119
|
+
// Обработка удаленных потоков
|
|
120
|
+
console.log('Получены удаленные потоки:', streams);
|
|
58
121
|
},
|
|
59
122
|
});
|
|
60
123
|
|
|
61
|
-
//
|
|
124
|
+
// Подписка на WebRTC-статистику
|
|
125
|
+
const unsubscribeStats = facade.onStats(({ outbound, inbound }) => {
|
|
126
|
+
console.log('Исходящая статистика:', outbound);
|
|
127
|
+
console.log('Входящая статистика:', inbound);
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Шаг 4: Завершение работы
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
62
134
|
await facade.disconnectFromServer();
|
|
135
|
+
unsubscribeStats();
|
|
63
136
|
```
|
|
64
137
|
|
|
65
|
-
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 📞 Входящие звонки
|
|
141
|
+
|
|
142
|
+
### Обработка входящих вызовов
|
|
66
143
|
|
|
67
|
-
```
|
|
144
|
+
```typescript
|
|
68
145
|
// Подписка на входящие события
|
|
69
146
|
sipConnector.on('incoming-call:incoming', () => {
|
|
70
|
-
//
|
|
147
|
+
// Автоматический ответ с локальным потоком
|
|
71
148
|
facade.answerToIncomingCall({
|
|
72
149
|
mediaStream: localStream,
|
|
73
150
|
setRemoteStreams: (streams) => {
|
|
74
|
-
|
|
151
|
+
// Отображение удаленных потоков
|
|
152
|
+
displayRemoteStreams(streams);
|
|
75
153
|
},
|
|
76
154
|
});
|
|
77
155
|
});
|
|
78
156
|
```
|
|
79
157
|
|
|
80
|
-
|
|
158
|
+
### Управление состоянием звонка
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// Отслеживание жизненного цикла звонка
|
|
162
|
+
sipConnector.on('call:accepted', () => {
|
|
163
|
+
console.log('Звонок принят');
|
|
164
|
+
});
|
|
165
|
+
|
|
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
|
+
## 🖥️ Управление презентациями
|
|
81
178
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
179
|
+
### Запуск презентации
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// Получение потока экрана
|
|
183
|
+
const displayStream = await navigator.mediaDevices.getDisplayMedia({
|
|
184
|
+
video: true,
|
|
185
|
+
audio: true,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Запуск презентации с настройками качества
|
|
85
189
|
await facade.startPresentation({
|
|
86
190
|
mediaStream: displayStream,
|
|
87
|
-
isP2P: false,
|
|
88
|
-
contentHint: 'detail',
|
|
191
|
+
isP2P: false, // MCU режим
|
|
192
|
+
contentHint: 'detail', // Оптимизация для детального контента
|
|
89
193
|
simulcastEncodings: [
|
|
90
194
|
{ width: 1920, height: 1080, scalabilityMode: 'L3T3_KEY' },
|
|
91
195
|
{ width: 1280, height: 720 },
|
|
92
196
|
],
|
|
93
197
|
});
|
|
198
|
+
```
|
|
94
199
|
|
|
95
|
-
|
|
96
|
-
await facade.updatePresentation({ mediaStream: displayStream, isP2P: false });
|
|
200
|
+
### Обновление и остановка
|
|
97
201
|
|
|
98
|
-
|
|
202
|
+
```typescript
|
|
203
|
+
// Обновление потока презентации
|
|
204
|
+
await facade.updatePresentation({
|
|
205
|
+
mediaStream: newDisplayStream,
|
|
206
|
+
isP2P: false,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Остановка презентации
|
|
99
210
|
await facade.stopShareSipConnector();
|
|
100
211
|
```
|
|
101
212
|
|
|
102
|
-
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 👥 Управление участниками конференции
|
|
216
|
+
|
|
217
|
+
### Отслеживание перемещений
|
|
103
218
|
|
|
104
|
-
|
|
219
|
+
```typescript
|
|
220
|
+
// Подписка на перемещение в зрители
|
|
221
|
+
const unsubscribeMoveToSpectators = facade.onMoveToSpectators(() => {
|
|
222
|
+
console.log('Участник перемещен в зрители');
|
|
223
|
+
updateParticipantRole('spectator');
|
|
224
|
+
});
|
|
105
225
|
|
|
106
|
-
|
|
107
|
-
|
|
226
|
+
// Подписка на перемещение в участники
|
|
227
|
+
const unsubscribeMoveToParticipants = facade.onMoveToParticipants(() => {
|
|
228
|
+
console.log('Участник перемещен в участники');
|
|
229
|
+
updateParticipantRole('participant');
|
|
230
|
+
});
|
|
108
231
|
|
|
109
|
-
|
|
232
|
+
// Отписка при необходимости
|
|
233
|
+
unsubscribeMoveToSpectators();
|
|
234
|
+
unsubscribeMoveToParticipants();
|
|
235
|
+
```
|
|
110
236
|
|
|
111
|
-
|
|
112
|
-
- `call:accepted`, `call:ended`, `call:failed` — жизненный цикл звонка;
|
|
113
|
-
- `api:enterRoom`, `api:useLicense`, `api:mustStopPresentation`, `api:newDTMF` — события от сервера;
|
|
114
|
-
- `incoming-call:incoming`, `incoming-call:failed` — входящие вызовы;
|
|
115
|
-
- `presentation:started`, `presentation:stopped` — презентация.
|
|
237
|
+
### Административные функции
|
|
116
238
|
|
|
117
|
-
|
|
239
|
+
```typescript
|
|
240
|
+
// Принудительная остановка презентации
|
|
241
|
+
facade.onMustStopPresentation(() => {
|
|
242
|
+
console.log('Администратор требует остановить презентацию');
|
|
243
|
+
facade.stopShareSipConnector();
|
|
244
|
+
});
|
|
118
245
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
console.log('
|
|
246
|
+
// Мониторинг лицензий
|
|
247
|
+
facade.onUseLicense((license) => {
|
|
248
|
+
console.log('Используется лицензия:', license);
|
|
249
|
+
updateLicenseStatus(license);
|
|
122
250
|
});
|
|
251
|
+
```
|
|
123
252
|
|
|
124
|
-
|
|
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
|
+
---
|
|
303
|
+
|
|
304
|
+
## 📡 События и их обработка
|
|
305
|
+
|
|
306
|
+
### Архитектура событий
|
|
307
|
+
|
|
308
|
+
SDK использует **событийно-ориентированную архитектуру** с префиксами для группировки:
|
|
309
|
+
|
|
310
|
+
| Префикс | Описание | Примеры событий |
|
|
311
|
+
| ---------------- | ------------------- | ----------------------------- |
|
|
312
|
+
| `connection:*` | События подключения | `connected`, `disconnected` |
|
|
313
|
+
| `call:*` | События звонков | `accepted`, `ended`, `failed` |
|
|
314
|
+
| `api:*` | События от сервера | `enterRoom`, `useLicense` |
|
|
315
|
+
| `presentation:*` | События презентаций | `started`, `stopped` |
|
|
316
|
+
| `stats:*` | События статистики | `collected` |
|
|
317
|
+
|
|
318
|
+
### Основные события
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
// Подключение
|
|
322
|
+
sipConnector.on('connection:connected', () => {
|
|
323
|
+
console.log('Подключение установлено');
|
|
324
|
+
});
|
|
325
|
+
|
|
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
|
+
// Ожидание одного из нескольких событий
|
|
125
353
|
sipConnector.onceRace(['call:ended', 'call:failed'], (_payload, eventName) => {
|
|
126
|
-
console.log('
|
|
354
|
+
console.log('Звонок завершен событием:', eventName);
|
|
355
|
+
cleanupCall();
|
|
127
356
|
});
|
|
357
|
+
|
|
358
|
+
// Ожидание конкретного события
|
|
359
|
+
const roomData = await sipConnector.wait('api:enterRoom');
|
|
360
|
+
console.log('Данные комнаты:', roomData);
|
|
128
361
|
```
|
|
129
362
|
|
|
130
|
-
|
|
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';
|
|
131
382
|
|
|
132
|
-
|
|
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
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
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
|
+
### Основные классы
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
133
413
|
import {
|
|
134
|
-
SipConnector,
|
|
135
|
-
SipConnectorFacade,
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
disableDebug,
|
|
139
|
-
ECallCause,
|
|
140
|
-
hasCanceledCallError,
|
|
141
|
-
EUseLicense,
|
|
142
|
-
EMimeTypesVideoCodecs,
|
|
143
|
-
type TContentHint,
|
|
144
|
-
type TCustomError,
|
|
145
|
-
type TJsSIP,
|
|
146
|
-
tools, // { getUserAgent, getExtraHeaders, hasPurgatory, ... }
|
|
414
|
+
SipConnector, // Низкоуровневый API
|
|
415
|
+
SipConnectorFacade, // Высокоуровневый фасад
|
|
416
|
+
StatsPeerConnection, // Сбор статистики
|
|
417
|
+
// ... другие экспорты
|
|
147
418
|
} from 'sip-connector';
|
|
148
419
|
```
|
|
149
420
|
|
|
150
|
-
|
|
421
|
+
### Утилиты и типы
|
|
151
422
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
+
## 🏗️ Архитектура и паттерны
|
|
155
444
|
|
|
156
|
-
|
|
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
|
+
```
|
|
157
489
|
|
|
158
|
-
|
|
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
|
+
```
|
|
504
|
+
|
|
505
|
+
### Оптимизация производительности
|
|
506
|
+
|
|
507
|
+
```typescript
|
|
508
|
+
// Используйте debounce для частых событий
|
|
509
|
+
const debouncedStatsHandler = debounce(handleStats, 1000);
|
|
510
|
+
facade.onStats(debouncedStatsHandler);
|
|
511
|
+
|
|
512
|
+
// Приоритизируйте современные кодеки
|
|
513
|
+
const facade = new SipConnectorFacade(sipConnector, {
|
|
514
|
+
preferredMimeTypesVideoCodecs: ['video/AV1', 'video/VP9'],
|
|
515
|
+
});
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## 🐛 Отладка и диагностика
|
|
521
|
+
|
|
522
|
+
### Включение отладочного режима
|
|
523
|
+
|
|
524
|
+
```typescript
|
|
159
525
|
import { enableDebug, disableDebug } from 'sip-connector';
|
|
160
526
|
|
|
527
|
+
// Включение детального логирования
|
|
161
528
|
enableDebug();
|
|
162
|
-
|
|
529
|
+
|
|
530
|
+
// Отключение для продакшена
|
|
163
531
|
disableDebug();
|
|
164
532
|
```
|
|
165
533
|
|
|
166
|
-
|
|
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
|
+
---
|
|
167
546
|
|
|
168
|
-
|
|
547
|
+
## 🧪 Тестирование
|
|
548
|
+
|
|
549
|
+
### Запуск тестов
|
|
550
|
+
|
|
551
|
+
```bash
|
|
552
|
+
# Все тесты
|
|
169
553
|
npm test
|
|
554
|
+
|
|
555
|
+
# Тесты с покрытием
|
|
556
|
+
npm run test:coverage
|
|
557
|
+
|
|
558
|
+
# Тесты в watch режиме
|
|
559
|
+
npm run test:watch
|
|
170
560
|
```
|
|
171
561
|
|
|
172
|
-
|
|
562
|
+
### Тестовые фикстуры
|
|
563
|
+
|
|
564
|
+
SDK включает готовые моки для тестирования:
|
|
173
565
|
|
|
174
|
-
|
|
566
|
+
| Мок | Назначение | Описание |
|
|
567
|
+
| ----------------------- | -------------------- | -------------------------- |
|
|
568
|
+
| `RTCPeerConnectionMock` | WebRTC API | Имитация WebRTC соединений |
|
|
569
|
+
| `UA.mock.ts` | SIP-функциональность | Имитация SIP User Agent |
|
|
570
|
+
| `BaseSession.mock.ts` | Сессии | Имитация SIP сессий |
|
|
175
571
|
|
|
176
|
-
|
|
572
|
+
---
|
|
177
573
|
|
|
178
|
-
|
|
574
|
+
## 🌐 Совместимость браузеров
|
|
179
575
|
|
|
180
|
-
|
|
181
|
-
- Github: [@Krivega](https://github.com/Krivega)
|
|
576
|
+
### WebRTC поддержка
|
|
182
577
|
|
|
183
|
-
|
|
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
|
+
```
|
|
184
600
|
|
|
185
|
-
|
|
186
|
-
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
|
+
---
|
|
187
602
|
|
|
188
|
-
##
|
|
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
|
+
## 📄 Лицензия
|
|
189
626
|
|
|
190
627
|
Copyright © 2021‑2025 [Krivega Dmitriy](https://github.com/Krivega).
|
|
191
|
-
|
|
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.
|