mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-01-08 00:08:14 +01:00
Update:Download podcast episodes and embed meta tags #1488
This commit is contained in:
parent
575a162f8b
commit
704fbaced8
@ -4,11 +4,12 @@ const SocketAuthority = require('../SocketAuthority')
|
|||||||
const fs = require('../libs/fsExtra')
|
const fs = require('../libs/fsExtra')
|
||||||
|
|
||||||
const { getPodcastFeed } = require('../utils/podcastUtils')
|
const { getPodcastFeed } = require('../utils/podcastUtils')
|
||||||
const { downloadFile, removeFile } = require('../utils/fileUtils')
|
const { removeFile } = require('../utils/fileUtils')
|
||||||
const filePerms = require('../utils/filePerms')
|
const filePerms = require('../utils/filePerms')
|
||||||
const { levenshteinDistance } = require('../utils/index')
|
const { levenshteinDistance } = require('../utils/index')
|
||||||
const opmlParser = require('../utils/parsers/parseOPML')
|
const opmlParser = require('../utils/parsers/parseOPML')
|
||||||
const prober = require('../utils/prober')
|
const prober = require('../utils/prober')
|
||||||
|
const ffmpegHelpers = require('../utils/ffmpegHelpers')
|
||||||
|
|
||||||
const LibraryFile = require('../objects/files/LibraryFile')
|
const LibraryFile = require('../objects/files/LibraryFile')
|
||||||
const PodcastEpisodeDownload = require('../objects/PodcastEpisodeDownload')
|
const PodcastEpisodeDownload = require('../objects/PodcastEpisodeDownload')
|
||||||
@ -93,7 +94,8 @@ class PodcastManager {
|
|||||||
await filePerms.setDefault(this.currentDownload.libraryItem.path)
|
await filePerms.setDefault(this.currentDownload.libraryItem.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
let success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath).then(() => true).catch((error) => {
|
// Downloads episode and tags it
|
||||||
|
let success = await ffmpegHelpers.downloadPodcastEpisode(this.currentDownload).catch((error) => {
|
||||||
Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
|
Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
@ -126,22 +128,22 @@ class PodcastManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async scanAddPodcastEpisodeAudioFile() {
|
async scanAddPodcastEpisodeAudioFile() {
|
||||||
var libraryFile = await this.getLibraryFile(this.currentDownload.targetPath, this.currentDownload.targetRelPath)
|
const libraryFile = await this.getLibraryFile(this.currentDownload.targetPath, this.currentDownload.targetRelPath)
|
||||||
|
|
||||||
// TODO: Set meta tags on new audio file
|
// TODO: Set meta tags on new audio file
|
||||||
|
|
||||||
var audioFile = await this.probeAudioFile(libraryFile)
|
const audioFile = await this.probeAudioFile(libraryFile)
|
||||||
if (!audioFile) {
|
if (!audioFile) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var libraryItem = this.db.libraryItems.find(li => li.id === this.currentDownload.libraryItem.id)
|
const libraryItem = this.db.libraryItems.find(li => li.id === this.currentDownload.libraryItem.id)
|
||||||
if (!libraryItem) {
|
if (!libraryItem) {
|
||||||
Logger.error(`[PodcastManager] Podcast Episode finished but library item was not found ${this.currentDownload.libraryItem.id}`)
|
Logger.error(`[PodcastManager] Podcast Episode finished but library item was not found ${this.currentDownload.libraryItem.id}`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var podcastEpisode = this.currentDownload.podcastEpisode
|
const podcastEpisode = this.currentDownload.podcastEpisode
|
||||||
podcastEpisode.audioFile = audioFile
|
podcastEpisode.audioFile = audioFile
|
||||||
libraryItem.media.addPodcastEpisode(podcastEpisode)
|
libraryItem.media.addPodcastEpisode(podcastEpisode)
|
||||||
if (libraryItem.isInvalid) {
|
if (libraryItem.isInvalid) {
|
||||||
|
@ -106,6 +106,10 @@ class PodcastEpisode {
|
|||||||
get enclosureUrl() {
|
get enclosureUrl() {
|
||||||
return this.enclosure ? this.enclosure.url : null
|
return this.enclosure ? this.enclosure.url : null
|
||||||
}
|
}
|
||||||
|
get pubYear() {
|
||||||
|
if (!this.publishedAt) return null
|
||||||
|
return new Date(this.publishedAt).getFullYear()
|
||||||
|
}
|
||||||
|
|
||||||
setData(data, index = 1) {
|
setData(data, index = 1) {
|
||||||
this.id = getId('ep')
|
this.id = getId('ep')
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
const axios = require('axios')
|
||||||
const Ffmpeg = require('../libs/fluentFfmpeg')
|
const Ffmpeg = require('../libs/fluentFfmpeg')
|
||||||
const fs = require('../libs/fsExtra')
|
const fs = require('../libs/fsExtra')
|
||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
@ -86,3 +87,77 @@ async function resizeImage(filePath, outputPath, width, height) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
module.exports.resizeImage = resizeImage
|
module.exports.resizeImage = resizeImage
|
||||||
|
|
||||||
|
module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
|
||||||
|
return new Promise(async (resolve) => {
|
||||||
|
const response = await axios({
|
||||||
|
url: podcastEpisodeDownload.url,
|
||||||
|
method: 'GET',
|
||||||
|
responseType: 'stream',
|
||||||
|
timeout: 30000
|
||||||
|
})
|
||||||
|
|
||||||
|
const ffmpeg = Ffmpeg(response.data)
|
||||||
|
ffmpeg.outputOptions([
|
||||||
|
'-c copy',
|
||||||
|
'-metadata',
|
||||||
|
`album=${podcastEpisodeDownload.libraryItem?.media.metadata.title ?? ""}`, // Podcast Title
|
||||||
|
'-metadata',
|
||||||
|
`album-sort=${podcastEpisodeDownload.libraryItem?.media.metadata.title ?? ""}`, // Podcast Title
|
||||||
|
'-metadata',
|
||||||
|
`artist=${podcastEpisodeDownload.libraryItem?.media.metadata.author ?? ""}`, // Podcast Artist
|
||||||
|
'-metadata',
|
||||||
|
`artist-sort=${podcastEpisodeDownload.libraryItem?.media.metadata.author ?? ""}`, // Podcast Artist
|
||||||
|
'-metadata',
|
||||||
|
`comment=${podcastEpisodeDownload.podcastEpisode?.description ?? ""}`, // Episode Description
|
||||||
|
'-metadata',
|
||||||
|
`description=${podcastEpisodeDownload.podcastEpisode?.subtitle ?? ""}`, // Episode Subtitle
|
||||||
|
'-metadata',
|
||||||
|
`disc=${podcastEpisodeDownload.podcastEpisode?.season ?? ""}`, // Episode Season
|
||||||
|
'-metadata',
|
||||||
|
`genre=${podcastEpisodeDownload.libraryItem?.media.metadata.genres.join(';') ?? ""}`, // Podcast Genres
|
||||||
|
'-metadata',
|
||||||
|
`language=${podcastEpisodeDownload.libraryItem?.media.metadata.language ?? ""}`, // Podcast Language
|
||||||
|
'-metadata',
|
||||||
|
`MVNM=${podcastEpisodeDownload.libraryItem?.media.metadata.title ?? ""}`, // Podcast Title
|
||||||
|
'-metadata',
|
||||||
|
`MVIN=${podcastEpisodeDownload.podcastEpisode?.episode ?? ""}`, // Episode Number
|
||||||
|
'-metadata',
|
||||||
|
`track=${podcastEpisodeDownload.podcastEpisode?.episode ?? ""}`, // Episode Number
|
||||||
|
'-metadata',
|
||||||
|
`series-part=${podcastEpisodeDownload.podcastEpisode?.episode ?? ""}`, // Episode Number
|
||||||
|
'-metadata',
|
||||||
|
`podcast=1`,
|
||||||
|
'-metadata',
|
||||||
|
`title=${podcastEpisodeDownload.podcastEpisode?.title ?? ""}`, // Episode Title
|
||||||
|
'-metadata',
|
||||||
|
`title-sort=${podcastEpisodeDownload.podcastEpisode?.title ?? ""}`, // Episode Title
|
||||||
|
'-metadata',
|
||||||
|
`year=${podcastEpisodeDownload.podcastEpisode?.pubYear ?? ""}`, // Episode Pub Year
|
||||||
|
'-metadata',
|
||||||
|
`date=${podcastEpisodeDownload.podcastEpisode?.pubDate ?? ""}`, // Episode PubDate
|
||||||
|
'-metadata',
|
||||||
|
`releasedate=${podcastEpisodeDownload.podcastEpisode?.pubDate ?? ""}`, // Episode PubDate
|
||||||
|
'-metadata',
|
||||||
|
`itunes-id=${podcastEpisodeDownload.libraryItem?.media.metadata.itunesId ?? ""}`, // Podcast iTunes ID
|
||||||
|
'-metadata',
|
||||||
|
`podcast-type=${podcastEpisodeDownload.libraryItem?.media.metadata.type ?? ""}`, // Podcast Type
|
||||||
|
'-metadata',
|
||||||
|
`episode-type=${podcastEpisodeDownload.podcastEpisode?.episodeType ?? ""}` // Episode Type
|
||||||
|
])
|
||||||
|
ffmpeg.addOutput(podcastEpisodeDownload.targetPath)
|
||||||
|
|
||||||
|
ffmpeg.on('start', (cmd) => {
|
||||||
|
Logger.debug(`[FfmpegHelpers] downloadPodcastEpisode: Cmd: ${cmd}`)
|
||||||
|
})
|
||||||
|
ffmpeg.on('error', (err, stdout, stderr) => {
|
||||||
|
Logger.error(`[FfmpegHelpers] downloadPodcastEpisode: Error ${err} ${stdout} ${stderr}`)
|
||||||
|
resolve(false)
|
||||||
|
})
|
||||||
|
ffmpeg.on('end', () => {
|
||||||
|
Logger.debug(`[FfmpegHelpers] downloadPodcastEpisode: Complete`)
|
||||||
|
resolve(podcastEpisodeDownload.targetPath)
|
||||||
|
})
|
||||||
|
ffmpeg.run()
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user