Merge pull request #959 from friday/876

Youtube and vimeo fixes
This commit is contained in:
Sam Potts 2018-05-19 16:49:31 +10:00 committed by GitHub
commit f4858f0c62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 75 deletions

6
src/js/controls.js vendored
View File

@ -481,6 +481,7 @@ const controls = {
// Video playing // Video playing
case 'timeupdate': case 'timeupdate':
case 'seeking': case 'seeking':
case 'seeked':
value = utils.getPercentage(this.currentTime, this.duration); value = utils.getPercentage(this.currentTime, this.duration);
// Set seek range value only if it's a 'natural' time event // Set seek range value only if it's a 'natural' time event
@ -601,9 +602,10 @@ const controls = {
controls.updateProgress.call(this, event); controls.updateProgress.call(this, event);
}, },
// Show the duration on metadataloaded // Show the duration on metadataloaded or durationchange events
durationUpdate() { durationUpdate() {
if (!this.supported.ui) { // Bail if no ui or durationchange event triggered after playing/seek when invertTime is false
if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) {
return; return;
} }

View File

@ -273,7 +273,7 @@ class Listeners {
// Listen for media events // Listen for media events
media() { media() {
// Time change on media // Time change on media
utils.on(this.player.media, 'timeupdate seeking', event => controls.timeUpdate.call(this.player, event)); utils.on(this.player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(this.player, event));
// Display duration // Display duration
utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => controls.durationUpdate.call(this.player, event)); utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => controls.durationUpdate.call(this.player, event));
@ -295,7 +295,7 @@ class Listeners {
}); });
// Check for buffer progress // Check for buffer progress
utils.on(this.player.media, 'progress playing', event => controls.updateProgress.call(this.player, event)); utils.on(this.player.media, 'progress playing seeking seeked', event => controls.updateProgress.call(this.player, event));
// Handle volume changes // Handle volume changes
utils.on(this.player.media, 'volumechange', event => controls.updateVolume.call(this.player, event)); utils.on(this.player.media, 'volumechange', event => controls.updateVolume.call(this.player, event));

View File

@ -7,6 +7,14 @@ import controls from './../controls';
import ui from './../ui'; import ui from './../ui';
import utils from './../utils'; import utils from './../utils';
// Set playback state and trigger change (only on actual change)
function assurePlaybackState(play) {
if (this.media.paused === play) {
this.media.paused = !play;
utils.dispatchEvent.call(this, this.media, play ? 'play' : 'pause');
}
}
const vimeo = { const vimeo = {
setup() { setup() {
// Add embed class for responsive // Add embed class for responsive
@ -120,15 +128,13 @@ const vimeo = {
// Create a faux HTML5 API using the Vimeo API // Create a faux HTML5 API using the Vimeo API
player.media.play = () => { player.media.play = () => {
player.embed.play().then(() => { assurePlaybackState.call(player, true);
player.media.paused = false; return player.embed.play();
});
}; };
player.media.pause = () => { player.media.pause = () => {
player.embed.pause().then(() => { assurePlaybackState.call(player, false);
player.media.paused = true; return player.embed.pause();
});
}; };
player.media.stop = () => { player.media.stop = () => {
@ -143,25 +149,26 @@ const vimeo = {
return currentTime; return currentTime;
}, },
set(time) { set(time) {
// Get current paused state // Vimeo will automatically play on seek if the video hasn't been played before
// Vimeo will automatically play on seek
const { paused } = player.media;
// Set seeking flag // Get current paused state and volume etc
player.media.seeking = true; const { embed, media, paused, volume } = player;
// Trigger seeking // Set seeking state and trigger event
utils.dispatchEvent.call(player, player.media, 'seeking'); media.seeking = true;
utils.dispatchEvent.call(player, media, 'seeking');
// Seek after events // If paused, mute until seek is complete
player.embed.setCurrentTime(time).catch(() => { Promise.resolve(paused && embed.setVolume(0))
// Do nothing // Seek
}); .then(() => embed.setCurrentTime(time))
// Restore paused
// Restore pause state .then(() => paused && embed.pause())
if (paused) { // Restore volume
player.pause(); .then(() => paused && embed.setVolume(volume))
} .catch(() => {
// Do nothing
});
}, },
}); });
@ -315,17 +322,12 @@ const vimeo = {
}); });
player.embed.on('play', () => { player.embed.on('play', () => {
// Only fire play if paused before assurePlaybackState.call(player, true);
if (player.media.paused) {
utils.dispatchEvent.call(player, player.media, 'play');
}
player.media.paused = false;
utils.dispatchEvent.call(player, player.media, 'playing'); utils.dispatchEvent.call(player, player.media, 'playing');
}); });
player.embed.on('pause', () => { player.embed.on('pause', () => {
player.media.paused = true; assurePlaybackState.call(player, false);
utils.dispatchEvent.call(player, player.media, 'pause');
}); });
player.embed.on('timeupdate', data => { player.embed.on('timeupdate', data => {
@ -356,7 +358,6 @@ const vimeo = {
player.embed.on('seeked', () => { player.embed.on('seeked', () => {
player.media.seeking = false; player.media.seeking = false;
utils.dispatchEvent.call(player, player.media, 'seeked'); utils.dispatchEvent.call(player, player.media, 'seeked');
utils.dispatchEvent.call(player, player.media, 'play');
}); });
player.embed.on('ended', () => { player.embed.on('ended', () => {

View File

@ -64,6 +64,14 @@ function mapQualityUnits(levels) {
return utils.dedupe(levels.map(level => mapQualityUnit(level))); return utils.dedupe(levels.map(level => mapQualityUnit(level)));
} }
// Set playback state and trigger change (only on actual change)
function assurePlaybackState(play) {
if (this.media.paused === play) {
this.media.paused = !play;
utils.dispatchEvent.call(this, this.media, play ? 'play' : 'pause');
}
}
const youtube = { const youtube = {
setup() { setup() {
// Add embed class for responsive // Add embed class for responsive
@ -264,10 +272,12 @@ const youtube = {
// Create a faux HTML5 API using the YouTube API // Create a faux HTML5 API using the YouTube API
player.media.play = () => { player.media.play = () => {
assurePlaybackState.call(player, true);
instance.playVideo(); instance.playVideo();
}; };
player.media.pause = () => { player.media.pause = () => {
assurePlaybackState.call(player, false);
instance.pauseVideo(); instance.pauseVideo();
}; };
@ -285,22 +295,17 @@ const youtube = {
return Number(instance.getCurrentTime()); return Number(instance.getCurrentTime());
}, },
set(time) { set(time) {
// Vimeo will automatically play on seek // If paused, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
const { paused } = player.media; if (player.paused) {
player.embed.mute();
}
// Set seeking flag // Set seeking state and trigger event
player.media.seeking = true; player.media.seeking = true;
// Trigger seeking
utils.dispatchEvent.call(player, player.media, 'seeking'); utils.dispatchEvent.call(player, player.media, 'seeking');
// Seek after events sent // Seek after events sent
instance.seekTo(time); instance.seekTo(time);
// Restore pause state
if (paused) {
player.pause();
}
}, },
}); });
@ -419,6 +424,17 @@ const youtube = {
// Reset timer // Reset timer
clearInterval(player.timers.playing); clearInterval(player.timers.playing);
const seeked = player.media.seeking && [
1,
2,
].includes(event.data);
if (seeked) {
// Unset seeking and fire seeked event
player.media.seeking = false;
utils.dispatchEvent.call(player, player.media, 'seeked');
}
// Handle events // Handle events
// -1 Unstarted // -1 Unstarted
// 0 Ended // 0 Ended
@ -438,7 +454,7 @@ const youtube = {
break; break;
case 0: case 0:
player.media.paused = true; assurePlaybackState.call(player, false);
// YouTube doesn't support loop for a single video, so mimick it. // YouTube doesn't support loop for a single video, so mimick it.
if (player.media.loop) { if (player.media.loop) {
@ -452,42 +468,39 @@ const youtube = {
break; break;
case 1: case 1:
// If we were seeking, fire seeked event // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)
if (player.media.seeking) {
utils.dispatchEvent.call(player, player.media, 'seeked');
}
player.media.seeking = false;
// Only fire play if paused before
if (player.media.paused) { if (player.media.paused) {
utils.dispatchEvent.call(player, player.media, 'play'); player.media.pause();
} else {
assurePlaybackState.call(player, true);
utils.dispatchEvent.call(player, player.media, 'playing');
// Poll to get playback progress
player.timers.playing = setInterval(() => {
utils.dispatchEvent.call(player, player.media, 'timeupdate');
}, 50);
// Check duration again due to YouTube bug
// https://github.com/sampotts/plyr/issues/374
// https://code.google.com/p/gdata-issues/issues/detail?id=8690
if (player.media.duration !== instance.getDuration()) {
player.media.duration = instance.getDuration();
utils.dispatchEvent.call(player, player.media, 'durationchange');
}
// Get quality
controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels()));
} }
player.media.paused = false;
utils.dispatchEvent.call(player, player.media, 'playing');
// Poll to get playback progress
player.timers.playing = setInterval(() => {
utils.dispatchEvent.call(player, player.media, 'timeupdate');
}, 50);
// Check duration again due to YouTube bug
// https://github.com/sampotts/plyr/issues/374
// https://code.google.com/p/gdata-issues/issues/detail?id=8690
if (player.media.duration !== instance.getDuration()) {
player.media.duration = instance.getDuration();
utils.dispatchEvent.call(player, player.media, 'durationchange');
}
// Get quality
controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels()));
break; break;
case 2: case 2:
player.media.paused = true; // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)
if (!player.muted) {
utils.dispatchEvent.call(player, player.media, 'pause'); player.embed.unMute();
}
assurePlaybackState.call(player, false);
break; break;