Initial skip intro and subs fix
This commit is contained in:
parent
f593f884d9
commit
2b6f41bb02
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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'),
|
||||
};
|
||||
|
|
|
@ -89,7 +89,10 @@ export default {
|
|||
includeStations: 1,
|
||||
includeExternalMedia: 1,
|
||||
asyncAugmentMetadata: 1,
|
||||
asyncRefreshLocalMediaAgent: 1,
|
||||
asyncRefreshAnalysis: 1,
|
||||
checkFiles: 1,
|
||||
includeMarkers: 1,
|
||||
},
|
||||
signal,
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
},
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ const state = () => ({
|
|||
mediaIndex: 0,
|
||||
offsetMs: 0,
|
||||
playerState: 'stopped',
|
||||
playerControlsShown: true,
|
||||
playerControlsShown: false,
|
||||
playerControlsShownInterval: null,
|
||||
bufferingEventListener: null,
|
||||
clickEventListener: null,
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue