diff --git a/package-lock.json b/package-lock.json index 2da3dbb4..e599dcb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9783,6 +9783,11 @@ "array-find-index": "^1.0.1" } }, + "custom-event-polyfill": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz", + "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==" + }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", @@ -17505,6 +17510,11 @@ } } }, + "loadjs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loadjs/-/loadjs-4.2.0.tgz", + "integrity": "sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA==" + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -19404,6 +19414,18 @@ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true }, + "plyr": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/plyr/-/plyr-3.6.4.tgz", + "integrity": "sha512-l0EKsRxhwGtzpPJhs+okusogXRiJaagNaGYlj+iiyqyNzjh0ef5bhxNLsKhpsGvvZMnfV/KbOvIva+qeNCA9ng==", + "requires": { + "core-js": "^3.8.1", + "custom-event-polyfill": "^1.0.7", + "loadjs": "^4.2.0", + "rangetouch": "^2.0.1", + "url-polyfill": "^1.1.12" + } + }, "pngquant-bin": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/pngquant-bin/-/pngquant-bin-6.0.0.tgz", @@ -20789,6 +20811,11 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, + "rangetouch": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz", + "integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==" + }, "raw-body": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", @@ -24268,6 +24295,11 @@ "prepend-http": "^1.0.1" } }, + "url-polyfill": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/url-polyfill/-/url-polyfill-1.1.12.tgz", + "integrity": "sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==" + }, "url-to-options": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", diff --git a/package.json b/package.json index a24dd6af..75dc385b 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "mux.js": "^5.14.1", "nuxt": "^2.15.8", "nuxt-vuex-localstorage": "^1.3.0", + "plyr": "3.6.4", "qs": "^6.10.1", "shaka-player": "^3.2.1", "simple-icons": "^5.19.0", diff --git a/src/components/Players/HlsPlayer.vue b/src/components/Players/HlsPlayer.vue index 1785ca03..685c5466 100644 --- a/src/components/Players/HlsPlayer.vue +++ b/src/components/Players/HlsPlayer.vue @@ -27,6 +27,7 @@ import Vue from 'vue'; // @ts-expect-error No typings in the old version we're using import Hls, { ErrorData, Events } from 'hls.js'; +import Plyr from 'plyr'; // @ts-expect-error - No types for libass import SubtitlesOctopus from 'libass-wasm'; // @ts-expect-error - No types for libass @@ -59,6 +60,7 @@ export default Vue.extend({ return { playbackInfo: {} as PlaybackInfoResponse, source: '', + plyr: undefined as Plyr | undefined, hls: undefined as Hls | undefined, octopus: undefined as SubtitlesOctopus | undefined, // eslint-disable-next-line @typescript-eslint/no-empty-function @@ -114,6 +116,13 @@ export default Vue.extend({ mediaSource.SupportsTranscoding && mediaSource.TranscodingSubProtocol === 'hls'; + if (!this.plyr) { + this.plyr = new Plyr(this.$refs.player as HTMLVideoElement, { + controls: [], + keyboard: { global: true } + }); + } + if ( mediaSource.SupportsDirectPlay || (isHls && @@ -303,25 +312,22 @@ export default Vue.extend({ this.displayExternalSub(newSub); }, displayExternalSub(newSub: PlaybackTrack | undefined) { - // Disable all VTT subs - for ( - let i = 0; - i < this.getCurrentItemVttParsedSubtitleTracks.length; - ++i - ) { - (this.$refs.player as HTMLMediaElement).textTracks[i].mode = 'disabled'; - } - // Disable octopus if (this.octopus) { this.octopus.dispose(); this.octopus = undefined; } + // We don't always set the Plyr current track to -1 cause it bugs the subs if you then change it back to a new value + // This causes a bug when some tracks have the same srcLang + // https://github.com/sampotts/plyr/issues/2330 + // If new sub doesn't exist, we're done here if (!newSub) { this.subtitleTrack = newSub; + if (this.plyr) this.plyr.currentTrack = -1; + return; } @@ -334,10 +340,12 @@ export default Vue.extend({ ).findIndex((el) => el.jfIdx === newSub.jfIdx); if (vttIdx !== -1) { - (this.$refs.player as HTMLMediaElement).textTracks[vttIdx].mode = - 'showing'; + if (this.plyr) this.plyr.currentTrack = vttIdx; + this.subtitleTrack = newSub; } else if (assIdx !== -1) { + if (this.plyr) this.plyr.currentTrack = -1; + this.octopus = new SubtitlesOctopus({ video: this.$refs.player, workerUrl: SubtitlesOctopusWorker, @@ -388,6 +396,11 @@ export default Vue.extend({ this.octopus = undefined; } + if (this.plyr) { + this.plyr.destroy(); + this.plyr = undefined; + } + this.unsubscribe(); }, onPlay(_event?: Event): void { @@ -433,3 +446,9 @@ video { height: 100%; } + +