From 16c3a7d9e5be8ed2ffbbcee1c786b88d1cecc4cd Mon Sep 17 00:00:00 2001 From: Albin Larsson Date: Tue, 15 May 2018 05:16:06 +0200 Subject: Rewrite ui.setPoster to check that images arent broken or youtube fallback images. Only show poster element when valid --- src/js/plugins/youtube.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/js/plugins/youtube.js') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 4fde9319..4ba8089b 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -162,7 +162,13 @@ const youtube = { player.media = utils.replaceElement(container, player.media); // Set poster image - player.media.setAttribute('poster', utils.format(player.config.urls.youtube.poster, videoId)); + const posterSrc = format => `https://img.youtube.com/vi/${videoId}/${format}default.jpg`; + + // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) + utils.loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded + .catch(() => utils.loadImage(posterSrc('sd'), 121)) // 480p padded 4:3 + .catch(() => utils.loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists + .then(image => ui.setPoster.call(player, image.src)); // Setup instance // https://developers.google.com/youtube/iframe_api_reference -- cgit v1.2.3 From c845558d960412ad5e942334fd9f60ed173e0a5a Mon Sep 17 00:00:00 2001 From: Albin Larsson Date: Tue, 15 May 2018 16:22:51 +0200 Subject: Youtube poster: Set css backgroundSize to 'cover' for padded youtube thumbnails --- src/js/plugins/youtube.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/js/plugins/youtube.js') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 4ba8089b..10283998 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -168,7 +168,13 @@ const youtube = { utils.loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded .catch(() => utils.loadImage(posterSrc('sd'), 121)) // 480p padded 4:3 .catch(() => utils.loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists - .then(image => ui.setPoster.call(player, image.src)); + .then(image => ui.setPoster.call(player, image.src)) + .then(posterSrc => { + // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) + if (!posterSrc.includes('maxres')) { + player.elements.poster.style.backgroundSize = 'cover'; + } + }); // Setup instance // https://developers.google.com/youtube/iframe_api_reference -- cgit v1.2.3 From 333435a9c2ce263686052318497e604c424d38f3 Mon Sep 17 00:00:00 2001 From: Albin Larsson Date: Fri, 18 May 2018 00:34:59 +0200 Subject: Fix playback state (paused) and events (play/pause) --- src/js/plugins/youtube.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src/js/plugins/youtube.js') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 10283998..794d099b 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -64,6 +64,14 @@ function mapQualityUnits(levels) { 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 = { setup() { // Add embed class for responsive @@ -264,10 +272,12 @@ const youtube = { // Create a faux HTML5 API using the YouTube API player.media.play = () => { + assurePlaybackState.call(player, true); instance.playVideo(); }; player.media.pause = () => { + assurePlaybackState.call(player, false); instance.pauseVideo(); }; @@ -438,7 +448,8 @@ const youtube = { break; case 0: - player.media.paused = true; + // Assure state and event + assurePlaybackState.call(player, false); // YouTube doesn't support loop for a single video, so mimick it. if (player.media.loop) { @@ -455,14 +466,11 @@ const youtube = { // If we were seeking, fire seeked event if (player.media.seeking) { utils.dispatchEvent.call(player, player.media, 'seeked'); + player.media.seeking = false; } - player.media.seeking = false; - // Only fire play if paused before - if (player.media.paused) { - utils.dispatchEvent.call(player, player.media, 'play'); - } - player.media.paused = false; + // Assure state and event (must be done after seeked event) + assurePlaybackState.call(player, true); utils.dispatchEvent.call(player, player.media, 'playing'); @@ -485,9 +493,7 @@ const youtube = { break; case 2: - player.media.paused = true; - - utils.dispatchEvent.call(player, player.media, 'pause'); + assurePlaybackState.call(player, false); break; -- cgit v1.2.3 From f8c89e3e95cb01a621f59d66c60f0fa2d76c4d58 Mon Sep 17 00:00:00 2001 From: Albin Larsson Date: Fri, 18 May 2018 04:42:58 +0200 Subject: Fix #876: YouTube and Vimeo autoplays on seek --- src/js/plugins/youtube.js | 58 ++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 28 deletions(-) (limited to 'src/js/plugins/youtube.js') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 794d099b..391da6ca 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -295,22 +295,17 @@ const youtube = { return Number(instance.getCurrentTime()); }, set(time) { - // Vimeo will automatically play on seek - const { paused } = player.media; + // If paused, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet). + if (player.paused) { + player.embed.mute(); + } - // Set seeking flag + // Set seeking state and trigger event player.media.seeking = true; - - // Trigger seeking utils.dispatchEvent.call(player, player.media, 'seeking'); // Seek after events sent instance.seekTo(time); - - // Restore pause state - if (paused) { - player.pause(); - } }, }); @@ -448,7 +443,6 @@ const youtube = { break; case 0: - // Assure state and event assurePlaybackState.call(player, false); // YouTube doesn't support loop for a single video, so mimick it. @@ -465,34 +459,42 @@ const youtube = { case 1: // If we were seeking, fire seeked event if (player.media.seeking) { - utils.dispatchEvent.call(player, player.media, 'seeked'); player.media.seeking = false; + utils.dispatchEvent.call(player, player.media, 'seeked'); } - // Assure state and event (must be done after seeked event) - assurePlaybackState.call(player, true); + // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) + if (player.media.paused) { + player.media.pause(); + } else { + assurePlaybackState.call(player, true); - utils.dispatchEvent.call(player, player.media, 'playing'); + utils.dispatchEvent.call(player, player.media, 'playing'); - // Poll to get playback progress - player.timers.playing = setInterval(() => { - utils.dispatchEvent.call(player, player.media, 'timeupdate'); - }, 50); + // 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'); - } + // 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())); + // Get quality + controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels())); + } break; case 2: + // Restore audio (YouTube starts playing on seek if the video hasn't been played yet) + if (!player.muted) { + player.embed.unMute(); + } assurePlaybackState.call(player, false); break; -- cgit v1.2.3 From 723298a07b4099486f6c071167979a8f8e2abed2 Mon Sep 17 00:00:00 2001 From: Albin Larsson Date: Sat, 12 May 2018 10:09:53 +0200 Subject: Fix #921: Trigger seeked event in youtube plugin if either playing or paused --- src/js/plugins/youtube.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/js/plugins/youtube.js') diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 391da6ca..67b8093e 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -424,6 +424,17 @@ const youtube = { // Reset timer 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 // -1 Unstarted // 0 Ended @@ -457,12 +468,6 @@ const youtube = { break; case 1: - // If we were seeking, fire seeked event - if (player.media.seeking) { - player.media.seeking = false; - utils.dispatchEvent.call(player, player.media, 'seeked'); - } - // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) if (player.media.paused) { player.media.pause(); -- cgit v1.2.3