Channel rail: sharp season posters (maxres thumbnail, was a cropped hqdefault)

The rail 'season poster' is a video thumbnail shown in a 2:3 portrait slot
(object-fit: cover), but InnerTube hands us hqdefault (480x360, often sqp-shrunk)
— so it got crop-zoomed and looked soft. Now the poster pulls maxresdefault
(1280x720; ~300KB vs ~23KB) via the image proxy, with a fallback chain
(maxres → original thumbnail → hide) so videos without a maxres thumb still
render. Only the big rail poster is upgraded; the small episode stills already
downscale crisply.
video
BoulderBadgeDad 2 weeks ago
parent cb5ae93f76
commit eb8f803c36

@ -902,7 +902,14 @@
return '<div class="vd-rail">' + data.seasons.map(function (s) {
var art = seasonArt(s), p = pct(s);
var on = s.season_number === selectedSeason ? ' vd-rcard--active' : '';
var img = art ? '<img class="vd-rcard-img" src="' + art + '" alt="" loading="lazy" onerror="this.style.display=\'none\'">' : '';
// YouTube posters carry a lower-res fallback (maxres → original) so a
// missing maxresdefault.jpg downgrades instead of vanishing.
var fb = (s.poster_fallback && s.poster_fallback !== art) ? s.poster_fallback : '';
var oe = fb
? 'var f=this.getAttribute(\'data-fb\');if(f){this.removeAttribute(\'data-fb\');this.src=f;}else{this.style.display=\'none\';}'
: 'this.style.display=\'none\'';
var img = art ? '<img class="vd-rcard-img" src="' + art + '" alt="" loading="lazy"' +
(fb ? ' data-fb="' + esc(fb) + '"' : '') + ' onerror="' + oe + '">' : '';
return '<button class="vd-rcard' + on + '" type="button" data-vd-season="' + s.season_number + '">' +
'<div class="vd-rcard-art">' + img + '<div class="vd-rcard-fb">📺</div>' +
'<div class="vd-rcard-grad"></div><div class="vd-rcard-pct">' + p + '%</div></div>' +
@ -1331,6 +1338,12 @@
var ytSearchTimer = null;
function ytProx(u) { return (window.VideoYoutube && u) ? VideoYoutube.img(u) : (u || ''); }
// Upgrade an i.ytimg thumbnail to maxresdefault (1280×720) for the big rail
// poster — hqdefault (480×360, often sqp-shrunk) looks soft cropped to 2:3.
function ytHiRes(u) {
var m = /\/vi\/([^/?]+)\//.exec(u || '');
return m ? 'https://i.ytimg.com/vi/' + m[1] + '/maxresdefault.jpg' : (u || '');
}
function ytEpisodeOf(v, i) {
return { episode_number: i + 1, title: v.title, overview: v.description || '',
@ -1355,12 +1368,14 @@
var x = a.published_at || '', y = b.published_at || '';
return asc ? (x < y ? -1 : x > y ? 1 : 0) : (x > y ? -1 : x < y ? 1 : 0);
});
var poster = '';
for (var k = 0; k < vids.length; k++) { if (vids[k].thumbnail_url) { poster = ytProx(vids[k].thumbnail_url); break; } }
var thumb = '';
for (var k = 0; k < vids.length; k++) { if (vids[k].thumbnail_url) { thumb = vids[k].thumbnail_url; break; } }
var poster = thumb ? ytProx(ytHiRes(thumb)) : ''; // maxres for the rail card
var eps = vids.map(ytEpisodeOf);
var wishedN = eps.filter(function (e) { return e.owned; }).length;
var label = yr ? String(yr) : (years.length === 1 ? 'All Videos' : 'Earlier videos');
return { season_number: yr, title: label, poster_url: poster || ytProx(ch.avatar_url),
poster_fallback: thumb ? ytProx(thumb) : '', // ← if maxres 404s
episode_owned: wishedN, episode_total: eps.length, episodes: eps };
});
}

Loading…
Cancel
Save