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.
- package/LICENSE +1 -1
- package/README.md +522 -98
- package/dist/@SipConnector-DcaeAFrM.cjs +1 -0
- package/dist/{@SipConnector-5Rac5oq2.js → @SipConnector-uiUlVCMv.js} +955 -395
- 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/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 +1 -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-Bv3-Y4Rz.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,203 +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
|
-
- подписки на события платформы.
|
|
13
|
-
- сбора и подписки на WebRTC‑статистику (outbound/inbound RTP, битрейты и др.).
|
|
8
|
+
## 📖 Описание
|
|
14
9
|
|
|
15
|
-
|
|
10
|
+
**sip-connector** — это TypeScript SDK для интеграции WebRTC-приложений с платформой Vinteo через SIP-протокол. Библиотека построена на базе `@krivega/jssip` и предоставляет высокоуровневый API для создания полнофункциональных видеоконференций.
|
|
16
11
|
|
|
17
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
32
|
-
const sipConnector = new SipConnector({
|
|
79
|
+
// Создание низкоуровневого коннектора
|
|
80
|
+
const sipConnector = new SipConnector({
|
|
81
|
+
JsSIP: { UA, WebSocketInterface },
|
|
82
|
+
});
|
|
33
83
|
|
|
34
|
-
//
|
|
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
|
-
|
|
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', //
|
|
99
|
+
name: '1001', // SIP URI user part
|
|
47
100
|
password: 'secret',
|
|
48
|
-
isRegisteredUser: true, //
|
|
101
|
+
isRegisteredUser: true, // Включить SIP REGISTER
|
|
49
102
|
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Шаг 3: Исходящий звонок
|
|
50
106
|
|
|
51
|
-
|
|
52
|
-
|
|
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('
|
|
119
|
+
// Обработка удаленных потоков
|
|
120
|
+
console.log('Получены удаленные потоки:', streams);
|
|
59
121
|
},
|
|
60
122
|
});
|
|
61
123
|
|
|
62
|
-
//
|
|
124
|
+
// Подписка на WebRTC-статистику
|
|
63
125
|
const unsubscribeStats = facade.onStats(({ outbound, inbound }) => {
|
|
64
|
-
console.log('
|
|
65
|
-
console.log('
|
|
126
|
+
console.log('Исходящая статистика:', outbound);
|
|
127
|
+
console.log('Входящая статистика:', inbound);
|
|
66
128
|
});
|
|
129
|
+
```
|
|
67
130
|
|
|
68
|
-
|
|
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
|
-
```
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
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
|
-
|
|
115
|
-
- `src/ApiManager/eventNames.ts`
|
|
116
|
-
- `src/StatsManager/eventNames.ts`
|
|
306
|
+
### Архитектура событий
|
|
117
307
|
|
|
118
|
-
|
|
308
|
+
SDK использует **событийно-ориентированную архитектуру** с префиксами для группировки:
|
|
119
309
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
```
|
|
130
|
-
|
|
131
|
-
|
|
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('
|
|
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
|
-
```
|
|
412
|
+
```typescript
|
|
143
413
|
import {
|
|
144
|
-
SipConnector,
|
|
145
|
-
SipConnectorFacade,
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
566
|
+
| Мок | Назначение | Описание |
|
|
567
|
+
| ----------------------- | -------------------- | -------------------------- |
|
|
568
|
+
| `RTCPeerConnectionMock` | WebRTC API | Имитация WebRTC соединений |
|
|
569
|
+
| `UA.mock.ts` | SIP-функциональность | Имитация SIP User Agent |
|
|
570
|
+
| `BaseSession.mock.ts` | Сессии | Имитация SIP сессий |
|
|
189
571
|
|
|
190
|
-
|
|
572
|
+
---
|
|
191
573
|
|
|
192
|
-
|
|
574
|
+
## 🌐 Совместимость браузеров
|
|
193
575
|
|
|
194
|
-
|
|
195
|
-
- Github: [@Krivega](https://github.com/Krivega)
|
|
576
|
+
### WebRTC поддержка
|
|
196
577
|
|
|
197
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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.
|