Жизненный цикл звонка
Звонок проходит через несколько этапов от инициализации до завершения.
Схема жизненного цикла
┌─────────────┐
│ init() │ ← Инициализация SDK
└──────┬──────┘
│
┌──────▼──────┐
│ authorize() │ ← Авторизация (для не-анонимов)
└──────┬──────┘
│
┌───┴───┐
│ │
┌──▼───┐ ┌─▼──────────────┐
│callTo│ │joinCallByLink │ ← Создание или присоединение
└──┬───┘ └─┬──────────────┘
│ │
└───┬───┘
│
┌──────▼──────┐
│ onConversation │ ← Звонок активен
└──────┬──────┘
│
Коллбэки
│
┌──────▼──────┐
│ hangup() │ ← Завершение
└─────────────┘1. Инициализация
javascript
import * as SDK from '@vkontakte/calls-sdk';
// Проверка поддержки браузера
if (!SDK.browser.isBrowserSupported()) {
console.error('Браузер не поддерживается');
return;
}
// Инициализация с коллбэками
await SDK.init({
apiKey: API_APP_KEY,
// Локальный стрим готов
onLocalStream: (stream, mediaSettings) => {
videoElement.srcObject = stream;
},
// Информация о звонке получена
onConversation: (externalId, mediaModifiers, muteStates, participants, rooms) => {
console.log('Вошли в звонок');
},
// Звонок завершён
onHangup: (type, conversationId) => {
console.log('Звонок завершён:', type);
},
// ...другие коллбэки
});2. Авторизация
javascript
// Для авторизованных пользователей
await SDK.authorize(authTokenFromBackend);
// Для анонимных - токен передаётся в init()
// authorize() вызывать не нужно3. Создание или присоединение к звонку
Создать новый звонок
javascript
import { MediaOption, ExternalIdType } from '@vkontakte/calls-sdk';
// Звонок конкретным пользователям
const conversation = await SDK.callTo(
[{ id: 'user123', type: ExternalIdType.USER }],
[MediaOption.AUDIO, MediaOption.VIDEO]
);
// Звонок с созданием ссылки для подключения
const conversation = await SDK.callTo(
[], // без участников
[MediaOption.AUDIO],
'', // payload
true // создать ссылку
);
console.log('Ссылка:', conversation.joinLink);Присоединиться к существующему звонку
javascript
// По ссылке
await SDK.joinCallByLink(
joinLink,
[MediaOption.AUDIO, MediaOption.VIDEO]
);
// По ID звонка
await SDK.joinCall(
conversationId,
[MediaOption.AUDIO]
);4. Активный звонок
Во время звонка SDK вызывает коллбэки для различных событий:
javascript
await SDK.init({
// Стримы
onLocalStream: (stream, mediaSettings) => {},
onRemoteStream: (userId, stream) => {},
onScreenStream: (stream, mediaSettings) => {},
onRemoteScreenStream: (userId, stream) => {},
// Участники
onRemoteStatus: (userIds, status, data) => {},
onRemoteMediaSettings: (userId, mediaSettings) => {},
onRemoteRemoved: (userId) => {},
// Состояние
onLocalStatus: (status) => {},
onCallState: (isCallActive, canAddParticipants, conversation) => {},
// ...
});Управление медиа
javascript
// Включить/выключить камеру
await SDK.toggleLocalVideo(true);
await SDK.toggleLocalVideo(false);
// Включить/выключить микрофон
await SDK.toggleLocalAudio(true);
await SDK.toggleLocalAudio(false);
// Демонстрация экрана
await SDK.captureScreen(true);
await SDK.captureScreen(false);5. Завершение звонка
Инициировать завершение
javascript
await SDK.hangup();Обработка завершения
javascript
await SDK.init({
// ...
onHangup: (type, conversationId) => {
// type может быть:
// - HangupType.HANGUP - нормальное завершение
// - HangupType.DECLINED - отклонён
// - HangupType.BUSY - занято
// - HangupType.TIMEOUT - таймаут
// - HangupType.FAILED - ошибка
// - HangupReason с деталями ошибки
// Очистить UI
cleanupCall();
}
});Очистка состояния
После onHangup рекомендуется:
- Очистить список участников
- Остановить все медиапотоки
- Сбросить UI в исходное состояние
javascript
function cleanupCall() {
participants = [];
localStream = null;
isInCall = false;
}Обработка ошибок
javascript
try {
await SDK.callTo(/* ... */);
} catch (error) {
if (error instanceof SDK.HangupReason) {
switch (error.hangup) {
case SDK.HangupType.FAILED:
console.error('Не удалось подключиться');
break;
case SDK.FatalError.UNSUPPORTED:
console.error('Браузер не поддерживается');
break;
}
}
}Переподключение
SDK автоматически пытается переподключиться при потере соединения. Статус можно отслеживать через onLocalStatus:
javascript
await SDK.init({
// ...
onLocalStatus: (status) => {
// ParticipantStatus.CONNECTING - переподключение
// ParticipantStatus.CONNECTED - подключен
if (status === ParticipantStatus.CONNECTING) {
showReconnectingUI();
}
}
});