From c150ed4e989a668501edfffad6b0754c501d35df Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 19 Jun 2025 17:14:56 -0500 Subject: [PATCH 1/2] Update view episode modal to include duration & episode feed modal to include duration & size --- client/components/modals/podcast/EpisodeFeed.vue | 9 ++++++++- client/components/modals/podcast/ViewEpisode.vue | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/client/components/modals/podcast/EpisodeFeed.vue b/client/components/modals/podcast/EpisodeFeed.vue index 7ec14ccd..e62342af 100644 --- a/client/components/modals/podcast/EpisodeFeed.vue +++ b/client/components/modals/podcast/EpisodeFeed.vue @@ -35,7 +35,14 @@

{{ episode.subtitle }}

-

Published {{ episode.publishedAt ? $dateDistanceFromNow(episode.publishedAt) : 'Unknown' }}

+
+ +

Published {{ episode.publishedAt ? $dateDistanceFromNow(episode.publishedAt) : 'Unknown' }}

+ +

{{ $strings.LabelDuration }}: {{ $elapsedPretty(Number(episode.duration)) }}

+ +

{{ $strings.LabelSize }}: {{ $bytesPretty(Number(episode.enclosure.length)) }}

+
diff --git a/client/components/modals/podcast/ViewEpisode.vue b/client/components/modals/podcast/ViewEpisode.vue index b4358c5d..2502a5ea 100644 --- a/client/components/modals/podcast/ViewEpisode.vue +++ b/client/components/modals/podcast/ViewEpisode.vue @@ -34,6 +34,12 @@ {{ audioFileSize }}

+
+

{{ $strings.LabelDuration }}

+

+ {{ audioFileDuration }} +

+
@@ -90,6 +96,10 @@ export default { return this.$bytesPretty(size) }, + audioFileDuration() { + const duration = this.episode.duration || 0 + return this.$elapsedPretty(duration) + }, bookCoverAspectRatio() { return this.$store.getters['libraries/getBookCoverAspectRatio'] } From 7b92c15a465fa6eae62145250d5c6709a2dda1b7 Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 19 Jun 2025 17:28:21 -0500 Subject: [PATCH 2/2] Include durationSeconds on RSS podcast episode parsed from duration --- client/components/modals/podcast/EpisodeFeed.vue | 2 +- server/utils/podcastUtils.js | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/components/modals/podcast/EpisodeFeed.vue b/client/components/modals/podcast/EpisodeFeed.vue index e62342af..6b99cee7 100644 --- a/client/components/modals/podcast/EpisodeFeed.vue +++ b/client/components/modals/podcast/EpisodeFeed.vue @@ -39,7 +39,7 @@

Published {{ episode.publishedAt ? $dateDistanceFromNow(episode.publishedAt) : 'Unknown' }}

-

{{ $strings.LabelDuration }}: {{ $elapsedPretty(Number(episode.duration)) }}

+

{{ $strings.LabelDuration }}: {{ $elapsedPretty(episode.durationSeconds) }}

{{ $strings.LabelSize }}: {{ $bytesPretty(Number(episode.enclosure.length)) }}

diff --git a/server/utils/podcastUtils.js b/server/utils/podcastUtils.js index 12469160..b62e024f 100644 --- a/server/utils/podcastUtils.js +++ b/server/utils/podcastUtils.js @@ -25,6 +25,7 @@ const Fuse = require('../libs/fusejs') * @property {string} episode * @property {string} author * @property {string} duration + * @property {number|null} durationSeconds - Parsed from duration string if duration is valid * @property {string} explicit * @property {number} publishedAt - Unix timestamp * @property {{ url: string, type?: string, length?: string }} enclosure @@ -217,8 +218,9 @@ function extractEpisodeData(item) { }) // Extract psc:chapters if duration is set - let episodeDuration = !isNaN(episode.duration) ? timestampToSeconds(episode.duration) : null - if (item['psc:chapters']?.[0]?.['psc:chapter']?.length && episodeDuration) { + episode.durationSeconds = episode.duration ? timestampToSeconds(episode.duration) : null + + if (item['psc:chapters']?.[0]?.['psc:chapter']?.length && episode.durationSeconds) { // Example chapter: // {"id":0,"start":0,"end":43.004286,"title":"chapter 1"} @@ -244,7 +246,7 @@ function extractEpisodeData(item) { } else { episode.chapters = cleanedChapters.map((chapter, index) => { const nextChapter = cleanedChapters[index + 1] - const end = nextChapter ? nextChapter.start : episodeDuration + const end = nextChapter ? nextChapter.start : episode.durationSeconds return { id: chapter.id, title: chapter.title, @@ -273,6 +275,7 @@ function cleanEpisodeData(data) { episode: data.episode || '', author: data.author || '', duration: data.duration || '', + durationSeconds: data.durationSeconds || null, explicit: data.explicit || '', publishedAt, enclosure: data.enclosure,