Skip to content

Commit df57f37

Browse files
Add support for upcoming livestream trailers
1 parent 4081d42 commit df57f37

File tree

4 files changed

+89
-36
lines changed

4 files changed

+89
-36
lines changed

src/renderer/helpers/api/local.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,17 @@ export async function getLocalVideoInfo(id) {
247247
const hasTrailer = info.has_trailer
248248
const trailerIsAgeRestricted = info.getTrailerInfo() === null
249249

250-
if (hasTrailer) {
251-
/** @type {import('youtubei.js').YTNodes.PlayerLegacyDesktopYpcTrailer} */
252-
const trailerScreen = info.playability_status.error_screen
253-
id = trailerScreen.video_id
250+
// upcoming videos can have trailers so we wont fetch the trailer if the original video is playable
251+
if (hasTrailer && info.playability_status.status !== 'OK') {
252+
if (info.playability_status.error_screen.type === 'PlayerLegacyDesktopYpcTrailer') {
253+
/** @type {import('youtubei.js').YTNodes.PlayerLegacyDesktopYpcTrailer} */
254+
const trailerScreen = info.playability_status.error_screen
255+
id = trailerScreen.video_id
256+
} else {
257+
/** @type {import('youtubei.js').YTNodes.YpcTrailer} */
258+
const trailerScreen = info.playability_status.error_screen
259+
id = trailerScreen.player_response.videoDetails.videoId
260+
}
254261
}
255262

256263
if ((info.playability_status.status === 'UNPLAYABLE' && (!hasTrailer || trailerIsAgeRestricted)) ||
@@ -263,9 +270,13 @@ export async function getLocalVideoInfo(id) {
263270
const iosInfo = await iosInnertube.getBasicInfo(id, 'iOS')
264271

265272
if (hasTrailer) {
273+
// don't override the timestamp of when the video will premiere for upcoming videos
274+
if (info.playability_status.status !== 'LIVE_STREAM_OFFLINE') {
275+
info.basic_info.start_timestamp = iosInfo.basic_info.start_timestamp
276+
}
277+
266278
info.playability_status = iosInfo.playability_status
267279
info.streaming_data = iosInfo.streaming_data
268-
info.basic_info.start_timestamp = iosInfo.basic_info.start_timestamp
269280
info.basic_info.duration = iosInfo.basic_info.duration
270281
info.captions = iosInfo.captions
271282
info.storyboards = iosInfo.storyboards

src/renderer/views/Watch/Watch.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ export default defineComponent({
123123
infoAreaSticky: true,
124124
blockVideoAutoplay: false,
125125
autoplayInterruptionTimeout: null,
126+
playabilityStatus: '',
126127

127128
onMountedRun: false,
128129

@@ -502,6 +503,7 @@ export default defineComponent({
502503
this.videoChapters = chapters
503504

504505
const playabilityStatus = result.playability_status
506+
this.playabilityStatus = playabilityStatus.status
505507

506508
// The apostrophe is intentionally that one (char code 8217), because that is the one YouTube uses
507509
const BOT_MESSAGE = 'Sign in to confirm you’re not a bot'
@@ -644,7 +646,9 @@ export default defineComponent({
644646
this.upcomingTimestamp = null
645647
this.upcomingTimeLeft = null
646648
}
647-
} else {
649+
}
650+
651+
if (!this.isUpcoming || (this.isUpcoming && this.playabilityStatus === 'OK')) {
648652
this.videoLengthSeconds = result.basic_info.duration
649653
if (result.streaming_data) {
650654
this.streamingDataExpiryDate = result.streaming_data.expires

src/renderer/views/Watch/Watch.scss

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,41 @@
2121
}
2222
}
2323

24+
.premiereDate {
25+
align-items: center;
26+
background-color: rgb(0 0 0 / 80%);
27+
border-radius: 5px;
28+
inset-block-end: 12px;
29+
color: #fff;
30+
display: flex;
31+
block-size: 60px;
32+
inset-inline-start: 12px;
33+
padding-block: 0;
34+
padding-inline: 12px;
35+
36+
.premiereIcon {
37+
float: var(--float-left-ltr-rtl-value);
38+
font-size: 25px;
39+
margin-block: 0;
40+
margin-inline: 12px;
41+
}
42+
43+
.premiereText {
44+
margin-block: 0;
45+
margin-inline: 12px;
46+
min-inline-size: 200px;
47+
48+
.premiereTextTimestamp {
49+
font-size: 0.85em;
50+
font-weight: bold;
51+
}
52+
}
53+
}
54+
55+
.trailer.premiereDate {
56+
margin-block-start: 8px;
57+
}
58+
2459
.videoLayout {
2560
@include dual-column-template;
2661

@@ -52,35 +87,7 @@
5287
}
5388

5489
.premiereDate {
55-
align-items: center;
56-
background-color: rgb(0 0 0 / 80%);
57-
border-radius: 5px;
58-
inset-block-end: 12px;
59-
color: #fff;
60-
display: flex;
61-
block-size: 60px;
62-
inset-inline-start: 12px;
63-
padding-block: 0;
64-
padding-inline: 12px;
6590
position: absolute;
66-
67-
.premiereIcon {
68-
float: var(--float-left-ltr-rtl-value);
69-
font-size: 25px;
70-
margin-block: 0;
71-
margin-inline: 12px;
72-
}
73-
74-
.premiereText {
75-
margin-block: 0;
76-
margin-inline: 12px;
77-
min-inline-size: 200px;
78-
79-
.premiereTextTimestamp {
80-
font-size: 0.85em;
81-
font-weight: bold;
82-
}
83-
}
8491
}
8592

8693
.errorContainer {

src/renderer/views/Watch/Watch.vue

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
>
1818
<div class="videoAreaMargin">
1919
<ft-shaka-video-player
20-
v-if="!isLoading && !isUpcoming && !errorMessage"
20+
v-if="!isLoading && (!isUpcoming || playabilityStatus === 'OK') && !errorMessage"
2121
ref="player"
2222
:manifest-src="manifestSrc"
2323
:manifest-mime-type="manifestMimeType"
@@ -42,7 +42,38 @@
4242
@toggle-theatre-mode="useTheatreMode = !useTheatreMode"
4343
/>
4444
<div
45-
v-if="!isLoading && (isUpcoming || errorMessage)"
45+
v-if="!isLoading && isUpcoming && playabilityStatus === 'OK'"
46+
class="trailer premiereDate"
47+
>
48+
<font-awesome-icon
49+
:icon="['fas', 'satellite-dish']"
50+
class="premiereIcon"
51+
/>
52+
<p
53+
v-if="upcomingTimestamp !== null"
54+
class="premiereText"
55+
>
56+
<span
57+
class="premiereTextTimeLeft"
58+
>
59+
{{ $t("Video.Premieres") }} {{ upcomingTimeLeft }}
60+
</span>
61+
<br>
62+
<span
63+
class="premiereTextTimestamp"
64+
>
65+
{{ upcomingTimestamp }}
66+
</span>
67+
</p>
68+
<p
69+
v-else
70+
class="premiereText"
71+
>
72+
{{ $t("Video.Starting soon, please refresh the page to check again") }}
73+
</p>
74+
</div>
75+
<div
76+
v-else-if="!isLoading && (isUpcoming || errorMessage)"
4677
class="videoPlayer"
4778
>
4879
<img

0 commit comments

Comments
 (0)