feat: drop shaka player and natively play direct streaming audio

This commit is contained in:
Thibault Nocchi 2023-01-27 22:02:42 +01:00 committed by Fernando Fernández
parent d3a2994d58
commit 7d168e8dd9
7 changed files with 37 additions and 97 deletions

View File

@ -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.",

View File

@ -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",

View File

@ -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>

View File

@ -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;

View File

@ -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();
}
}
);

View File

@ -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
View File

@ -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",