fix: stop the YouTube covers coming out blurry and cropped

The ytimg variants are 16:9, so picking one by width handed a square tile far
fewer pixels than it needed: a 96px cover got the 120x90 file and kept 90px
after the crop. They are chosen by their short side now, the album art is
preferred over the video frame when the search returns both, and the display
sizes account for the tiles being up to 180px on a 2x screen.
This commit is contained in:
2026-07-20 19:05:44 +02:00
parent 75c08f2a6c
commit 8c62faa822
4 changed files with 17 additions and 11 deletions
@@ -167,8 +167,11 @@ namespace Musify.Infrastructure.Services
{
var ordered = thumbnails.OrderBy(thumbnail => thumbnail.Width).ToList();
var chosen = ordered.FirstOrDefault(thumbnail => thumbnail.Width >= configuration.ThumbnailSize)
?? ordered.LastOrDefault();
var square = ordered.Where(thumbnail => YouTubeThumbnail.IsSquare(thumbnail.Url)).ToList();
var candidates = square.Count > 0 ? square : ordered;
var chosen = candidates.FirstOrDefault(thumbnail => thumbnail.Width >= configuration.ThumbnailSize)
?? candidates.LastOrDefault();
return chosen is null
? string.Empty
@@ -2,6 +2,9 @@ namespace Musify.Infrastructure.Services
{
public static class YouTubeThumbnail
{
public static bool IsSquare(string url) =>
url.Contains("googleusercontent.com", StringComparison.OrdinalIgnoreCase);
public static string WithSize(string url, int size)
{
if (string.IsNullOrEmpty(url))
@@ -40,9 +43,9 @@ namespace Musify.Infrastructure.Services
private static string YtImgFileName(int size) => size switch
{
<= 120 => "default.jpg",
<= 320 => "mqdefault.jpg",
<= 480 => "hqdefault.jpg",
<= 90 => "default.jpg",
<= 180 => "mqdefault.jpg",
<= 360 => "hqdefault.jpg",
_ => "maxresdefault.jpg"
};
+3 -3
View File
@@ -55,9 +55,9 @@ export function resizeThumbnailUrl(url: URL, size: number): string {
}
function ytImgFileName(size: number): string {
if (size <= 120) return 'default.jpg';
if (size <= 320) return 'mqdefault.jpg';
if (size <= 480) return 'hqdefault.jpg';
if (size <= 90) return 'default.jpg';
if (size <= 180) return 'mqdefault.jpg';
if (size <= 360) return 'hqdefault.jpg';
return 'maxresdefault.jpg';
}
+3 -3
View File
@@ -1,7 +1,7 @@
export const THUMBNAIL_SIZES = {
small: 96,
medium: 160,
large: 320
small: 128,
medium: 192,
large: 360
} as const;
export type ThumbnailSize = keyof typeof THUMBNAIL_SIZES;