mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-08 10:21:38 +00:00
Add series metadata tags to FFmpeg encoding
This commit is contained in:
parent
e7a980d55a
commit
cbd63de17d
1 changed files with 44 additions and 1 deletions
|
|
@ -392,6 +392,34 @@ function escapeFFMetadataValue(value) {
|
||||||
return value.replace(/([;=\n\\#])/g, '\\$1')
|
return value.replace(/([;=\n\\#])/g, '\\$1')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the ALBUMSORT tag for proper series ordering.
|
||||||
|
* Format:
|
||||||
|
* - No series: "Title" or "Title - Subtitle"
|
||||||
|
* - In series: "Series Name 001 - Title" (zero-padded sequence)
|
||||||
|
*
|
||||||
|
* @param {import('../models/LibraryItem')} libraryItem
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function computeAlbumSort(libraryItem) {
|
||||||
|
const title = libraryItem.media.title || ''
|
||||||
|
const subtitle = libraryItem.media.subtitle
|
||||||
|
const series = libraryItem.media.series?.[0]
|
||||||
|
|
||||||
|
if (series?.name) {
|
||||||
|
// In series: "Series Name 001 - Title"
|
||||||
|
const sequence = series.bookSeries?.sequence || ''
|
||||||
|
const paddedSequence = sequence ? String(sequence).padStart(3, '0') : ''
|
||||||
|
return `${series.name} ${paddedSequence} - ${title}`.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not in series: "Title" or "Title - Subtitle"
|
||||||
|
if (subtitle) {
|
||||||
|
return `${title} - ${subtitle}`
|
||||||
|
}
|
||||||
|
return title
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the FFmpeg metadata object for a given library item.
|
* Retrieves the FFmpeg metadata object for a given library item.
|
||||||
*
|
*
|
||||||
|
|
@ -408,6 +436,11 @@ function getFFMetadataObject(libraryItem, audioFilesLength) {
|
||||||
format = 'unabridged'
|
format = 'unabridged'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get first series for series tags (multiple series not widely supported)
|
||||||
|
const primarySeries = libraryItem.media.series?.[0]
|
||||||
|
const seriesName = primarySeries?.name
|
||||||
|
const seriesSequence = primarySeries?.bookSeries?.sequence
|
||||||
|
|
||||||
const ffmetadata = {
|
const ffmetadata = {
|
||||||
title: libraryItem.media.title,
|
title: libraryItem.media.title,
|
||||||
artist: libraryItem.media.authorName,
|
artist: libraryItem.media.authorName,
|
||||||
|
|
@ -431,7 +464,17 @@ function getFFMetadataObject(libraryItem, audioFilesLength) {
|
||||||
LANGUAGE: libraryItem.media.language,
|
LANGUAGE: libraryItem.media.language,
|
||||||
EXPLICIT: libraryItem.media.explicit ? '1' : null,
|
EXPLICIT: libraryItem.media.explicit ? '1' : null,
|
||||||
ITUNESADVISORY: libraryItem.media.explicit ? '1' : '2', // 1 = explicit, 2 = clean
|
ITUNESADVISORY: libraryItem.media.explicit ? '1' : '2', // 1 = explicit, 2 = clean
|
||||||
FORMAT: format
|
FORMAT: format,
|
||||||
|
// Series tags (Mp3tag standard)
|
||||||
|
SERIES: seriesName,
|
||||||
|
'SERIES-PART': seriesSequence,
|
||||||
|
PART: seriesSequence, // Libation uses PART
|
||||||
|
// M4B-specific series tags
|
||||||
|
MOVEMENTNAME: seriesName,
|
||||||
|
MOVEMENT: seriesSequence,
|
||||||
|
SHOWMOVEMENT: seriesName ? '1' : null,
|
||||||
|
// Album sort for proper series ordering
|
||||||
|
ALBUMSORT: computeAlbumSort(libraryItem)
|
||||||
}
|
}
|
||||||
Object.keys(ffmetadata).forEach((key) => {
|
Object.keys(ffmetadata).forEach((key) => {
|
||||||
if (!ffmetadata[key]) {
|
if (!ffmetadata[key]) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue