Skip to content

Commit e231e4d

Browse files
committed
Cleanup shorts duration parsing now that YouTube has removed it (#4509)
1 parent b4ebca9 commit e231e4d

File tree

3 files changed

+12
-67
lines changed

3 files changed

+12
-67
lines changed

src/renderer/components/ft-list-video/ft-list-video.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export default defineComponent({
6464
viewCount: 0,
6565
parsedViewCount: '',
6666
uploadedTime: '',
67+
lengthSeconds: 0,
6768
duration: '',
6869
description: '',
6970
watched: false,
@@ -156,7 +157,11 @@ export default defineComponent({
156157
},
157158

158159
progressPercentage: function () {
159-
return (this.watchProgress / this.data.lengthSeconds) * 100
160+
if (typeof this.lengthSeconds !== 'number') {
161+
return 0
162+
}
163+
164+
return (this.watchProgress / this.lengthSeconds) * 100
160165
},
161166

162167
hideSharingActions: function() {
@@ -445,9 +450,11 @@ export default defineComponent({
445450
this.channelName = this.data.author ?? null
446451
this.channelId = this.data.authorId ?? null
447452

448-
if (this.data.isRSS && this.historyEntryExists) {
453+
if ((this.data.lengthSeconds === '' || this.data.lengthSeconds === '0:00') && this.historyEntryExists) {
454+
this.lengthSeconds = this.historyEntry.lengthSeconds
449455
this.duration = formatDurationAsTimestamp(this.historyEntry.lengthSeconds)
450456
} else {
457+
this.lengthSeconds = this.data.lengthSeconds
451458
this.duration = formatDurationAsTimestamp(this.data.lengthSeconds)
452459
}
453460

src/renderer/components/ft-list-video/ft-list-video.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
>
2929
</router-link>
3030
<div
31-
v-if="isLive || duration !== '0:00'"
31+
v-if="isLive || isUpcoming || (duration !== '' && duration !== '0:00')"
3232
class="videoDuration"
3333
:class="{
3434
live: isLive,

src/renderer/helpers/api/local.js

Lines changed: 2 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -526,77 +526,18 @@ export function parseLocalChannelVideos(videos, channelId, channelName) {
526526
*/
527527
export function parseLocalChannelShorts(shorts, channelId, channelName) {
528528
return shorts.map(short => {
529-
// unfortunately the only place with the duration is the accesibility string
530-
const duration = parseShortDuration(short.accessibility_label, short.id)
531-
532529
return {
533530
type: 'video',
534531
videoId: short.id,
535532
title: short.title.text,
536533
author: channelName,
537534
authorId: channelId,
538535
viewCount: parseLocalSubscriberCount(short.views.text),
539-
lengthSeconds: isNaN(duration) ? '' : duration
536+
lengthSeconds: ''
540537
}
541538
})
542539
}
543540

544-
/**
545-
* Shorts can only be up to 60 seconds long, so we only need to handle seconds and minutes
546-
* Of course this is YouTube, so are edge cases that don't match the docs, like example 3 taken from LTT
547-
*
548-
* https://support.google.com/youtube/answer/10059070?hl=en
549-
*
550-
* Example input strings:
551-
* - These mice keep getting WEIRDER... - 59 seconds - play video
552-
* - How Low Can Our Resolution Go? - 1 minute - play video
553-
* - I just found out about Elon. #SHORTS - 1 minute, 1 second - play video
554-
* @param {string} accessibilityLabel
555-
* @param {string} videoId only used for error logging
556-
*/
557-
function parseShortDuration(accessibilityLabel, videoId) {
558-
// we want to count from the end of the array,
559-
// as it's possible that the title could contain a `-` too
560-
const timeString = accessibilityLabel.split('-').at(-2)
561-
562-
if (typeof timeString === 'undefined') {
563-
console.error(`Failed to parse local API short duration from accessibility label. video ID: ${videoId}, text: "${accessibilityLabel}"`)
564-
return NaN
565-
}
566-
567-
let duration = 0
568-
569-
const matches = timeString.matchAll(/(\d+) (second|minute)s?/g)
570-
571-
// matchAll returns an iterator, which doesn't have a length property
572-
// so we need to check if it's empty this way instead
573-
let validDuration = false
574-
575-
for (const match of matches) {
576-
let number = parseInt(match[1])
577-
578-
if (isNaN(number) || match[2].length === 0) {
579-
validDuration = false
580-
break
581-
}
582-
583-
validDuration = true
584-
585-
if (match[2] === 'minute') {
586-
number *= 60
587-
}
588-
589-
duration += number
590-
}
591-
592-
if (!validDuration) {
593-
console.error(`Failed to parse local API short duration from accessibility label. video ID: ${videoId}, text: "${accessibilityLabel}"`)
594-
return NaN
595-
}
596-
597-
return duration
598-
}
599-
600541
/**
601542
* @typedef {import('youtubei.js').YTNodes.Playlist} Playlist
602543
* @typedef {import('youtubei.js').YTNodes.GridPlaylist} GridPlaylist
@@ -678,15 +619,12 @@ export function parseLocalPlaylistVideo(video) {
678619
/** @type {import('youtubei.js').YTNodes.ReelItem} */
679620
const short = video
680621

681-
// unfortunately the only place with the duration is the accesibility string
682-
const duration = parseShortDuration(video.accessibility_label, short.id)
683-
684622
return {
685623
type: 'video',
686624
videoId: short.id,
687625
title: short.title.text,
688626
viewCount: parseLocalSubscriberCount(short.views.text),
689-
lengthSeconds: isNaN(duration) ? '' : duration
627+
lengthSeconds: ''
690628
}
691629
} else {
692630
/** @type {import('youtubei.js').YTNodes.PlaylistVideo} */

0 commit comments

Comments
 (0)