fix(backend): keep the saved cover art at full resolution
Search results now carry a small thumbnail, so the artwork downloaded when a YouTube track is saved would have shrunk with them. The URL is upsized to the configured artwork resolution right before the download event goes out.
This commit is contained in:
@@ -54,7 +54,8 @@
|
|||||||
"SearchContinuationCacheSeconds": 600,
|
"SearchContinuationCacheSeconds": 600,
|
||||||
"SearchResultsCacheSeconds": 900,
|
"SearchResultsCacheSeconds": 900,
|
||||||
"SongInfoCacheSeconds": 86400,
|
"SongInfoCacheSeconds": 86400,
|
||||||
"ThumbnailSize": 240
|
"ThumbnailSize": 240,
|
||||||
|
"ArtworkSize": 544
|
||||||
},
|
},
|
||||||
"PlayList": {
|
"PlayList": {
|
||||||
"Routes": {
|
"Routes": {
|
||||||
|
|||||||
@@ -27,5 +27,7 @@ namespace Musify.Application.Contracts
|
|||||||
Task<ErrorOr<YouTubeStreamInfo>> GetAudioStreamAsync(string videoId, CancellationToken cancellationToken);
|
Task<ErrorOr<YouTubeStreamInfo>> GetAudioStreamAsync(string videoId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
Task<ErrorOr<YouTubeSongResult>> GetSongAsync(string videoId, CancellationToken cancellationToken);
|
Task<ErrorOr<YouTubeSongResult>> GetSongAsync(string videoId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
string ResolveArtworkUrl(string thumbnailUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,13 +111,13 @@ namespace Musify.Application.PlayLists
|
|||||||
private async Task<ErrorOr<string>> ResolveThumbnailUrlAsync(string videoId, YouTubeSongResult? song, CancellationToken cancellationToken)
|
private async Task<ErrorOr<string>> ResolveThumbnailUrlAsync(string videoId, YouTubeSongResult? song, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(song?.ThumbnailUrl))
|
if (!string.IsNullOrEmpty(song?.ThumbnailUrl))
|
||||||
return song.ThumbnailUrl;
|
return youTubeMusicService.ResolveArtworkUrl(song.ThumbnailUrl);
|
||||||
|
|
||||||
var songResult = await youTubeMusicService.GetSongAsync(videoId, cancellationToken);
|
var songResult = await youTubeMusicService.GetSongAsync(videoId, cancellationToken);
|
||||||
if (songResult.IsError)
|
if (songResult.IsError)
|
||||||
return songResult.Errors;
|
return songResult.Errors;
|
||||||
|
|
||||||
return songResult.Value.ThumbnailUrl;
|
return youTubeMusicService.ResolveArtworkUrl(songResult.Value.ThumbnailUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PublishDownloadEventAsync(Guid trackId, string videoId, string thumbnailUrl, CancellationToken cancellationToken)
|
private async Task PublishDownloadEventAsync(Guid trackId, string videoId, string thumbnailUrl, CancellationToken cancellationToken)
|
||||||
|
|||||||
@@ -23,5 +23,8 @@ namespace Musify.Infrastructure.Configuration
|
|||||||
|
|
||||||
[Range(32, 720)]
|
[Range(32, 720)]
|
||||||
public int ThumbnailSize { get; set; } = 240;
|
public int ThumbnailSize { get; set; } = 240;
|
||||||
|
|
||||||
|
[Range(120, 1080)]
|
||||||
|
public int ArtworkSize { get; set; } = 544;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,6 +160,9 @@ namespace Musify.Infrastructure.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string ResolveArtworkUrl(string thumbnailUrl) =>
|
||||||
|
YouTubeThumbnail.WithSize(thumbnailUrl, configuration.ArtworkSize);
|
||||||
|
|
||||||
private string PickThumbnail(IEnumerable<YouTubeMusicAPI.Models.Thumbnail> thumbnails)
|
private string PickThumbnail(IEnumerable<YouTubeMusicAPI.Models.Thumbnail> thumbnails)
|
||||||
{
|
{
|
||||||
var ordered = thumbnails.OrderBy(thumbnail => thumbnail.Width).ToList();
|
var ordered = thumbnails.OrderBy(thumbnail => thumbnail.Width).ToList();
|
||||||
|
|||||||
@@ -25,6 +25,17 @@ API_BASE_URL=http://localhost:5111
|
|||||||
# Dev already allows a plain-HTTP issuer. Set this only to allow it in a production build (never with a public issuer).
|
# Dev already allows a plain-HTTP issuer. Set this only to allow it in a production build (never with a public issuer).
|
||||||
# AUTH_ALLOW_INSECURE_HTTP=true
|
# AUTH_ALLOW_INSECURE_HTTP=true
|
||||||
|
|
||||||
|
# Optional tuning for the YouTube artwork proxy (/api/youtube/thumbnail),
|
||||||
|
# which caches the covers in memory so the browser never hits Google directly.
|
||||||
|
# THUMBNAIL_CACHE_MAX_AGE_SECONDS=2592000
|
||||||
|
# THUMBNAIL_FAILURE_CACHE_SECONDS=300
|
||||||
|
# THUMBNAIL_CACHE_BYTES=134217728
|
||||||
|
# THUMBNAIL_MAX_CONCURRENT_FETCHES=4
|
||||||
|
# THUMBNAIL_FETCH_TIMEOUT_MS=8000
|
||||||
|
# THUMBNAIL_COOLDOWN_SECONDS=30
|
||||||
|
# THUMBNAIL_MAX_COOLDOWN_SECONDS=300
|
||||||
|
# THUMBNAIL_MAX_SIZE=720
|
||||||
|
|
||||||
# Where to send presigned S3 PUTs when the public S3 host is not reachable from
|
# Where to send presigned S3 PUTs when the public S3 host is not reachable from
|
||||||
# the server (in Docker: http://seaweedfs:8333). The signed Host header is kept
|
# the server (in Docker: http://seaweedfs:8333). The signed Host header is kept
|
||||||
# either way. Defaults to the host in the presigned URL.
|
# either way. Defaults to the host in the presigned URL.
|
||||||
|
|||||||
Reference in New Issue
Block a user