mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
YouTube video view refactored
This commit is contained in:
parent
78b7cd7f16
commit
80cc9697f7
1 changed files with 484 additions and 174 deletions
|
|
@ -1,97 +1,45 @@
|
|||
var EventEmitter = require('events');
|
||||
var HTMLSubtitles = require('./HTMLSubtitles');
|
||||
|
||||
var YouTubeVideo = function(containerElement) {
|
||||
var videoElement = document.createElement('div');
|
||||
containerElement.appendChild(videoElement);
|
||||
var events = new EventEmitter();
|
||||
function YouTubeVideo(containerElement) {
|
||||
if (!(containerElement instanceof HTMLElement)) {
|
||||
throw new Error('Instance of HTMLElement required as a first argument');
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var ready = false;
|
||||
var observedProps = {};
|
||||
var timeIntervalId = null;
|
||||
var durationIntervalId = null;
|
||||
var dispatchArgsQueue = [];
|
||||
var onEnded = function() {
|
||||
events.emit('ended');
|
||||
};
|
||||
var onError = function(event) {
|
||||
var message;
|
||||
var critical;
|
||||
switch (event.data) {
|
||||
case 2:
|
||||
message = 'Invalid request';
|
||||
critical = true;
|
||||
break;
|
||||
case 5:
|
||||
message = 'The requested content cannot be played';
|
||||
critical = true;
|
||||
break;
|
||||
case 100:
|
||||
message = 'The video has been removed or marked as private';
|
||||
critical = true;
|
||||
break;
|
||||
case 101:
|
||||
case 150:
|
||||
message = 'The video cannot be played in embedded players';
|
||||
critical = true;
|
||||
break;
|
||||
default:
|
||||
message = 'Unknown error';
|
||||
critical = true;
|
||||
}
|
||||
var loaded = false;
|
||||
var destroyed = false;
|
||||
var events = new EventEmitter();
|
||||
var dispatchArgsReadyQueue = [];
|
||||
var dispatchArgsLoadedQueue = [];
|
||||
var pausedObserved = false;
|
||||
var timeObserved = false;
|
||||
var durationObserved = false;
|
||||
var bufferingObserved = false;
|
||||
var volumeObserved = false;
|
||||
var timeChangedIntervalId = window.setInterval(onTimeChangedInterval, 100);
|
||||
var durationChangedIntervalId = window.setInterval(onDurationChangedInterval, 100);
|
||||
var volumeChangedIntervalId = window.setInterval(onVolumeChangedInterval, 100);
|
||||
var subtitles = new HTMLSubtitles(containerElement);
|
||||
var video = null;
|
||||
// TODO handle script element
|
||||
var stylesElement = document.createElement('style');
|
||||
var videoContainer = document.createElement('div');
|
||||
|
||||
events.emit('error', {
|
||||
code: event.data,
|
||||
message: message,
|
||||
critical: critical
|
||||
});
|
||||
};
|
||||
var onPausedChanged = function() {
|
||||
events.emit('propChanged', 'paused', video.getPlayerState() !== YT.PlayerState.PLAYING);
|
||||
};
|
||||
var onTimeChanged = function() {
|
||||
events.emit('propChanged', 'time', video.getCurrentTime() * 1000);
|
||||
};
|
||||
var onDurationChanged = function() {
|
||||
events.emit('propChanged', 'duration', video.getDuration() !== 0 ? video.getDuration() * 1000 : null);
|
||||
};
|
||||
var onVolumeChanged = function(volume) {
|
||||
events.emit('propChanged', 'volume', volume);
|
||||
};
|
||||
var onReady = function() {
|
||||
ready = true;
|
||||
dispatchArgsQueue.forEach(function(args) {
|
||||
this.dispatch.apply(this, args);
|
||||
}, this);
|
||||
dispatchArgsQueue = [];
|
||||
};
|
||||
var onStateChange = function(event) {
|
||||
switch (event.data) {
|
||||
case YT.PlayerState.ENDED:
|
||||
onEnded();
|
||||
break;
|
||||
case YT.PlayerState.PLAYING:
|
||||
if (observedProps.paused) {
|
||||
onPausedChanged();
|
||||
}
|
||||
subtitles.addListener('error', onSubtitlesError);
|
||||
subtitles.addListener('load', updateSubtitleText);
|
||||
containerElement.appendChild(stylesElement);
|
||||
stylesElement.sheet.insertRule('#' + containerElement.id + ' .video { position: absolute; width: 100%; height: 100%; z-index: -1; }', stylesElement.sheet.cssRules.length);
|
||||
containerElement.appendChild(videoContainer);
|
||||
videoContainer.classList.add('video');
|
||||
|
||||
if (observedProps.duration) {
|
||||
onDurationChanged();
|
||||
}
|
||||
break;
|
||||
case YT.PlayerState.PAUSED:
|
||||
if (observedProps.paused) {
|
||||
onPausedChanged();
|
||||
}
|
||||
break;
|
||||
case YT.PlayerState.UNSTARTED:
|
||||
if (observedProps.paused) {
|
||||
onPausedChanged();
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
var video;
|
||||
YT.ready(() => {
|
||||
video = new YT.Player(videoElement, {
|
||||
if (destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
video = new YT.Player(videoContainer, {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
playerVars: {
|
||||
|
|
@ -108,106 +56,468 @@ var YouTubeVideo = function(containerElement) {
|
|||
rel: 0
|
||||
},
|
||||
events: {
|
||||
onError: onError.bind(this),
|
||||
onReady: onReady.bind(this),
|
||||
onStateChange: onStateChange.bind(this)
|
||||
onError: onVideoError,
|
||||
onReady: onVideoReady,
|
||||
onStateChange: onVideoStateChange
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.on = function(eventName, listener) {
|
||||
events.on(eventName, listener);
|
||||
function getPaused() {
|
||||
if (!loaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return video.getPlayerState() !== YT.PlayerState.PLAYING;
|
||||
}
|
||||
function getTime() {
|
||||
if (!loaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Math.floor(video.getCurrentTime() * 1000);
|
||||
}
|
||||
function getDuration() {
|
||||
if (!loaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Math.floor(video.getDuration() * 1000);
|
||||
}
|
||||
function getBuffering() {
|
||||
if (!loaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return video.getPlayerState() === YT.PlayerState.BUFFERING;
|
||||
}
|
||||
function getVolume() {
|
||||
if (!ready || destroyed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return video.isMuted() ? 0 : video.getVolume();
|
||||
}
|
||||
function getSubtitleTracks() {
|
||||
if (!loaded) {
|
||||
return Object.freeze([]);
|
||||
}
|
||||
|
||||
return subtitles.dispatch('getProp', 'tracks');
|
||||
}
|
||||
function getSelectedSubtitleTrackId() {
|
||||
if (!loaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return subtitles.dispatch('getProp', 'selectedTrackId');
|
||||
}
|
||||
function getSubtitleDelay() {
|
||||
if (!loaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return subtitles.dispatch('getProp', 'delay');
|
||||
}
|
||||
function getSubtitleSize() {
|
||||
if (!ready || destroyed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return subtitles.dispatch('getProp', 'size');
|
||||
}
|
||||
function getSubtitleDarkBackground() {
|
||||
if (!ready || destroyed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return subtitles.dispatch('getProp', 'darkBackground');
|
||||
}
|
||||
function onEnded() {
|
||||
events.emit('ended');
|
||||
}
|
||||
function onError(error) {
|
||||
Object.freeze(error);
|
||||
events.emit('error', error);
|
||||
if (error.critical) {
|
||||
self.dispatch('command', 'stop');
|
||||
}
|
||||
}
|
||||
function onPausedChanged() {
|
||||
events.emit('propChanged', 'paused', getPaused());
|
||||
}
|
||||
function onTimeChanged() {
|
||||
events.emit('propChanged', 'time', getTime());
|
||||
}
|
||||
function onDurationChanged() {
|
||||
events.emit('propChanged', 'duration', getDuration());
|
||||
}
|
||||
function onBufferingChanged() {
|
||||
events.emit('propChanged', 'buffering', getBuffering());
|
||||
}
|
||||
function onVolumeChanged() {
|
||||
events.emit('propChanged', 'volume', getVolume());
|
||||
}
|
||||
function onSubtitleTracksChanged() {
|
||||
events.emit('propChanged', 'subtitleTracks', getSubtitleTracks());
|
||||
}
|
||||
function onSelectedSubtitleTrackIdChanged() {
|
||||
events.emit('propChanged', 'selectedSubtitleTrackId', getSelectedSubtitleTrackId());
|
||||
}
|
||||
function onSubtitleDelayChanged() {
|
||||
events.emit('propChanged', 'subtitleDelay', getSubtitleDelay());
|
||||
}
|
||||
function onSubtitleSizeChanged() {
|
||||
events.emit('propChanged', 'subtitleSize', getSubtitleSize());
|
||||
}
|
||||
function onSubtitleDarkBackgroundChanged() {
|
||||
events.emit('propChanged', 'subtitleDarkBackground', getSubtitleDarkBackground());
|
||||
}
|
||||
function onSubtitlesError(error) {
|
||||
var message;
|
||||
switch (error.code) {
|
||||
case 70:
|
||||
message = 'Failed to fetch subtitles from ' + error.track.origin;
|
||||
break;
|
||||
case 71:
|
||||
message = 'Failed to parse subtitles from ' + error.track.origin;
|
||||
break;
|
||||
default:
|
||||
message = 'Unknown subtitles error';
|
||||
}
|
||||
|
||||
onError({
|
||||
code: error.code,
|
||||
message: message,
|
||||
critical: false
|
||||
});
|
||||
}
|
||||
function onVideoError(error) {
|
||||
var message;
|
||||
switch (error.data) {
|
||||
case 2:
|
||||
message = 'Invalid request';
|
||||
break;
|
||||
case 5:
|
||||
message = 'The requested content cannot be played';
|
||||
break;
|
||||
case 100:
|
||||
message = 'The video has been removed or marked as private';
|
||||
break;
|
||||
case 101:
|
||||
case 150:
|
||||
message = 'The video cannot be played in embedded players';
|
||||
break;
|
||||
default:
|
||||
message = 'Unknown error';
|
||||
}
|
||||
|
||||
onError({
|
||||
code: error.data,
|
||||
message: message,
|
||||
critical: true
|
||||
});
|
||||
}
|
||||
function onVideoReady() {
|
||||
ready = true;
|
||||
onVolumeChanged();
|
||||
onSubtitleSizeChanged();
|
||||
onSubtitleDarkBackgroundChanged();
|
||||
flushDispatchArgsQueue(dispatchArgsReadyQueue);
|
||||
}
|
||||
function onVideoStateChange(state) {
|
||||
if (bufferingObserved) {
|
||||
onBufferingChanged();
|
||||
}
|
||||
|
||||
switch (state.data) {
|
||||
case YT.PlayerState.ENDED:
|
||||
onEnded();
|
||||
break;
|
||||
case YT.PlayerState.PAUSED:
|
||||
case YT.PlayerState.PLAYING:
|
||||
if (pausedObserved) {
|
||||
onPausedChanged();
|
||||
}
|
||||
|
||||
if (timeObserved) {
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
if (durationObserved) {
|
||||
onDurationChanged();
|
||||
}
|
||||
|
||||
break;
|
||||
case YT.PlayerState.UNSTARTED:
|
||||
if (pausedObserved) {
|
||||
onPausedChanged();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
function onTimeChangedInterval() {
|
||||
updateSubtitleText();
|
||||
if (timeObserved) {
|
||||
onTimeChanged();
|
||||
}
|
||||
}
|
||||
function onDurationChangedInterval() {
|
||||
if (durationObserved) {
|
||||
onDurationChanged();
|
||||
}
|
||||
}
|
||||
function onVolumeChangedInterval() {
|
||||
if (volumeObserved) {
|
||||
onVolumeChanged();
|
||||
}
|
||||
}
|
||||
function updateSubtitleText() {
|
||||
subtitles.dispatch('command', 'updateText', getTime());
|
||||
}
|
||||
function flushDispatchArgsQueue(dispatchArgsQueue) {
|
||||
while (dispatchArgsQueue.length > 0) {
|
||||
var args = dispatchArgsQueue.shift();
|
||||
self.dispatch.apply(self, args);
|
||||
}
|
||||
}
|
||||
|
||||
this.addListener = function(eventName, listener) {
|
||||
if (destroyed) {
|
||||
throw new Error('Unable to add ' + eventName + ' listener');
|
||||
}
|
||||
|
||||
events.addListener(eventName, listener);
|
||||
};
|
||||
|
||||
this.removeListener = function(eventName, listener) {
|
||||
if (destroyed) {
|
||||
throw new Error('Unable to remove ' + eventName + ' listener');
|
||||
}
|
||||
|
||||
events.removeListener(eventName, listener);
|
||||
};
|
||||
|
||||
this.dispatch = function() {
|
||||
if (arguments[0] === 'observeProp') {
|
||||
switch (arguments[1]) {
|
||||
case 'paused':
|
||||
if (ready) {
|
||||
events.emit('propValue', 'paused', video.getPlayerState() !== YT.PlayerState.PLAYING);
|
||||
observedProps.paused = true;
|
||||
}
|
||||
break;
|
||||
case 'time':
|
||||
if (ready) {
|
||||
events.emit('propValue', 'time', video.getCurrentTime() * 1000);
|
||||
if (timeIntervalId === null) {
|
||||
timeIntervalId = window.setInterval(onTimeChanged, 100);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'duration':
|
||||
if (ready) {
|
||||
events.emit('propValue', 'duration', video.getDuration() !== 0 ? video.getDuration() * 1000 : null);
|
||||
observedProps.duration = true;
|
||||
if (durationIntervalId === null) {
|
||||
durationIntervalId = window.setInterval(onDurationChanged, 5000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'volume':
|
||||
if (ready) {
|
||||
events.emit('propValue', 'volume', video.getVolume());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error('observeProp not supported: ' + arguments[1]);
|
||||
}
|
||||
} else if (arguments[0] === 'setProp') {
|
||||
switch (arguments[1]) {
|
||||
case 'paused':
|
||||
if (ready) {
|
||||
arguments[2] ? video.pauseVideo() : video.playVideo();
|
||||
}
|
||||
break;
|
||||
case 'time':
|
||||
if (ready) {
|
||||
video.seekTo(arguments[2] / 1000);
|
||||
}
|
||||
break;
|
||||
case 'volume':
|
||||
if (ready) {
|
||||
video.setVolume(arguments[2]);
|
||||
onVolumeChanged(arguments[2]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error('setProp not supported: ' + arguments[1]);
|
||||
}
|
||||
} else if (arguments[0] === 'command') {
|
||||
switch (arguments[1]) {
|
||||
case 'load':
|
||||
if (ready) {
|
||||
video.loadVideoById({
|
||||
videoId: arguments[2].ytId,
|
||||
startSeconds: isNaN(arguments[3].time) ? 0 : arguments[3].time / 1000
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'stop':
|
||||
if (ready) {
|
||||
events.removeAllListeners();
|
||||
observedProps = {};
|
||||
clearInterval(timeIntervalId);
|
||||
clearInterval(durationIntervalId);
|
||||
video.pauseVideo();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error('command not supported: ' + arguments[1]);
|
||||
}
|
||||
console.log(Array.from(arguments).map(String))
|
||||
if (destroyed) {
|
||||
throw new Error('Unable to dispatch ' + arguments[0]);
|
||||
}
|
||||
|
||||
if (!ready) {
|
||||
dispatchArgsQueue.push(Array.from(arguments));
|
||||
switch (arguments[0]) {
|
||||
case 'observeProp':
|
||||
switch (arguments[1]) {
|
||||
case 'paused':
|
||||
events.emit('propValue', 'paused', getPaused());
|
||||
pausedObserved = true;
|
||||
return;
|
||||
case 'time':
|
||||
events.emit('propValue', 'time', getTime());
|
||||
timeObserved = true;
|
||||
return;
|
||||
case 'duration':
|
||||
events.emit('propValue', 'duration', getDuration());
|
||||
durationObserved = true;
|
||||
return;
|
||||
case 'buffering':
|
||||
events.emit('propValue', 'duration', getBuffering());
|
||||
bufferingObserved = true;
|
||||
return;
|
||||
case 'volume':
|
||||
events.emit('propValue', 'volume', getVolume());
|
||||
volumeObserved = true;
|
||||
return;
|
||||
case 'subtitleTracks':
|
||||
events.emit('propValue', 'subtitleTracks', getSubtitleTracks());
|
||||
return;
|
||||
case 'selectedSubtitleTrackId':
|
||||
events.emit('propValue', 'selectedSubtitleTrackId', getSelectedSubtitleTrackId());
|
||||
return;
|
||||
case 'subtitleSize':
|
||||
events.emit('propValue', 'subtitleSize', getSubtitleSize());
|
||||
return;
|
||||
case 'subtitleDelay':
|
||||
events.emit('propValue', 'subtitleDelay', getSubtitleDelay());
|
||||
return;
|
||||
case 'subtitleDarkBackground':
|
||||
events.emit('propValue', 'subtitleDarkBackground', getSubtitleDarkBackground());
|
||||
return;
|
||||
default:
|
||||
throw new Error('observeProp not supported: ' + arguments[1]);
|
||||
}
|
||||
case 'setProp':
|
||||
switch (arguments[1]) {
|
||||
case 'paused':
|
||||
if (loaded) {
|
||||
arguments[2] ? video.pauseVideo() : video.playVideo();
|
||||
} else {
|
||||
dispatchArgsLoadedQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'time':
|
||||
if (loaded) {
|
||||
if (!isNaN(arguments[2])) {
|
||||
video.seekTo(arguments[2] / 1000);
|
||||
}
|
||||
} else {
|
||||
dispatchArgsLoadedQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'volume':
|
||||
if (ready) {
|
||||
if (!isNaN(arguments[2])) {
|
||||
video.unMute();
|
||||
video.setVolume(Math.max(0, Math.min(100, arguments[2])));
|
||||
}
|
||||
} else {
|
||||
dispatchArgsReadyQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'selectedSubtitleTrackId':
|
||||
if (loaded) {
|
||||
subtitles.dispatch('setProp', 'selectedTrackId', arguments[2]);
|
||||
onSubtitleDelayChanged();
|
||||
onSelectedSubtitleTrackIdChanged();
|
||||
updateSubtitleText();
|
||||
} else {
|
||||
dispatchArgsLoadedQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'subtitleSize':
|
||||
if (ready) {
|
||||
subtitles.dispatch('setProp', 'size', arguments[2]);
|
||||
onSubtitleSizeChanged();
|
||||
} else {
|
||||
dispatchArgsReadyQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'subtitleDelay':
|
||||
if (loaded) {
|
||||
subtitles.dispatch('setProp', 'delay', arguments[2]);
|
||||
onSubtitleDelayChanged();
|
||||
updateSubtitleText();
|
||||
} else {
|
||||
dispatchArgsLoadedQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'subtitleDarkBackground':
|
||||
if (ready) {
|
||||
subtitles.dispatch('setProp', 'darkBackground', arguments[2]);
|
||||
onSubtitleDarkBackgroundChanged();
|
||||
} else {
|
||||
dispatchArgsReadyQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
default:
|
||||
throw new Error('setProp not supported: ' + arguments[1]);
|
||||
}
|
||||
case 'command':
|
||||
switch (arguments[1]) {
|
||||
case 'addSubtitleTracks':
|
||||
if (loaded) {
|
||||
subtitles.dispatch('command', 'addTracks', arguments[2]);
|
||||
onSubtitleTracksChanged();
|
||||
} else {
|
||||
dispatchArgsLoadedQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'mute':
|
||||
if (ready) {
|
||||
video.mute();
|
||||
} else {
|
||||
dispatchArgsReadyQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'unmute':
|
||||
if (ready) {
|
||||
video.unMute();
|
||||
if (video.getVolume() === 0) {
|
||||
video.setVolume(50);
|
||||
}
|
||||
} else {
|
||||
dispatchArgsReadyQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'stop':
|
||||
loaded = false;
|
||||
dispatchArgsLoadedQueue = [];
|
||||
subtitles.dispatch('command', 'clearTracks');
|
||||
if (ready) {
|
||||
video.stopVideo();
|
||||
}
|
||||
onPausedChanged();
|
||||
onTimeChanged();
|
||||
onDurationChanged();
|
||||
onBufferingChanged();
|
||||
onSubtitleTracksChanged();
|
||||
onSelectedSubtitleTrackIdChanged();
|
||||
onSubtitleDelayChanged();
|
||||
updateSubtitleText();
|
||||
return;
|
||||
case 'load':
|
||||
if (ready) {
|
||||
debugger;
|
||||
var dispatchArgsLoadedQueueCopy = dispatchArgsLoadedQueue.slice();
|
||||
self.dispatch('command', 'stop');
|
||||
dispatchArgsLoadedQueue = dispatchArgsLoadedQueueCopy;
|
||||
var autoplay = typeof arguments[3].autoplay === 'boolean' ? arguments[3].autoplay : true;
|
||||
var time = !isNaN(arguments[3].time) ? arguments[3].time / 1000 : 0;
|
||||
if (autoplay) {
|
||||
video.loadVideoById({
|
||||
videoId: arguments[2].ytId,
|
||||
startSeconds: time
|
||||
});
|
||||
} else {
|
||||
video.cueVideoById({
|
||||
videoId: arguments[2].ytId,
|
||||
startSeconds: time
|
||||
});
|
||||
}
|
||||
loaded = true;
|
||||
onPausedChanged();
|
||||
onTimeChanged();
|
||||
onDurationChanged();
|
||||
onBufferingChanged();
|
||||
onSubtitleDelayChanged();
|
||||
updateSubtitleText();
|
||||
flushDispatchArgsQueue(dispatchArgsLoadedQueue);
|
||||
} else {
|
||||
dispatchArgsReadyQueue.push(Array.from(arguments));
|
||||
}
|
||||
return;
|
||||
case 'destroy':
|
||||
self.dispatch('command', 'stop');
|
||||
destroyed = true;
|
||||
onVolumeChanged();
|
||||
onSubtitleSizeChanged();
|
||||
onSubtitleDarkBackgroundChanged();
|
||||
events.removeAllListeners();
|
||||
clearInterval(timeChangedIntervalId);
|
||||
clearInterval(durationChangedIntervalId);
|
||||
clearInterval(volumeChangedIntervalId);
|
||||
video.destroy();
|
||||
containerElement.removeChild(videoElement);
|
||||
containerElement.removeChild(stylesElement);
|
||||
subtitles.dispatch('command', 'destroy');
|
||||
return;
|
||||
default:
|
||||
throw new Error('command not supported: ' + arguments[1]);
|
||||
}
|
||||
default:
|
||||
throw new Error('Invalid dispatch call: ' + Array.from(arguments).map(String));
|
||||
}
|
||||
};
|
||||
|
||||
Object.freeze(this);
|
||||
};
|
||||
|
||||
YouTubeVideo.manifest = {
|
||||
YouTubeVideo.manifest = Object.freeze({
|
||||
name: 'YouTubeVideo',
|
||||
embedded: true,
|
||||
props: ['paused', 'time', 'duration', 'volume']
|
||||
};
|
||||
props: Object.freeze(['paused', 'time', 'duration', 'volume', 'buffering', 'subtitleTracks', 'selectedSubtitleTrackId', 'subtitleSize', 'subtitleDelay', 'subtitleDarkBackground'])
|
||||
});
|
||||
|
||||
Object.freeze(YouTubeVideo);
|
||||
|
||||
module.exports = YouTubeVideo;
|
||||
|
|
|
|||
Loading…
Reference in a new issue