Update:M4b Merge tool moved to manage page

This commit is contained in:
advplyr 2022-10-02 11:53:53 -05:00
parent d456ec2786
commit 441b8c5bb7
6 changed files with 213 additions and 287 deletions

View file

@ -1,9 +1,20 @@
<template>
<div id="page-wrapper" class="bg-bg page p-8 overflow-auto relative" :class="streamLibraryItem ? 'streaming' : ''">
<div class="flex justify-center mb-4">
<div class="flex items-center justify-center mb-6">
<div class="w-full max-w-2xl">
<p class="text-xl mb-2">Metadata to embed</p>
<p class="mb-4 text-base text-gray-300">audiobookshelf uses <a href="https://github.com/sandreas/tone" target="_blank" class="hover:underline text-blue-400 hover:text-blue-300">tone</a> to write metadata.</p>
<p class="text-2xl mb-2">Audiobook File Management Tools</p>
</div>
<div class="w-full max-w-2xl">
<div class="flex justify-end">
<ui-dropdown v-model="selectedTool" :items="availableTools" :disabled="processing" class="max-w-sm" @input="selectedToolUpdated" />
</div>
</div>
</div>
<div class="flex justify-center">
<div class="w-full max-w-2xl">
<p class="text-xl mb-1">Metadata to embed</p>
<p class="mb-2 text-base text-gray-300">audiobookshelf uses <a href="https://github.com/sandreas/tone" target="_blank" class="hover:underline text-blue-400 hover:text-blue-300">tone</a> to write metadata.</p>
</div>
<div class="w-full max-w-2xl"></div>
</div>
@ -26,12 +37,13 @@
</div>
</div>
<div class="w-full max-w-2xl border border-white border-opacity-10 bg-bg mx-2">
<div class="flex py-2 px-4">
<div class="flex py-2 px-4 bg-primary bg-opacity-25">
<div class="flex-grow text-xs font-semibold uppercase text-gray-200">Chapter Title</div>
<div class="w-24 text-xs font-semibold uppercase text-gray-200">Start</div>
<div class="w-24 text-xs font-semibold uppercase text-gray-200">End</div>
</div>
<div class="w-full max-h-72 overflow-auto">
<p v-if="!metadataChapters.length" class="py-5 text-center text-gray-200">No chapters</p>
<template v-for="(chapter, index) in metadataChapters">
<div :key="index" class="flex py-1 px-4 text-sm" :class="index % 2 === 0 ? 'bg-primary bg-opacity-25' : ''">
<div class="flex-grow font-semibold">{{ chapter.title }}</div>
@ -50,18 +62,44 @@
<div class="w-full h-px bg-white bg-opacity-10 my-8" />
<div class="w-full max-w-4xl mx-auto">
<div class="w-full flex justify-between items-center mb-2">
<p class="text-warning text-lg font-semibold">Warning: Modifies your audio files</p>
<ui-btn v-if="!embedFinished" color="primary" :loading="updatingMetadata" @click.stop="embedClick">Embed Metadata</ui-btn>
<div v-if="selectedTool === 'embed'" class="w-full flex justify-end items-center mb-4">
<ui-btn v-if="!isFinished" color="primary" :loading="processing" @click.stop="embedClick">Start Metadata Embed</ui-btn>
<p v-else class="text-success text-lg font-semibold">Embed Finished!</p>
</div>
<div class="flex mb-4">
<p class="text-gray-200">
A backup of your audio files will be stored in <span class="rounded-md bg-neutral-600 text-sm text-white py-0.5 px-1 font-mono">/metadata/cache/items/{{ libraryItemId }}/</span> so you can restore the originals if necessary.
</p>
<div v-else class="w-full flex justify-end items-center mb-4">
<ui-btn v-if="!isFinished" color="primary" :loading="processing" @click.stop="encodeM4bClick">Start M4B Encode</ui-btn>
<p v-else class="text-success text-lg font-semibold">M4B Finished!</p>
</div>
<div class="mb-4">
<div v-if="selectedTool === 'embed'" class="flex items-start mb-2">
<span class="material-icons text-base text-warning pt-1">star</span>
<p class="text-gray-200 ml-2">Metadata will be embedded on the audio tracks inside your audiobook folder.</p>
</div>
<div v-else class="flex items-start mb-2">
<span class="material-icons text-base text-warning pt-1">star</span>
<p class="text-gray-200 ml-2">
Finished M4B will be put into your audiobook folder at <span class="rounded-md bg-neutral-600 text-sm text-white py-0.5 px-1 font-mono">.../{{ libraryItemRelPath }}/</span>.
</p>
</div>
<div class="flex items-start mb-2">
<span class="material-icons text-base text-warning pt-1">star</span>
<p class="text-gray-200 ml-2">
A backup of your original audio files will be stored in <span class="rounded-md bg-neutral-600 text-sm text-white py-0.5 px-1 font-mono">/metadata/cache/items/{{ libraryItemId }}/</span> so you can restore the originals if necessary.
</p>
</div>
<div class="flex items-start mb-2">
<span class="material-icons text-base text-warning pt-1">star</span>
<p class="text-gray-200 ml-2">Once the task is started you can navigate away from this page.</p>
</div>
</div>
</div>
<div class="w-full max-w-4xl mx-auto">
<p class="mb-2 font-semibold">Audio Tracks</p>
<div class="w-full mx-auto border border-white border-opacity-10 bg-bg">
<div class="flex py-2 px-4">
<div class="flex py-2 px-4 bg-primary bg-opacity-25">
<div class="w-10 text-xs font-semibold text-gray-200">#</div>
<div class="flex-grow text-xs font-semibold uppercase text-gray-200">Filename</div>
<div class="w-16 text-xs font-semibold uppercase text-gray-200">Size</div>
@ -124,15 +162,19 @@ export default {
return {
audiofilesEncoding: {},
audiofilesFinished: {},
updatingMetadata: false,
embedFinished: false,
toneObject: null
processing: false,
isFinished: false,
toneObject: null,
selectedTool: 'embed'
}
},
computed: {
libraryItemId() {
return this.libraryItem.id
},
libraryItemRelPath() {
return this.libraryItem.relPath
},
media() {
return this.libraryItem.media || {}
},
@ -140,16 +182,42 @@ export default {
return this.media.metadata || {}
},
audioFiles() {
return this.media.audioFiles || []
return (this.media.audioFiles || []).filter((af) => !af.exclude && !af.invalid)
},
isSingleM4b() {
return this.audioFiles.length === 1 && this.audioFiles[0].metadata.ext.toLowerCase() === '.m4b'
},
streamLibraryItem() {
return this.$store.state.streamLibraryItem
},
metadataChapters() {
return this.media.chapters || []
},
availableTools() {
if (this.isSingleM4b) {
return [{ value: 'embed', text: 'Embed Metadata' }]
} else {
return [
{ value: 'embed', text: 'Embed Metadata' },
{ value: 'm4b', text: 'M4B Encoder' }
]
}
}
},
methods: {
encodeM4bClick() {
this.processing = true
this.$axios
.$get(`/api/audiobook-merge/${this.libraryItemId}`)
.then(() => {
this.processing = false
})
.catch((error) => {
var errorMsg = error.response ? error.response.data || 'Unknown Error' : 'Unknown Error'
this.$toast.error(errorMsg)
this.processing = false
})
},
embedClick() {
const payload = {
message: `Are you sure you want to embed metadata in ${this.audioFiles.length} audio files?`,
@ -163,7 +231,7 @@ export default {
this.$store.commit('globals/setConfirmPrompt', payload)
},
updateAudioFileMetadata() {
this.updatingMetadata = true
this.processing = true
this.$axios
.$get(`/api/items/${this.libraryItemId}/audio-metadata?tone=1`)
.then(() => {
@ -171,20 +239,20 @@ export default {
})
.catch((error) => {
console.error('Audio metadata encode failed', error)
this.updatingMetadata = false
this.processing = false
})
},
audioMetadataStarted(data) {
console.log('audio metadata started', data)
if (data.libraryItemId !== this.libraryItemId) return
this.audiofilesFinished = {}
this.updatingMetadata = true
this.processing = true
},
audioMetadataFinished(data) {
console.log('audio metadata finished', data)
if (data.libraryItemId !== this.libraryItemId) return
this.updatingMetadata = false
this.embedFinished = true
this.processing = false
this.isFinished = true
this.audiofilesEncoding = {}
this.$toast.success('Audio file metadata updated')
},
@ -197,6 +265,20 @@ export default {
this.$set(this.audiofilesEncoding, data.ino, false)
this.$set(this.audiofilesFinished, data.ino, true)
},
selectedToolUpdated() {
let newurl = window.location.protocol + '//' + window.location.host + window.location.pathname + `?tool=${this.selectedTool}`
window.history.replaceState({ path: newurl }, '', newurl)
},
init() {
this.fetchToneObject()
if (this.$route.query.tool === 'm4b') {
if (this.availableTools.some((t) => t.value === 'm4b')) {
this.selectedTool = 'm4b'
} else {
this.selectedToolUpdated()
}
}
},
fetchToneObject() {
this.$axios
.$get(`/api/items/${this.libraryItemId}/tone-object`)
@ -210,7 +292,7 @@ export default {
}
},
mounted() {
this.fetchToneObject()
this.init()
this.$root.socket.on('audio_metadata_started', this.audioMetadataStarted)
this.$root.socket.on('audio_metadata_finished', this.audioMetadataFinished)
this.$root.socket.on('audiofile_metadata_started', this.audiofileMetadataStarted)