mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-03 14:20:50 +08:00
Merge pull request #464 from souvenp/feat/flac-tags
feat: flac tags support and optimize cover images
This commit is contained in:
@@ -32,12 +32,14 @@
|
||||
"electron-window-state": "^5.0.3",
|
||||
"express": "^4.18.2",
|
||||
"file-type": "^21.0.0",
|
||||
"flac-tagger": "^1.0.7",
|
||||
"font-list": "^1.5.1",
|
||||
"husky": "^9.1.7",
|
||||
"music-metadata": "^11.2.3",
|
||||
"netease-cloud-music-api-alger": "^4.26.1",
|
||||
"node-id3": "^0.2.9",
|
||||
"node-machine-id": "^1.1.12",
|
||||
"sharp": "^0.34.3",
|
||||
"vue-i18n": "^11.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -9,7 +9,8 @@ import * as mm from 'music-metadata';
|
||||
import * as NodeID3 from 'node-id3';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
|
||||
import { FlacTagMap, writeFlacTags } from 'flac-tagger';
|
||||
import sharp from 'sharp';
|
||||
import { getStore } from './config';
|
||||
|
||||
const MAX_CONCURRENT_DOWNLOADS = 3;
|
||||
@@ -386,7 +387,7 @@ async function downloadMusic(
|
||||
let formattedFilename = filename;
|
||||
if (songInfo) {
|
||||
// 准备替换变量
|
||||
const artistName = songInfo.ar?.map((a: any) => a.name).join('/') || '未知艺术家';
|
||||
const artistName = songInfo.ar?.map((a: any) => a.name).join('、') || '未知艺术家';
|
||||
const songName = songInfo.name || filename;
|
||||
const albumName = songInfo.al?.name || '未知专辑';
|
||||
|
||||
@@ -576,8 +577,39 @@ async function downloadMusic(
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
// 获取封面图片的buffer
|
||||
coverImageBuffer = Buffer.from(coverResponse.data);
|
||||
const originalCoverBuffer = Buffer.from(coverResponse.data);
|
||||
const TWO_MB = 2 * 1024 * 1024;
|
||||
// 检查图片大小是否超过2MB
|
||||
if (originalCoverBuffer.length > TWO_MB) {
|
||||
const originalSizeMB = (originalCoverBuffer.length / (1024 * 1024)).toFixed(2);
|
||||
console.log(`封面图大于2MB (${originalSizeMB} MB),开始压缩...`);
|
||||
try {
|
||||
// 使用 sharp 进行压缩
|
||||
coverImageBuffer = await sharp(originalCoverBuffer)
|
||||
.resize({
|
||||
width: 1600,
|
||||
height: 1600,
|
||||
fit: 'inside',
|
||||
withoutEnlargement: true
|
||||
})
|
||||
.jpeg({
|
||||
quality: 80,
|
||||
mozjpeg: true
|
||||
})
|
||||
.toBuffer();
|
||||
|
||||
const compressedSizeMB = (coverImageBuffer.length / (1024 * 1024)).toFixed(2);
|
||||
console.log(`封面图压缩完成,新大小: ${compressedSizeMB} MB`);
|
||||
|
||||
} catch (compressionError) {
|
||||
console.error('封面图压缩失败,将使用原图:', compressionError);
|
||||
coverImageBuffer = originalCoverBuffer; // 如果压缩失败,则回退使用原始图片
|
||||
}
|
||||
} else {
|
||||
// 如果图片不大于2MB,直接使用原图
|
||||
coverImageBuffer = originalCoverBuffer;
|
||||
}
|
||||
|
||||
console.log('封面已准备好,将写入元数据');
|
||||
}
|
||||
}
|
||||
@@ -588,7 +620,7 @@ async function downloadMusic(
|
||||
|
||||
const fileFormat = fileExtension.toLowerCase();
|
||||
const artistNames =
|
||||
(songInfo?.ar || songInfo?.song?.artists)?.map((a: any) => a.name).join('/ ') || '未知艺术家';
|
||||
(songInfo?.ar || songInfo?.song?.artists)?.map((a: any) => a.name).join('、') || '未知艺术家';
|
||||
|
||||
// 根据文件类型处理元数据
|
||||
if (['.mp3'].includes(fileFormat)) {
|
||||
@@ -598,7 +630,7 @@ async function downloadMusic(
|
||||
NodeID3.removeTags(finalFilePath);
|
||||
|
||||
const tags = {
|
||||
title: filename,
|
||||
title: songInfo?.name,
|
||||
artist: artistNames,
|
||||
TPE1: artistNames,
|
||||
TPE2: artistNames,
|
||||
@@ -634,10 +666,35 @@ async function downloadMusic(
|
||||
} catch (err) {
|
||||
console.error('Error writing ID3 tags:', err);
|
||||
}
|
||||
} else {
|
||||
// 对于非MP3文件,使用music-metadata来写入元数据可能需要专门的库
|
||||
// 或者根据不同文件类型使用专用工具,暂时只记录但不处理
|
||||
console.log(`文件类型 ${fileFormat} 不支持使用NodeID3写入标签,跳过元数据写入`);
|
||||
} else if (['.flac'].includes(fileFormat)) {
|
||||
try {
|
||||
const tagMap: FlacTagMap = {
|
||||
TITLE: songInfo?.name,
|
||||
ARTIST: artistNames,
|
||||
ALBUM: songInfo?.al?.name || songInfo?.song?.album?.name || songInfo?.name || filename,
|
||||
LYRICS: lyricsContent || '',
|
||||
TRACKNUMBER: songInfo?.no ? String(songInfo.no) : undefined,
|
||||
DATE: songInfo?.publishTime
|
||||
? new Date(songInfo.publishTime).getFullYear().toString()
|
||||
: undefined
|
||||
};
|
||||
|
||||
await writeFlacTags(
|
||||
{
|
||||
tagMap,
|
||||
picture: coverImageBuffer
|
||||
? {
|
||||
buffer: coverImageBuffer,
|
||||
mime: 'image/jpeg'
|
||||
}
|
||||
: undefined
|
||||
},
|
||||
finalFilePath
|
||||
);
|
||||
console.log('FLAC tags written successfully');
|
||||
} catch (err) {
|
||||
console.error('Error writing FLAC tags:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存下载信息
|
||||
@@ -683,7 +740,7 @@ async function downloadMusic(
|
||||
// 发送桌面通知
|
||||
try {
|
||||
const artistNames =
|
||||
(songInfo?.ar || songInfo?.song?.artists)?.map((a: any) => a.name).join('/') ||
|
||||
(songInfo?.ar || songInfo?.song?.artists)?.map((a: any) => a.name).join('、') ||
|
||||
'未知艺术家';
|
||||
const notification = new Notification({
|
||||
title: '下载完成',
|
||||
|
||||
Reference in New Issue
Block a user