mirror of
https://github.com/jellyfin/jellyfin-vue.git
synced 2024-10-07 03:23:37 +00:00
feat: drop shaka player and natively play direct streaming audio
This commit is contained in:
parent
d3a2994d58
commit
7d168e8dd9
@ -65,12 +65,12 @@
|
||||
"episodeNumber": "Episode {episodeNumber}",
|
||||
"errors": {
|
||||
"anErrorHappened": "An error happened",
|
||||
"cantPlayItem": "This item can't be played",
|
||||
"messages": {
|
||||
"errorCode": "Error code: {errorCode}",
|
||||
"videoPlayerError": "The video player encountered an unrecoverable error."
|
||||
},
|
||||
"unauthorized": "You're not authorized to access this page",
|
||||
"cantPlayItem": "This item can't be played"
|
||||
"unauthorized": "You're not authorized to access this page"
|
||||
},
|
||||
"failedRetrievingDisplayPreferences": "Unable to get display preferences. Using last known settings.",
|
||||
"failedSettingDisplayPreferences": "Unable to update display preferences.",
|
||||
|
@ -38,9 +38,7 @@
|
||||
"he": "1.2.0",
|
||||
"langs": "2.0.0",
|
||||
"lodash-es": "4.17.21",
|
||||
"mux.js": "6.1.0",
|
||||
"screenfull": "6.0.1",
|
||||
"shaka-player": "4.1.1",
|
||||
"swiper": "8.3.2",
|
||||
"uuid": "9.0.0",
|
||||
"vue": "3.2.39",
|
||||
|
@ -50,7 +50,7 @@
|
||||
:to="getItemDetailsLink(artist, 'MusicArtist')"
|
||||
custom>
|
||||
<span
|
||||
class="text--secondary text-caption text-truncate link"
|
||||
class="font-weight-light text-caption text-truncate link"
|
||||
@click="navigate">
|
||||
{{ artist.Name }}
|
||||
</span>
|
||||
|
@ -26,9 +26,9 @@ import { ticksToMs, formatTime } from '@/utils/time';
|
||||
const playbackManager = playbackManagerStore();
|
||||
const currentInput = ref(0);
|
||||
const clicked = ref(false);
|
||||
const runtime = computed(() => {
|
||||
return ticksToMs(playbackManager.currentItem?.RunTimeTicks) / 1000;
|
||||
});
|
||||
const runtime = computed(
|
||||
() => ticksToMs(playbackManager.currentItem?.RunTimeTicks) / 1000
|
||||
);
|
||||
const sliderValue = computed({
|
||||
get() {
|
||||
return clicked.value ? currentInput.value : playbackManager.currentTime;
|
||||
|
@ -14,28 +14,16 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* Shaka Player needs to be unmounted for it to be properly disposed. However,
|
||||
* since this component will always be mounted in the app (as it's inside the top-level App component),
|
||||
* it doesn't make sense to add code for handling the unmount process.
|
||||
*/
|
||||
// @ts-expect-error - This module doesn't have typings
|
||||
import muxjs from 'mux.js';
|
||||
// @ts-expect-error - This module doesn't have typings
|
||||
import shakaPlayer from 'shaka-player/dist/shaka-player.compiled';
|
||||
import { computed, watch } from 'vue';
|
||||
import { isNil } from 'lodash-es';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { playbackManagerStore, RepeatMode } from '@/store';
|
||||
import { mediaElementRef } from '@/store/playbackManager';
|
||||
import { getImageInfo } from '@/utils/images';
|
||||
import { useSnackbar } from '@/composables';
|
||||
|
||||
const playbackManager = playbackManagerStore();
|
||||
let isShakaAttached = false;
|
||||
const shaka = new shakaPlayer.Player();
|
||||
|
||||
window.muxjs = muxjs;
|
||||
window.player = shaka;
|
||||
shakaPlayer.polyfill.installAll();
|
||||
const { t } = useI18n();
|
||||
|
||||
const mediaElement = computed<'audio' | 'video' | undefined>(() => {
|
||||
if (playbackManager.currentlyPlayingMediaType === 'Audio') {
|
||||
@ -46,51 +34,37 @@ const mediaElement = computed<'audio' | 'video' | undefined>(() => {
|
||||
});
|
||||
|
||||
/**
|
||||
* If the player is a video element and we're
|
||||
* If the player is a video element and we're in the PiP player or fullscreen video playback, we need to ensure the DOM elements are mounted before the teleport target is ready
|
||||
*/
|
||||
const teleportTarget = computed<'body' | '.video-container'>(() => {
|
||||
return mediaElement.value === 'audio' ? 'body' : '.video-container';
|
||||
});
|
||||
const teleportTarget = computed<'body' | '.video-container'>(() =>
|
||||
mediaElement.value === 'audio' ? 'body' : '.video-container'
|
||||
);
|
||||
|
||||
const posterUrl = computed<string>(() => {
|
||||
return !isNil(playbackManager.currentItem) && mediaElement.value === 'video'
|
||||
const posterUrl = computed<string>(() =>
|
||||
!isNil(playbackManager.currentItem) && mediaElement.value === 'video'
|
||||
? getImageInfo(playbackManager.currentItem, {
|
||||
preferBackdrop: true
|
||||
}).url || ''
|
||||
: '';
|
||||
});
|
||||
: ''
|
||||
);
|
||||
|
||||
const isLoopingOnce = computed(
|
||||
() => playbackManager.repeatMode === RepeatMode.RepeatOne
|
||||
);
|
||||
|
||||
watch(mediaElement, async () => {
|
||||
await shaka.detach();
|
||||
isShakaAttached = false;
|
||||
|
||||
if (mediaElementRef.value) {
|
||||
await shaka.attach(mediaElementRef.value);
|
||||
|
||||
if (playbackManager.currentSourceUrl) {
|
||||
await shaka.load(playbackManager.currentSourceUrl);
|
||||
}
|
||||
|
||||
isShakaAttached = true;
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => playbackManager.currentItemIndex,
|
||||
async () => {
|
||||
await shaka.unload();
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => playbackManager.currentSourceUrl,
|
||||
async () => {
|
||||
if (isShakaAttached && playbackManager.currentSourceUrl) {
|
||||
await shaka.load(playbackManager.currentSourceUrl);
|
||||
() => {
|
||||
if (
|
||||
mediaElementRef.value &&
|
||||
playbackManager.currentSourceUrl &&
|
||||
playbackManager.currentMediaSource?.SupportsDirectPlay &&
|
||||
playbackManager.currentlyPlayingMediaType === 'Audio'
|
||||
) {
|
||||
mediaElementRef.value.src = playbackManager.currentSourceUrl;
|
||||
} else {
|
||||
useSnackbar(t('errors.cantPlayItem'), 'error');
|
||||
playbackManager.stop();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -30,11 +30,7 @@ class ItemsStore {
|
||||
* == GETTERS ==
|
||||
*/
|
||||
public getItemById = (id: string | undefined): BaseItemDto | undefined => {
|
||||
return computed(() => {
|
||||
if (id) {
|
||||
return state.value.byId[id];
|
||||
}
|
||||
}).value;
|
||||
return computed(() => (id ? state.value.byId[id] : undefined)).value;
|
||||
};
|
||||
|
||||
public getItemsById = (ids: string[]): BaseItemDto[] => {
|
||||
|
44
package-lock.json
generated
44
package-lock.json
generated
@ -33,9 +33,7 @@
|
||||
"he": "1.2.0",
|
||||
"langs": "2.0.0",
|
||||
"lodash-es": "4.17.21",
|
||||
"mux.js": "6.1.0",
|
||||
"screenfull": "6.0.1",
|
||||
"shaka-player": "4.1.1",
|
||||
"swiper": "8.3.2",
|
||||
"uuid": "9.0.0",
|
||||
"vue": "3.2.39",
|
||||
@ -1694,6 +1692,7 @@
|
||||
"version": "7.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
|
||||
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
@ -6634,7 +6633,8 @@
|
||||
"node_modules/dom-walk": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
|
||||
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
|
||||
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/dom7": {
|
||||
"version": "4.0.4",
|
||||
@ -6877,11 +6877,6 @@
|
||||
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/eme-encryption-scheme-polyfill": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eme-encryption-scheme-polyfill/-/eme-encryption-scheme-polyfill-2.1.1.tgz",
|
||||
"integrity": "sha512-njD17wcUrbqCj0ArpLu5zWXtaiupHb/2fIUQGdInf83GlI+Q6mmqaPGLdrke4savKAu15J/z1Tg/ivDgl14g0g=="
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
@ -9325,6 +9320,7 @@
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"min-document": "^2.19.0",
|
||||
"process": "^0.11.10"
|
||||
@ -11406,6 +11402,7 @@
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
|
||||
"integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dom-walk": "^0.1.0"
|
||||
}
|
||||
@ -11491,22 +11488,6 @@
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/mux.js": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-6.1.0.tgz",
|
||||
"integrity": "sha512-9Ay5vGzAnJnrA+xGpj93YuVIJSqOGOXxvLn/sc0bD4Li1N4s8ED9jn00WyQfPlLRbqNJ0jN4ZZPvJzbIdgYk5Q==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"global": "^4.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"muxjs-transmux": "bin/transmux.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
|
||||
@ -12722,6 +12703,7 @@
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
}
|
||||
@ -13028,7 +13010,8 @@
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/regenerator-transform": {
|
||||
"version": "0.15.0",
|
||||
@ -13610,17 +13593,6 @@
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/shaka-player": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/shaka-player/-/shaka-player-4.1.1.tgz",
|
||||
"integrity": "sha512-4/Ua4fFo+WazdegCmFeXV7VrATSrsSAqRcTZ41WrngGyMCNlqLPI8LYCaDnkirOW+ipffxxZSjlXa1K2Vashjw==",
|
||||
"dependencies": {
|
||||
"eme-encryption-scheme-polyfill": "^2.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/sharp": {
|
||||
"version": "0.30.4",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.30.4.tgz",
|
||||
|
Loading…
Reference in New Issue
Block a user