Update:Experimental metadata embed tool to use tone

This commit is contained in:
advplyr 2022-09-25 15:56:06 -05:00
parent b6e3559aba
commit 97da73baf3
10 changed files with 296 additions and 119 deletions

View file

@ -1,29 +1,31 @@
<template>
<div id="page-wrapper" class="bg-bg page p-8 overflow-auto relative" :class="streamLibraryItem ? 'streaming' : ''">
<div class="flex justify-center mb-2">
<div class="flex justify-center mb-4">
<div class="w-full max-w-2xl">
<p class="text-xl">Metadata to embed</p>
<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>
</div>
<div class="w-full max-w-2xl"></div>
</div>
<div class="flex justify-center flex-wrap">
<div class="w-full max-w-2xl border border-opacity-10 bg-bg mx-2">
<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="w-1/3 text-xs font-semibold uppercase text-gray-200">Meta Tag</div>
<div class="w-2/3 text-xs font-semibold uppercase text-gray-200">Value</div>
</div>
<div class="w-full max-h-72 overflow-auto">
<template v-for="(keyValue, index) in metadataKeyValues">
<div :key="keyValue.key" class="flex py-1 px-4 text-sm" :class="index % 2 === 0 ? 'bg-primary bg-opacity-25' : ''">
<div class="w-1/3 font-semibold">{{ keyValue.key }}</div>
<template v-for="(value, key, index) in toneObject">
<div :key="key" class="flex py-1 px-4 text-sm" :class="index % 2 === 0 ? 'bg-primary bg-opacity-25' : ''">
<div class="w-1/3 font-semibold">{{ key }}</div>
<div class="w-2/3">
{{ keyValue.value }}
{{ value }}
</div>
</div>
</template>
</div>
</div>
<div class="w-full max-w-2xl border border-opacity-10 bg-bg mx-2">
<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-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>
@ -34,10 +36,10 @@
<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>
<div class="w-24">
{{ chapter.start.toFixed(2) }}
{{ $secondsToTimestamp(chapter.start) }}
</div>
<div class="w-24">
{{ chapter.end.toFixed(2) }}
{{ $secondsToTimestamp(chapter.end) }}
</div>
</div>
</template>
@ -48,12 +50,17 @@
<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-4">
<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="updateAudioFileMetadata">Embed Metadata</ui-btn>
<ui-btn v-if="!embedFinished" color="primary" :loading="updatingMetadata" @click.stop="embedClick">Embed Metadata</ui-btn>
<p v-else class="text-success text-lg font-semibold">Embed Finished!</p>
</div>
<div class="w-full mx-auto border border-opacity-10 bg-bg">
<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>
<div class="w-full mx-auto border border-white border-opacity-10 bg-bg">
<div class="flex py-2 px-4">
<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>
@ -118,7 +125,8 @@ export default {
audiofilesEncoding: {},
audiofilesFinished: {},
updatingMetadata: false,
embedFinished: false
embedFinished: false,
toneObject: null
}
},
computed: {
@ -137,98 +145,35 @@ export default {
streamLibraryItem() {
return this.$store.state.streamLibraryItem
},
metadataKeyValues() {
const keyValues = [
{
key: 'title',
value: this.mediaMetadata.title
},
{
key: 'artist',
value: this.mediaMetadata.authorName
},
{
key: 'album_artist',
value: this.mediaMetadata.authorName
},
{
key: 'date',
value: this.mediaMetadata.publishedYear
},
{
key: 'description',
value: this.mediaMetadata.description
},
{
key: 'genre',
value: this.mediaMetadata.genres.join(';')
},
{
key: 'performer',
value: this.mediaMetadata.narratorName
}
]
if (this.mediaMetadata.subtitle) {
keyValues.push({
key: 'subtitle',
value: this.mediaMetadata.subtitle
})
}
if (this.mediaMetadata.asin) {
keyValues.push({
key: 'asin',
value: this.mediaMetadata.asin
})
}
if (this.mediaMetadata.isbn) {
keyValues.push({
key: 'isbn',
value: this.mediaMetadata.isbn
})
}
if (this.mediaMetadata.language) {
keyValues.push({
key: 'language',
value: this.mediaMetadata.language
})
}
if (this.mediaMetadata.series.length) {
var firstSeries = this.mediaMetadata.series[0]
keyValues.push({
key: 'series',
value: firstSeries.name
})
if (firstSeries.sequence) {
keyValues.push({
key: 'series-part',
value: firstSeries.sequence
})
}
}
return keyValues
},
metadataChapters() {
var chapters = this.media.chapters || []
return chapters.concat(chapters)
}
},
methods: {
updateAudioFileMetadata() {
if (confirm(`Warning!\n\nThis will modify the audio files for this audiobook.\nMake sure your audio files are backed up before using this feature.`)) {
this.updatingMetadata = true
this.$axios
.$get(`/api/items/${this.libraryItemId}/audio-metadata`)
.then(() => {
console.log('Audio metadata encode started')
})
.catch((error) => {
console.error('Audio metadata encode failed', error)
this.updatingMetadata = false
})
embedClick() {
const payload = {
message: `Are you sure you want to embed metadata in ${this.audioFiles.length} audio files?`,
callback: (confirmed) => {
if (confirmed) {
this.updateAudioFileMetadata()
}
},
type: 'yesNo'
}
this.$store.commit('globals/setConfirmPrompt', payload)
},
updateAudioFileMetadata() {
this.updatingMetadata = true
this.$axios
.$get(`/api/items/${this.libraryItemId}/audio-metadata?tone=1`)
.then(() => {
console.log('Audio metadata encode started')
})
.catch((error) => {
console.error('Audio metadata encode failed', error)
this.updatingMetadata = false
})
},
audioMetadataStarted(data) {
console.log('audio metadata started', data)
@ -252,9 +197,21 @@ export default {
if (data.libraryItemId !== this.libraryItemId) return
this.$set(this.audiofilesEncoding, data.ino, false)
this.$set(this.audiofilesFinished, data.ino, true)
},
fetchToneObject() {
this.$axios
.$get(`/api/items/${this.libraryItemId}/tone-object`)
.then((toneObject) => {
delete toneObject.CoverFile
this.toneObject = toneObject
})
.catch((error) => {
console.error('Failed to fetch tone object', error)
})
}
},
mounted() {
this.fetchToneObject()
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)