Обязательно прочитайте раздел Работа с устройствами

Инициализация и пример использования

import * as SDK from '@vkontakte/calls-sdk';

if (!SDK.browser.isBrowserSupported()) {
// Браузер не поддерживается
return;
}

// Инициализация SDK
await SDK.init({

// Ключ приложения, полученный при регистрации
apiKey: API_APP_KEY,

// Пользовательский токен авторизации
authToken: USER_TOKEN,

// Получен локальный стрим с камеры
onLocalStream: (stream, mediaSettings) => {
$localVideo.srcObject = stream;
},

// Получен локальный стрим с трансляцией экрана
onScreenStream: (stream, mediaSettings) => {
$localScreenVideo.srcObject = stream;
},

// Локальный стрим с камеры или микрофона был обновлен
onLocalStreamUpdate: (mediaSettings, kind) => {
$localVideo.classList.toggle('disabled', !mediaSettings.isVideoEnabled);
},

// Получен стрим с камеры собеседника
onRemoteStream: (userId, stream) => {
$remoteVideos[userId].srcObject = stream;
},

// Получен стрим трансляции экрана собеседника
onRemoteScreenStream: (userId, stream) => {
$remoteScreenVideos[userId].srcObject = stream;
},

// Получена информация о звонке
onConversation: (externalId, mediaModifiers, muteStates, conversationParticipants, rooms) => {
// Обычно этот коллбэк вызывается при входе в звонок
// нужно обработать состояния звонка и нарисовать их в интерфейсе
},

// Изменились состояния локальных устройств
onLocalMediaSettings: (userId, mediaSettings) => {
// Нужно отобразить в интерфейсе включены ли камера и микрофон
},

// Изменились состояния устройств собеседника
onRemoteMediaSettings: (userId, mediaSettings) => {
// Нужно отобразить в интерфейсе включены ли камера и микрофон
},

// Изменилось состояние соединения
onLocalStatus: (status) => {
// Нужно отобразить в интерфейсе состояние
},

// Изменилось состояние соединений собеседников
onRemoteStatus(userIds, status, data) {
// Нужно отобразить в интерфейсе состояния
},

// Запрошены браузерные разрешения на доступ к камере или микрофону
onPermissionsRequested: () => {
// Можно отобразить подсказку для пользователя
},

// Разрешения на доступ к камере или микрофону не были получены
onPermissionsError: (e, orig) => {
console.warn('onPermissionsError', e, orig);
},

// Собеседник отключился от звонка
onRemoteRemoved: (userId) => {
delete $remoteVideos[userId];
},

// Изменилось состояние звонка
onCallState: (isCallActive, canAddParticipants, addParticipantLimit) => {
// Нужно отобразить в интерфейсе
},

// Изменился говорящий собеседник в звонке
onSpeakerChanged: (userId) => {
// Можно в интерфейсе подсветить того, кто сейчас говорит
},

// Звонок завершился
onHangup: (type, conversationId) => {
// Отобразить причину завершения звонка
},

// Исходящий звонок был принят
onCallAccepted: () => {
// Изменить интерфейс исходящего звонка на текущий
},

// Изменился список подключенных устройств
onDeviceChange: () => {
// Обновить список камер и микрофонов в интерфейсе
},

// Изменилось качество локального соединения
onLocalNetworkStatusChanged: (rating) => {
// Отобразить в интерфейсе шкалу качества соединения
},

// Изменилось качество соединения собеседника
onNetworkStatusChanged: (status) => {
// Отобразить в интерфейсе шкалу качества соединения
},

// Изменилась локальная громкость
onLocalVolume: (volume, isMicEnabled) => {
// Можно нарисовать анимацию микрофона, чтобы пользователь видел, что его слышно
},

// Не удалось воспроизвести звук звонка
onAutoplayError: () => {
// Обычно, это фатальная ошибка и мы никого не услышим
},
});

// Авторизуемся в API
await SDK.authorize();

// Звоним пользователю
await SDK.callTo(OPPONENT_ID, [MediaOption.AUDIO]);
// или подключаемся к существующему звонку
await SDK.joinCall(conversationId);

Не забывайте вызывать updateDisplayLayout, иначе видео от собеседников может не приходить