-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathyoutube-setup.js
More file actions
202 lines (183 loc) · 7.14 KB
/
Copy pathyoutube-setup.js
File metadata and controls
202 lines (183 loc) · 7.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// youtube-setup.js
let youtubePlayer;
let apiReady = false;
// Preload YouTube API faster
(function() {
const tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
tag.async = true;
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
})();
// Called by the YouTube IFrame API when it's ready.
function onYouTubeIframeAPIReady() {
apiReady = true;
// First check if the player container exists
const playerContainer = document.getElementById('youtube-player');
if (!playerContainer) {
// Try to create it if missing
const section1 = document.getElementById('section1');
if (section1) {
const videoBackground = section1.querySelector('.video-background');
if (videoBackground) {
const playerDiv = document.createElement('div');
playerDiv.id = 'youtube-player';
videoBackground.appendChild(playerDiv);
}
}
}
// Try again to find the container
if (!document.getElementById('youtube-player')) {
return;
}
// Check for mobile devices or low bandwidth signal set by the Channel 1 module
const isMobile = window.innerWidth <= 600;
const optimizedMode = window.useLowQualityVideo || document.querySelector('.video-background[data-optimized="true"]');
const section1 = document.getElementById('section1');
const videoBackground = section1 ? section1.querySelector('.video-background') : null;
let handoffTimer;
const ensureChromeVeil = () => {
if (!videoBackground) return null;
let veil = videoBackground.querySelector('.youtube-chrome-veil');
if (!veil) {
veil = document.createElement('div');
veil.className = 'youtube-chrome-veil';
veil.setAttribute('aria-hidden', 'true');
videoBackground.appendChild(veil);
}
return veil;
};
const veilLoopHandoff = (duration = 520) => {
if (!videoBackground || !ensureChromeVeil()) return;
window.clearTimeout(handoffTimer);
videoBackground.classList.add('is-loop-handoff');
handoffTimer = window.setTimeout(() => {
videoBackground.classList.remove('is-loop-handoff');
}, duration);
};
// Determine optimal quality based on device and connection
let suggestedQuality = 'hd720'; // Default quality
if (isMobile || optimizedMode) {
suggestedQuality = 'small'; // Lower quality for mobile/low bandwidth
}
youtubePlayer = new YT.Player('youtube-player', {
videoId: 'KISNE4qOIBM', // Original video ID
width: '100%',
height: '100%',
playerVars: {
autoplay: 1,
controls: 0,
loop: 1,
playlist: 'KISNE4qOIBM', // Required for looping the same video
modestbranding: 1,
rel: 0,
playsinline: 1, // Important for iOS
fs: 0,
showinfo: 0,
iv_load_policy: 3,
disablekb: 1,
cc_load_policy: 0,
vq: suggestedQuality, // Suggest initial quality level
enablejsapi: 1, // Enable JS API for better control
origin: window.location.origin // Specify origin for faster loading
},
events: {
onReady: event => {
// Mute the video initially to allow autoplay.
event.target.mute();
event.target.playVideo();
ensureChromeVeil();
// Set quality level based on device type
if (isMobile || optimizedMode) {
event.target.setPlaybackQuality('small');
}
// Mobile autoplay is restricted; iOS requires user interaction for unmuted playback.
// Muted autoplay is already attempted above. Retry once, then defer to touch.
if (isMobile) {
const retryOnce = () => {
if (event.target.getPlayerState() !== YT.PlayerState.PLAYING) {
event.target.playVideo();
}
};
setTimeout(retryOnce, 800);
const attemptOnTouch = () => {
event.target.playVideo();
document.removeEventListener('touchstart', attemptOnTouch);
};
document.addEventListener('touchstart', attemptOnTouch, { once: true, passive: true });
}
// Apply styles to containing divs
if (section1) {
if (videoBackground) {
videoBackground.style.position = 'absolute';
videoBackground.style.top = '0';
videoBackground.style.left = '0';
videoBackground.style.width = '100%';
videoBackground.style.height = '100%';
videoBackground.style.zIndex = '-1';
videoBackground.style.overflow = 'hidden';
}
}
// Adjust the iframe size after a shorter delay for faster loading
setTimeout(() => {
const iframe = document.querySelector('#youtube-player iframe');
if (iframe) {
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.position = 'absolute';
iframe.style.top = '50%';
iframe.style.left = '50%';
// Overscan/crop the YouTube frame so native chrome and watermarks stay off the TV surface.
iframe.style.transform = 'translate(-50%, -50%) scale(1.36)';
iframe.style.willChange = 'transform'; // Optimize for animations
} else {
}
}, 200); // Reduced from 500ms to 200ms
},
onStateChange: event => {
// Keep CH01 feeling like authored signal, not a web player. If YouTube
// exposes native chrome during a pause/end handoff, veil that moment as
// broadcast flicker while the underlying player recovers.
if (event.data === YT.PlayerState.PAUSED) {
veilLoopHandoff(520);
event.target.playVideo();
return;
}
if (event.data !== YT.PlayerState.ENDED) return;
veilLoopHandoff(720);
// Only recover if the native loop actually stalls after the handoff.
setTimeout(() => {
if (event.target.getPlayerState && event.target.getPlayerState() === YT.PlayerState.ENDED) {
event.target.seekTo(0, true);
event.target.playVideo();
}
}, 1200);
},
onError: event => {
// On error, apply an optimized fallback background quickly
const section1 = document.getElementById('section1');
if (section1) {
const videoBackground = section1.querySelector('.video-background');
if (videoBackground) {
// Use a smoother fallback transition
videoBackground.style.transition = 'opacity 0.3s ease-in-out';
videoBackground.style.background = "#000000 url('visuals/static.gif') center center repeat";
videoBackground.style.backgroundSize = 'cover';
videoBackground.style.opacity = '0.8';
}
}
}
}
});
}
// Unmute the video on user interaction (e.g., clicking the power button)
document.addEventListener('DOMContentLoaded', () => {
const powerButton = document.getElementById('powerButton');
if (powerButton) {
powerButton.addEventListener('click', () => {
if (youtubePlayer && typeof youtubePlayer.unMute === 'function') {
youtubePlayer.unMute();
}
});
}
});