feat: 歌手头像 —— 下载时写入 artist.jpg、曲库批量补全、无头像时用专辑封面拼图
- 按「歌手/专辑」下载时,歌手目录没有图片则保存歌手头像(合辑不写) - 曲库页列出缺少头像的歌手文件夹,一键从网易云 / QQ 音乐按名字精确匹配补全 - 网易云头像缩到 600×600,避免原图数 MB - 仍无头像的文件夹显示前 4 张专辑封面拼图 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,17 @@ export interface DownloadOptions {
|
||||
|
||||
const TAG_OVERHEAD_MAX = 8 * 1024 * 1024;
|
||||
|
||||
/** 文件夹封面 / 歌手头像的常见文件名(曲库页按此顺序取图) */
|
||||
export const FOLDER_IMAGES = ['artist.jpg', 'folder.jpg', 'cover.jpg', 'cover.png', 'artist.png'];
|
||||
|
||||
export async function hasFolderImage(dir: string): Promise<boolean> {
|
||||
for (const name of FOLDER_IMAGES) {
|
||||
const stat = await fs.promises.stat(path.join(dir, name)).catch(() => null);
|
||||
if (stat?.size) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export type Stage ='resolve' | 'metadata' | 'download' | 'lyric' | 'cover' | 'tag';
|
||||
|
||||
export interface Reporter {
|
||||
@@ -151,6 +162,15 @@ async function downloadOnce(provider: MusicProvider, id: string, opts: DownloadO
|
||||
if (!stat?.size) await fs.promises.writeFile(coverPath, cover);
|
||||
}
|
||||
|
||||
// 歌手目录还没有头像时写入 artist.jpg(合辑「群星」不写)
|
||||
if (wantAlbumCover && meta?.albumArtistImage && !meta.compilation) {
|
||||
const artistDir = path.dirname(target.dir);
|
||||
if (!(await hasFolderImage(artistDir))) {
|
||||
const avatar = await fetchBuffer(meta.albumArtistImage, { signal }).catch(() => null);
|
||||
if (avatar?.length) await fs.promises.writeFile(path.join(artistDir, 'artist.jpg'), avatar);
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.embedTags) {
|
||||
reporter?.stage?.('tag', '写入标签');
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user