mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Merge branch 'master' into feat/book-series-info
This commit is contained in:
		
						commit
						82c3670ee2
					
				@ -80,7 +80,8 @@ export default {
 | 
				
			|||||||
      episodeComponentRefs: {},
 | 
					      episodeComponentRefs: {},
 | 
				
			||||||
      windowHeight: 0,
 | 
					      windowHeight: 0,
 | 
				
			||||||
      episodesTableOffsetTop: 0,
 | 
					      episodesTableOffsetTop: 0,
 | 
				
			||||||
      episodeRowHeight: 176
 | 
					      episodeRowHeight: 176,
 | 
				
			||||||
 | 
					      currScrollTop: 0
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  watch: {
 | 
					  watch: {
 | 
				
			||||||
@ -484,9 +485,8 @@ export default {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    scroll(evt) {
 | 
					    handleScroll() {
 | 
				
			||||||
      if (!evt?.target?.scrollTop) return
 | 
					      const scrollTop = this.currScrollTop
 | 
				
			||||||
      const scrollTop = Math.max(evt.target.scrollTop - this.episodesTableOffsetTop, 0)
 | 
					 | 
				
			||||||
      let firstEpisodeIndex = Math.floor(scrollTop / this.episodeRowHeight)
 | 
					      let firstEpisodeIndex = Math.floor(scrollTop / this.episodeRowHeight)
 | 
				
			||||||
      let lastEpisodeIndex = Math.ceil((scrollTop + this.windowHeight) / this.episodeRowHeight)
 | 
					      let lastEpisodeIndex = Math.ceil((scrollTop + this.windowHeight) / this.episodeRowHeight)
 | 
				
			||||||
      lastEpisodeIndex = Math.min(this.totalEpisodes - 1, lastEpisodeIndex)
 | 
					      lastEpisodeIndex = Math.min(this.totalEpisodes - 1, lastEpisodeIndex)
 | 
				
			||||||
@ -501,6 +501,12 @@ export default {
 | 
				
			|||||||
      })
 | 
					      })
 | 
				
			||||||
      this.mountEpisodes(firstEpisodeIndex, lastEpisodeIndex + 1)
 | 
					      this.mountEpisodes(firstEpisodeIndex, lastEpisodeIndex + 1)
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    scroll(evt) {
 | 
				
			||||||
 | 
					      if (!evt?.target?.scrollTop) return
 | 
				
			||||||
 | 
					      const scrollTop = Math.max(evt.target.scrollTop - this.episodesTableOffsetTop, 0)
 | 
				
			||||||
 | 
					      this.currScrollTop = scrollTop
 | 
				
			||||||
 | 
					      this.handleScroll()
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    initListeners() {
 | 
					    initListeners() {
 | 
				
			||||||
      const itemPageWrapper = document.getElementById('item-page-wrapper')
 | 
					      const itemPageWrapper = document.getElementById('item-page-wrapper')
 | 
				
			||||||
      if (itemPageWrapper) {
 | 
					      if (itemPageWrapper) {
 | 
				
			||||||
@ -535,7 +541,12 @@ export default {
 | 
				
			|||||||
      this.episodesPerPage = Math.ceil(this.windowHeight / this.episodeRowHeight)
 | 
					      this.episodesPerPage = Math.ceil(this.windowHeight / this.episodeRowHeight)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      this.$nextTick(() => {
 | 
					      this.$nextTick(() => {
 | 
				
			||||||
        this.mountEpisodes(0, Math.min(this.episodesPerPage, this.totalEpisodes))
 | 
					        // Maybe update currScrollTop if items were removed
 | 
				
			||||||
 | 
					        const itemPageWrapper = document.getElementById('item-page-wrapper')
 | 
				
			||||||
 | 
					        const { scrollHeight, clientHeight } = itemPageWrapper
 | 
				
			||||||
 | 
					        const maxScrollTop = scrollHeight - clientHeight
 | 
				
			||||||
 | 
					        this.currScrollTop = Math.min(this.currScrollTop, maxScrollTop)
 | 
				
			||||||
 | 
					        this.handleScroll()
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
				
			|||||||
@ -461,6 +461,9 @@ class PodcastController {
 | 
				
			|||||||
      return res.sendStatus(404)
 | 
					      return res.sendStatus(404)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Remove it from the podcastEpisodes array
 | 
				
			||||||
 | 
					    req.libraryItem.media.podcastEpisodes = req.libraryItem.media.podcastEpisodes.filter((ep) => ep.id !== episodeId)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (hardDelete) {
 | 
					    if (hardDelete) {
 | 
				
			||||||
      const audioFile = episode.audioFile
 | 
					      const audioFile = episode.audioFile
 | 
				
			||||||
      // TODO: this will trigger the watcher. should maybe handle this gracefully
 | 
					      // TODO: this will trigger the watcher. should maybe handle this gracefully
 | 
				
			||||||
 | 
				
			|||||||
@ -115,10 +115,24 @@ class PodcastManager {
 | 
				
			|||||||
    let success = false
 | 
					    let success = false
 | 
				
			||||||
    if (this.currentDownload.isMp3) {
 | 
					    if (this.currentDownload.isMp3) {
 | 
				
			||||||
      // Download episode and tag it
 | 
					      // Download episode and tag it
 | 
				
			||||||
      success = await ffmpegHelpers.downloadPodcastEpisode(this.currentDownload).catch((error) => {
 | 
					      const ffmpegDownloadResponse = 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
 | 
					 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
 | 
					      success = !!ffmpegDownloadResponse?.success
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // If failed due to ffmpeg error, retry without tagging
 | 
				
			||||||
 | 
					      // e.g. RSS feed may have incorrect file extension and file type
 | 
				
			||||||
 | 
					      // See https://github.com/advplyr/audiobookshelf/issues/3837
 | 
				
			||||||
 | 
					      if (!success && ffmpegDownloadResponse?.isFfmpegError) {
 | 
				
			||||||
 | 
					        Logger.info(`[PodcastManager] Retrying episode download without tagging`)
 | 
				
			||||||
 | 
					        // Download episode only
 | 
				
			||||||
 | 
					        success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath)
 | 
				
			||||||
 | 
					          .then(() => true)
 | 
				
			||||||
 | 
					          .catch((error) => {
 | 
				
			||||||
 | 
					            Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
 | 
				
			||||||
 | 
					            return false
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      // Download episode only
 | 
					      // Download episode only
 | 
				
			||||||
      success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath)
 | 
					      success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath)
 | 
				
			||||||
 | 
				
			|||||||
@ -99,7 +99,7 @@ module.exports.resizeImage = resizeImage
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {import('../objects/PodcastEpisodeDownload')} podcastEpisodeDownload
 | 
					 * @param {import('../objects/PodcastEpisodeDownload')} podcastEpisodeDownload
 | 
				
			||||||
 * @returns
 | 
					 * @returns {Promise<{success: boolean, isFfmpegError?: boolean}>}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
 | 
					module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
 | 
				
			||||||
  return new Promise(async (resolve) => {
 | 
					  return new Promise(async (resolve) => {
 | 
				
			||||||
@ -115,7 +115,11 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
 | 
				
			|||||||
      Logger.error(`[ffmpegHelpers] Failed to download podcast episode with url "${podcastEpisodeDownload.url}"`, error)
 | 
					      Logger.error(`[ffmpegHelpers] Failed to download podcast episode with url "${podcastEpisodeDownload.url}"`, error)
 | 
				
			||||||
      return null
 | 
					      return null
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    if (!response) return resolve(false)
 | 
					    if (!response) {
 | 
				
			||||||
 | 
					      return resolve({
 | 
				
			||||||
 | 
					        success: false
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** @type {import('../libs/fluentFfmpeg/index').FfmpegCommand} */
 | 
					    /** @type {import('../libs/fluentFfmpeg/index').FfmpegCommand} */
 | 
				
			||||||
    const ffmpeg = Ffmpeg(response.data)
 | 
					    const ffmpeg = Ffmpeg(response.data)
 | 
				
			||||||
@ -177,7 +181,10 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
 | 
				
			|||||||
      if (stderrLines.length) {
 | 
					      if (stderrLines.length) {
 | 
				
			||||||
        Logger.error(`Full stderr dump for episode url "${podcastEpisodeDownload.url}": ${stderrLines.join('\n')}`)
 | 
					        Logger.error(`Full stderr dump for episode url "${podcastEpisodeDownload.url}": ${stderrLines.join('\n')}`)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      resolve(false)
 | 
					      resolve({
 | 
				
			||||||
 | 
					        success: false,
 | 
				
			||||||
 | 
					        isFfmpegError: true
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    ffmpeg.on('progress', (progress) => {
 | 
					    ffmpeg.on('progress', (progress) => {
 | 
				
			||||||
      let progressPercent = 0
 | 
					      let progressPercent = 0
 | 
				
			||||||
@ -189,7 +196,9 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
 | 
				
			|||||||
    })
 | 
					    })
 | 
				
			||||||
    ffmpeg.on('end', () => {
 | 
					    ffmpeg.on('end', () => {
 | 
				
			||||||
      Logger.debug(`[FfmpegHelpers] downloadPodcastEpisode: Complete`)
 | 
					      Logger.debug(`[FfmpegHelpers] downloadPodcastEpisode: Complete`)
 | 
				
			||||||
      resolve(podcastEpisodeDownload.targetPath)
 | 
					      resolve({
 | 
				
			||||||
 | 
					        success: true
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    ffmpeg.run()
 | 
					    ffmpeg.run()
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user