Я работаю над видео api Vonage. Я создал несколько опций, используя библиотеку opentok js, но она не полностью соответствует моим требованиям. Я нашел пример приложения opentok accelerator vanilla js, он работает, но у меня проблема. Я назначил роли издателя и подписчика при передаче этой потоковой передачи издателя, работающей нормально, но когда я передаю роль подписчика, она выдаст мне ошибку 1500 (для токена клиента не задана роль publi sh или модератора. После подключения клиента к сеансу, свойство features объекта Session перечисляет возможности клиента.).
Я не очень разбираюсь в концепциях сценария. В качестве основного файла js я хочу запустить подписчика вручную, но я не знаю, как запустить и передать поток в функцию подписчика.
/**
* Manually subscribe to a stream
* @param {Object} stream - An OpenTok stream
* @param {Object} [subscriberProperties] - https://tokbox.com/developer/sdks/js/reference/Session.html#subscribe
* @param {Boolean} [networkTest] - Subscribing to our own publisher as part of a network test?
* @returns {Promise} <resolve: Subscriber, reject: Error>
*/
subscribe = (stream, subscriberProperties, networkTest = false) =>
this.communication.subscribe(stream, subscriberProperties, networkTest)
Это приложение. js
/* global AccCore */
let otCore;
const options = {
// A container can either be a query selector or an HTMLElement
// eslint-disable-next-line no-unused-vars
streamContainers: function streamContainers(pubSub, type, data) {
return {
publisher: {
camera: '#cameraPublisherContainer',
screen: '#screenPublisherContainer',
},
subscriber: {
camera: '#cameraSubscriberContainer',
screen: '#screenSubscriberContainer',
},
}[pubSub][type];
},
controlsContainer: '#controls',
packages: ['textChat', 'screenSharing', 'annotation', 'archiving'],
communication: {
callProperties: null, // Using default
},
textChat: {
name: ['David', 'Paul', 'Emma', 'George', 'Amanda'][Math.random() * 5 | 0], // eslint-disable-line no-bitwise
waitingMessage: 'Messages will be delivered when other users arrive',
container: '#chat',
},
screenSharing: {
extensionID: 'plocfffmbcclpdifaikiikgplfnepkpo',
annotation: true,
externalWindow: false,
dev: true,
screenProperties: null, // Using default
},
annotation: {
},
archiving: {
startURL: 'https://example.com/startArchive',
stopURL: 'https://example.com/stopArchive',
},
};
/** Application Logic */
const app = function() {
const state = {
connected: false,
active: false,
publishers: null,
subscribers: null,
meta: null,
localAudioEnabled: true,
localVideoEnabled: true,
};
/**
* Update the size and position of video containers based on the number of
* publishers and subscribers specified in the meta property returned by otCore.
*/
const updateVideoContainers = () => {
const { meta } = state;
const sharingScreen = meta ? !!meta.publisher.screen : false;
const viewingSharedScreen = meta ? meta.subscriber.screen : false;
const activeCameraSubscribers = meta ? meta.subscriber.camera : 0;
const videoContainerClass = `App-video-container ${(sharingScreen || viewingSharedScreen) ? 'center' : ''}`;
document.getElementById('appVideoContainer').setAttribute('class', videoContainerClass);
const cameraPublisherClass =
`video-container ${!!activeCameraSubscribers || sharingScreen ? 'small' : ''} ${!!activeCameraSubscribers || sharingScreen ? 'small' : ''} ${sharingScreen || viewingSharedScreen ? 'left' : ''}`;
document.getElementById('cameraPublisherContainer').setAttribute('class', cameraPublisherClass);
const screenPublisherClass = `video-container ${!sharingScreen ? 'hidden' : ''}`;
document.getElementById('screenPublisherContainer').setAttribute('class', screenPublisherClass);
const cameraSubscriberClass =
`video-container ${!activeCameraSubscribers ? 'hidden' : ''} active-${activeCameraSubscribers} ${viewingSharedScreen || sharingScreen ? 'small' : ''}`;
document.getElementById('cameraSubscriberContainer').setAttribute('class', cameraSubscriberClass);
const screenSubscriberClass = `video-container ${!viewingSharedScreen ? 'hidden' : ''}`;
document.getElementById('screenSubscriberContainer').setAttribute('class', screenSubscriberClass);
};
/**
* Update the UI
* @param {String} update - 'connected', 'active', or 'meta'
*/
const updateUI = (update) => {
const { connected, active } = state;
switch (update) {
case 'connected':
if (connected) {
document.getElementById('connecting-mask').classList.add('hidden');
document.getElementById('start-mask').classList.remove('hidden');
}
break;
case 'active':
if (active) {
document.getElementById('cameraPublisherContainer').classList.remove('hidden');
document.getElementById('start-mask').classList.add('hidden');
document.getElementById('controls').classList.remove('hidden');
}
break;
case 'meta':
updateVideoContainers();
break;
default:
console.log('nothing to do, nowhere to go');
}
};
/**
* Update the state and UI
*/
const updateState = function(updates) {
Object.assign(state, updates);
Object.keys(updates).forEach(update => updateUI(update));
};
/**
* Start publishing video/audio and subscribe to streams
*/
const startCall = function() {
otCore.startCall()
.then(function({ publishers, subscribers, meta }) {
updateState({ publishers, subscribers, meta, active: true });
}).catch(function(error) { console.log(error); });
};
/**
* Toggle publishing local audio
*/
const toggleLocalAudio = function() {
const enabled = state.localAudioEnabled;
otCore.toggleLocalAudio(!enabled);
updateState({ localAudioEnabled: !enabled });
const action = enabled ? 'add' : 'remove';
document.getElementById('toggleLocalAudio').classList[action]('muted');
};
/**
* Toggle publishing local video
*/
const toggleLocalVideo = function() {
const enabled = state.localVideoEnabled;
otCore.toggleLocalVideo(!enabled);
updateState({ localVideoEnabled: !enabled });
const action = enabled ? 'add' : 'remove';
document.getElementById('toggleLocalVideo').classList[action]('muted');
};
/**
* Subscribe to otCore and UI events
*/
const createEventListeners = function() {
const events = [
'subscribeToCamera',
'unsubscribeFromCamera',
'subscribeToScreen',
'unsubscribeFromScreen',
'startScreenShare',
'endScreenShare',
];
events.forEach(event => otCore.on(event, ({ publishers, subscribers, meta }) => {
updateState({ publishers, subscribers, meta });
}));
document.getElementById('start').addEventListener('click', startCall);
document.getElementById('toggleLocalAudio').addEventListener('click', toggleLocalAudio);
document.getElementById('toggleLocalVideo').addEventListener('click', toggleLocalVideo);
};
/**
* Initialize otCore, connect to the session, and listen to events
*/
const init = function() {
otCore = new AccCore(options);
otCore.connect().then(function() { updateState({ connected: true }); });
createEventListeners();
};
init();
};
document.addEventListener('DOMContentLoaded', app);
Кто-нибудь может предложить решение. Как я могу добиться этого процесса.