Initial skip intro and subs fix

This commit is contained in:
Travis Shivers 2020-07-30 21:08:44 -05:00
parent f593f884d9
commit 2b6f41bb02
No known key found for this signature in database
GPG Key ID: EE4CC2891B8FCD33
8 changed files with 92 additions and 16 deletions

View File

@ -44,7 +44,7 @@ const defaults = {
default_sync_mode: 'cleanseek',
slplayer_plex_timeline_update_interval: 10000,
slplayer_controls_visible_checker_interval: 500,
slplayer_controls_visible_checker_interval: 250,
// Controlls the max time difference cutoff for syncing by changing the playback speed
slplayer_speed_sync_max_diff: 10000,

View File

@ -25,11 +25,6 @@ export const setVolume = (volume) => {
export const play = () => getPlayer().getMediaElement().play();
export const pause = () => getPlayer().getMediaElement().pause();
// eslint-disable-next-line no-underscore-dangle
export const areControlsShown = () => getOverlay().getControls().enabled_
&& (getOverlay().getControls().getControlsContainer().getAttribute('shown') != null
|| getOverlay().getControls().getControlsContainer().getAttribute('casting') != null);
export const isTimeInBufferedRange = (timeMs) => {
const bufferedTimeRange = getPlayer().getMediaElement().buffered;

View File

@ -20,6 +20,15 @@ export const setOverlay = (newOverlay) => {
overlay = newOverlay;
};
// eslint-disable-next-line no-underscore-dangle
export const areControlsShown = () => !getOverlay() || (getOverlay()?.getControls().enabled_
&& (getOverlay()?.getControls().getControlsContainer().getAttribute('shown') != null
|| getOverlay()?.getControls().getControlsContainer().getAttribute('casting') != null));
export const getControlsOffset = (fallbackHeight) => (areControlsShown()
? (getPlayer()?.getMediaElement().offsetHeight || fallbackHeight) * 0.025 + 48 || 0
: 0);
/**
* Resize the subtitles to the dimensions of the video element.
*
@ -31,15 +40,18 @@ export const resizeSubtitleContainer = () => {
return;
}
const bottomOffset = getControlsOffset();
console.debug('resizeSubtitleContainer', bottomOffset);
const {
videoWidth, videoHeight, offsetWidth, offsetHeight,
} = getPlayer().getMediaElement();
const ratio = Math.min(offsetWidth / videoWidth, offsetHeight / videoHeight);
const ratio = Math.min(offsetWidth / videoWidth, (offsetHeight - bottomOffset) / videoHeight);
const subsWrapperWidth = videoWidth * ratio;
const subsWrapperHeight = videoHeight * ratio;
const subsWrapperLeft = (offsetWidth - subsWrapperWidth) / 2;
const subsWrapperTop = (offsetHeight - subsWrapperHeight) / 2;
const subsWrapperTop = ((offsetHeight - bottomOffset) - subsWrapperHeight) / 2;
subtitleRenderer.resize(subsWrapperWidth, subsWrapperHeight, subsWrapperLeft, subsWrapperTop);
};
@ -94,6 +106,18 @@ const initRenderer = async (ass) => {
resizeSubtitleContainer();
};
const handleStreamError = async (assPromise) => {
try {
await assPromise;
} catch (e) {
if (assAbortController) {
// If there is no abort controller, we have just aborted
// If there is one, then something went wrong
throw e;
}
}
};
const makeAss = async (url) => {
console.debug('makeAss');
const libjass = await import('libjass');
@ -101,6 +125,9 @@ const makeAss = async (url) => {
const stream = resiliantStreamFactory(url, assAbortController.signal);
const parser = new libjass.parser.StreamParser(stream);
// Purposefully not awaited because we never get the full file at once
// We still need to catch abort errors to clean up console
handleStreamError(parser.ass);
return parser.minimalASS;
};
@ -130,8 +157,9 @@ export const setSubtitleUrl = async (url) => {
const ass = await makeAss(url);
if (subtitleRenderer) {
// eslint-disable-next-line no-underscore-dangle
// eslint-disable-next-line no-underscore-dangle
subtitleRenderer._ass = ass;
resizeSubtitleContainer();
} else {
await initRenderer(ass);
}

View File

@ -79,4 +79,10 @@ export default {
: false),
GET_LAST_PLAY_MEDIA_COMMAND_ID: (state) => state.lastPlayMediaCommandId,
GET_ACTIVE_MEDIA_METADATA_MARKERS: (state, getters) => getters
.GET_ACTIVE_MEDIA_METADATA?.Marker || [],
GET_ACTIVE_MEDIA_METADATA_INTRO_MARKER: (state, getters) => getters
.GET_ACTIVE_MEDIA_METADATA_MARKERS.find((marker) => marker.type === 'intro'),
};

View File

@ -89,7 +89,10 @@ export default {
includeStations: 1,
includeExternalMedia: 1,
asyncAugmentMetadata: 1,
asyncRefreshLocalMediaAgent: 1,
asyncRefreshAnalysis: 1,
checkFiles: 1,
includeMarkers: 1,
},
signal,
});

View File

@ -3,13 +3,16 @@ import CAF from 'caf';
import guid from '@/utils/guid';
import { fetchJson, queryFetch, makeUrl } from '@/utils/fetchutils';
import {
play, pause, getDurationMs, areControlsShown, getCurrentTimeMs, isTimeInBufferedRange,
play, pause, getDurationMs, getCurrentTimeMs, isTimeInBufferedRange,
isMediaElementAttached, isPlaying, isPresentationPaused, isBuffering, getVolume, isPaused,
waitForMediaElementEvent, destroy, cancelTrickPlay, load, setPlaybackRate, getPlaybackRate,
setCurrentTimeMs, setVolume, addEventListener, removeEventListener,
getSmallPlayButton, getBigPlayButton, unload,
getSmallPlayButton, getBigPlayButton, unload, addMediaElementEventListener,
removeMediaElementEventListener,
} from '@/player';
import { destroySubtitles, setSubtitleUrl, destroyAss } from '@/player/state';
import {
destroySubtitles, setSubtitleUrl, destroyAss, areControlsShown, resizeSubtitleContainer,
} from '@/player/state';
import Deferred from '@/utils/deferredpromise';
export default {
@ -350,6 +353,7 @@ export default {
dispatch('START_PERIODIC_PLEX_TIMELINE_UPDATE');
} catch (e) {
if (getters.GET_PLAYER_INITIALIZED_DEFERRED_PROMISE) {
// TODO: potentially close player
getters.GET_PLAYER_INITIALIZED_DEFERRED_PROMISE.reject(e);
commit('SET_PLAYER_INITIALIZED_DEFERRED_PROMISE', null);
}
@ -373,6 +377,7 @@ export default {
DESTROY_PLAYER_STATE: async ({ commit, dispatch }) => {
console.debug('DESTROY_PLAYER_STATE');
commit('STOP_UPDATE_PLAYER_CONTROLS_SHOWN_INTERVAL');
commit('UPDATE_PLAYER_CONTROLS_SHOWN', false);
await dispatch('UNREGISTER_PLAYER_EVENTS');
await dispatch('CANCEL_PERIODIC_PLEX_TIMELINE_UPDATE');
@ -462,4 +467,8 @@ export default {
await dispatch('plexclients/UPDATE_ACTIVE_PLAY_QUEUE', null, { root: true });
},
SKIP_INTRO: () => {
console.debug('SKIP_INTRO');
},
};

View File

@ -7,7 +7,7 @@ const state = () => ({
mediaIndex: 0,
offsetMs: 0,
playerState: 'stopped',
playerControlsShown: true,
playerControlsShown: false,
playerControlsShownInterval: null,
bufferingEventListener: null,
clickEventListener: null,

View File

@ -25,6 +25,19 @@
@enterpictureinpicture="HANDLE_PICTURE_IN_PICTURE_CHANGE"
@leavepictureinpicture="HANDLE_PICTURE_IN_PICTURE_CHANGE"
/>
<v-btn
absolute
bottom
right
large
class="skip-intro"
:class="ARE_PLAYER_CONTROLS_SHOWN ? 'above-controls' : null"
:style="skipIntroButtonStyle"
@click="SKIP_INTRO"
>
Skip Intro
</v-btn>
</div>
<v-fade-transition
@ -154,7 +167,7 @@
import { mapActions, mapGetters, mapMutations } from 'vuex';
import sizing from '@/mixins/sizing';
import initialize from '@/player/init';
import { resizeSubtitleContainer } from '@/player/state';
import { resizeSubtitleContainer, getControlsOffset } from '@/player/state';
import 'shaka-player/dist/controls.css';
import 'libjass/libjass.css';
@ -220,6 +233,14 @@ export default {
...mapGetters('plexservers', [
'GET_MEDIA_IMAGE_URL',
]),
skipIntroButtonStyle() {
return this.ARE_PLAYER_CONTROLS_SHOWN
? {
'margin-bottom': `${getControlsOffset(this.$refs?.videoPlayerContainer?.offsetHeight)}px`,
}
: {};
},
},
watch: {
@ -238,6 +259,10 @@ export default {
},
immediate: true,
},
ARE_PLAYER_CONTROLS_SHOWN() {
resizeSubtitleContainer();
},
},
async mounted() {
@ -253,12 +278,12 @@ export default {
await this.INIT_PLAYER_STATE();
window.addEventListener('keyup', this.onKeyUp);
window.addEventListener('resize', resizeSubtitleContainer);
window.addEventListener('resize', this.resizeSubtitles);
},
beforeDestroy() {
window.removeEventListener('keyup', this.onKeyUp);
window.removeEventListener('resize', resizeSubtitleContainer);
window.removeEventListener('resize', this.resizeSubtitles);
this.DESTROY_PLAYER_STATE();
},
@ -279,6 +304,7 @@ export default {
'DESTROY_PLAYER_STATE',
'PLAY_PAUSE_VIDEO',
'SEND_PARTY_PLAY_PAUSE',
'SKIP_INTRO',
]),
...mapMutations([
@ -410,6 +436,15 @@ export default {
margin-left: auto;
margin-right: auto;
}
.skip-intro {
transition-timing-function: cubic-bezier(0.55, 0.06, 0.68, 0.19);
transition: margin 250ms;
}
.skip-intro.above-controls {
transition-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
}
</style>
<style>