Compare commits

...

2 Commits

Author SHA1 Message Date
nullptr-0 c3a1fbd24d always use multiple artists in meta 2023-08-29 14:56:37 +08:00
nullptr-0 c972b66aa2 add build outDir to fix error in tsconfig.json 2023-08-29 14:56:22 +08:00
15 changed files with 32 additions and 27 deletions

View File

@ -14,7 +14,7 @@
</el-table-column> </el-table-column>
<el-table-column label="歌手"> <el-table-column label="歌手">
<template #default="scope"> <template #default="scope">
<p>{{ scope.row.artist }}</p> <p>{{ scope.row.artist.join('/') }}</p>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="专辑"> <el-table-column label="专辑">

View File

@ -21,7 +21,7 @@ describe('decrypt/joox', () => {
title: 'unused', title: 'unused',
album: 'unused', album: 'unused',
blob: blob, blob: blob,
artist: 'unused', artist: ['unused'],
imgUrl: 'https://example.unlock-music.dev/', imgUrl: 'https://example.unlock-music.dev/',
}; };
}); });

View File

@ -1,7 +1,7 @@
export interface DecryptResult { export interface DecryptResult {
title: string; title: string;
album?: string; album?: string;
artist?: string; artist?: string[];
mime: string; mime: string;
ext: string; ext: string;

View File

@ -43,7 +43,7 @@ export async function Decrypt(file: File, raw_filename: string, raw_ext: string)
const mime = AudioMimeType[ext]; const mime = AudioMimeType[ext];
let musicBlob = new Blob([musicDecoded], { type: mime }); let musicBlob = new Blob([musicDecoded], { type: mime });
const musicMeta = await metaParseBlob(musicBlob); const musicMeta = await metaParseBlob(musicBlob);
const { title, artist } = GetMetaFromFile(raw_filename, musicMeta.common.title, String(musicMeta.common.artists || musicMeta.common.artist || "")); const { title, artist } = GetMetaFromFile(raw_filename, musicMeta.common.title, musicMeta.common.artists || [musicMeta.common.artist || ""]);
return { return {
album: musicMeta.common.album, album: musicMeta.common.album,
picture: GetCoverFromFile(musicMeta), picture: GetCoverFromFile(musicMeta),

View File

@ -42,7 +42,7 @@ export async function Decrypt(file: File, raw_filename: string, _: string): Prom
let musicBlob = new Blob([audioData], { type: mime }); let musicBlob = new Blob([audioData], { type: mime });
const musicMeta = await metaParseBlob(musicBlob); const musicMeta = await metaParseBlob(musicBlob);
const { title, artist } = GetMetaFromFile(raw_filename, musicMeta.common.title, String(musicMeta.common.artists || musicMeta.common.artist || "")); const { title, artist } = GetMetaFromFile(raw_filename, musicMeta.common.title, musicMeta.common.artists || [musicMeta.common.artist || ""]);
return { return {
album: musicMeta.common.album, album: musicMeta.common.album,
picture: GetCoverFromFile(musicMeta), picture: GetCoverFromFile(musicMeta),

View File

@ -175,7 +175,6 @@ class NcmDecrypt {
if (artists.length === 0 && info.artist) { if (artists.length === 0 && info.artist) {
artists = info.artist artists = info.artist
.split(',')
.map((val) => val.trim()) .map((val) => val.trim())
.filter((val) => val != ''); .filter((val) => val != '');
} }
@ -219,7 +218,7 @@ class NcmDecrypt {
if (!this.newMeta || !this.blob) throw Error('bad sequence'); if (!this.newMeta || !this.blob) throw Error('bad sequence');
return { return {
title: this.newMeta.title, title: this.newMeta.title,
artist: this.newMeta.artists?.join('; '), artist: this.newMeta.artists,
ext: this.format, ext: this.format,
album: this.newMeta.album, album: this.newMeta.album,
picture: this.image?.url, picture: this.image?.url,

View File

@ -13,7 +13,7 @@ export async function Decrypt(file: Blob, raw_filename: string, raw_ext: string)
const ext = SniffAudioExt(buffer, raw_ext); const ext = SniffAudioExt(buffer, raw_ext);
if (ext !== raw_ext) file = new Blob([buffer], { type: AudioMimeType[ext] }); if (ext !== raw_ext) file = new Blob([buffer], { type: AudioMimeType[ext] });
const tag = await metaParseBlob(file); const tag = await metaParseBlob(file);
const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, String(tag.common.artists || tag.common.artist || "")); const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, tag.common.artists || [tag.common.artist || ""]);
return { return {
title, title,

View File

@ -43,7 +43,7 @@ export async function Decrypt(file: Blob, raw_filename: string, raw_ext: string)
throw '不支持的QQ音乐缓存格式'; throw '不支持的QQ音乐缓存格式';
} }
const tag = await metaParseBlob(audioBlob); const tag = await metaParseBlob(audioBlob);
const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, String(tag.common.artists || tag.common.artist || "")); const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, tag.common.artists || [tag.common.artist || ""]);
return { return {
title, title,

View File

@ -17,7 +17,7 @@ export async function Decrypt(
if (ext !== raw_ext) file = new Blob([buffer], { type: AudioMimeType[ext] }); if (ext !== raw_ext) file = new Blob([buffer], { type: AudioMimeType[ext] });
} }
const tag = await metaParseBlob(file); const tag = await metaParseBlob(file);
const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, String(tag.common.artists || tag.common.artist || '')); const { title, artist } = GetMetaFromFile(raw_filename, tag.common.title, tag.common.artists || [tag.common.artist || '']);
return { return {
title, title,

View File

@ -80,13 +80,13 @@ export function GetCoverFromFile(metadata: IAudioMetadata): string {
export interface IMusicMetaBasic { export interface IMusicMetaBasic {
title: string; title: string;
artist?: string; artist?: string[];
} }
export function GetMetaFromFile( export function GetMetaFromFile(
filename: string, filename: string,
exist_title?: string, exist_title?: string,
exist_artist?: string, exist_artist?: string[],
separator = '-', separator = '-',
): IMusicMetaBasic { ): IMusicMetaBasic {
const meta: IMusicMetaBasic = { title: exist_title ?? '', artist: exist_artist }; const meta: IMusicMetaBasic = { title: exist_title ?? '', artist: exist_artist };
@ -94,7 +94,7 @@ export function GetMetaFromFile(
const items = filename.split(separator); const items = filename.split(separator);
if (items.length > 1) { if (items.length > 1) {
//由文件名和原metadata共同决定歌手tag(有时从文件名看有多个歌手而metadata只有一个) //由文件名和原metadata共同决定歌手tag(有时从文件名看有多个歌手而metadata只有一个)
if (!meta.artist || meta.artist.split(split_regex).length < items[0].trim().split(split_regex).length) meta.artist = items[0].trim(); if (!meta.artist || meta.artist.length < items[0].trim().split(split_regex).length) meta.artist = items[0].trim().split(split_regex);
if (!meta.title) meta.title = items[1].trim(); if (!meta.title) meta.title = items[1].trim();
} else if (items.length === 1) { } else if (items.length === 1) {
if (!meta.title) meta.title = items[0].trim(); if (!meta.title) meta.title = items[0].trim();

View File

@ -20,7 +20,7 @@ export async function Decrypt(file: File, raw_filename: string, raw_ext: string)
const musicMeta = await metaParseBlob(musicBlob); const musicMeta = await metaParseBlob(musicBlob);
const info = GetMetaFromFile(raw_filename, musicMeta.common.title, musicMeta.common.artist); const info = GetMetaFromFile(raw_filename, musicMeta.common.title, musicMeta.common.artists || [musicMeta.common.artist || '']);
return { return {
picture: '', picture: '',

View File

@ -49,7 +49,7 @@ export async function Decrypt(file: File, raw_filename: string, raw_ext: string)
const { title, artist } = GetMetaFromFile( const { title, artist } = GetMetaFromFile(
raw_filename, raw_filename,
musicMeta.common.title, musicMeta.common.title,
String(musicMeta.common.artists || musicMeta.common.artist || ""), musicMeta.common.artists || [musicMeta.common.artist || ""],
raw_filename.indexOf('_') === -1 ? '-' : '_', raw_filename.indexOf('_') === -1 ? '-' : '_',
); );

View File

@ -14,7 +14,7 @@ import { getQMImageURLFromPMID, queryAlbumCover, querySongInfoById } from '@/uti
interface MetaResult { interface MetaResult {
title: string; title: string;
artist: string; artist: string[];
album: string; album: string;
imgUrl: string; imgUrl: string;
blob: Blob; blob: Blob;
@ -44,6 +44,7 @@ export async function extractQQMusicMeta(
musicMeta.common.artist = ''; musicMeta.common.artist = '';
if (!musicMeta.common.artists) { if (!musicMeta.common.artists) {
musicMeta.common.artist = fromGBK(musicMeta.common.artist); musicMeta.common.artist = fromGBK(musicMeta.common.artist);
musicMeta.common.artists = [musicMeta.common.artist];
} }
else { else {
musicMeta.common.artist = musicMeta.common.artists.map(fromGBK).join(); musicMeta.common.artist = musicMeta.common.artists.map(fromGBK).join();
@ -61,8 +62,8 @@ export async function extractQQMusicMeta(
} }
} }
const info = GetMetaFromFile(name, musicMeta.common.title, musicMeta.common.artist); const info = GetMetaFromFile(name, musicMeta.common.title, musicMeta.common.artists);
info.artist = info.artist || ''; info.artist = info.artist || [''];
let imageURL = GetCoverFromFile(musicMeta); let imageURL = GetCoverFromFile(musicMeta);
if (!imageURL) { if (!imageURL) {
@ -76,7 +77,7 @@ export async function extractQQMusicMeta(
imgUrl: imageURL, imgUrl: imageURL,
blob: await writeMetaToAudioFile({ blob: await writeMetaToAudioFile({
title: info.title, title: info.title,
artists: info.artist.split(split_regex), artists: info.artist,
ext, ext,
imageURL, imageURL,
musicMeta, musicMeta,
@ -97,7 +98,7 @@ async function fetchMetadataFromSongId(
return { return {
title: info.track_info.title, title: info.track_info.title,
artist: artists.join(','), artist: artists,
album: info.track_info.album.name, album: info.track_info.album.name,
imgUrl: imageURL, imgUrl: imageURL,
@ -112,9 +113,9 @@ async function fetchMetadataFromSongId(
}; };
} }
async function getCoverImage(title: string, artist?: string, album?: string): Promise<string> { async function getCoverImage(title: string, artist?: string[], album?: string): Promise<string> {
try { try {
const data = await queryAlbumCover(title, artist, album); const data = await queryAlbumCover(title, artist?.join(), album);
return getQMImageURLFromPMID(data.Id, data.Type); return getQMImageURLFromPMID(data.Id, data.Type);
} catch (e) { } catch (e) {
console.warn(e); console.warn(e);

View File

@ -217,10 +217,13 @@ export default {
}, },
async editFile(data) { async editFile(data) {
this.editing_data = data; this.editing_data.picture = data.picture;
const musicMeta = await metaParseBlob(this.editing_data.blob); this.editing_data.title = data.title
this.editing_data.artist = data.artist.join()
this.editing_data.album = data.album
const musicMeta = await metaParseBlob(data.blob);
this.editing_data.albumartist = musicMeta.common.albumartist || ''; this.editing_data.albumartist = musicMeta.common.albumartist || '';
this.editing_data.genre = musicMeta.common.genre?.toString() || ''; this.editing_data.genre = musicMeta.common.genre?.join() || '';
this.showEditDialog = true; this.showEditDialog = true;
}, },
async saveFile(data) { async saveFile(data) {

View File

@ -28,7 +28,8 @@
"dom.iterable", "dom.iterable",
"scripthost" "scripthost"
], ],
"resolveJsonModule": true "resolveJsonModule": true,
"outDir": "build"
}, },
"include": [ "include": [
"src/**/*.ts", "src/**/*.ts",
@ -38,6 +39,7 @@
"tests/**/*.tsx" "tests/**/*.tsx"
], ],
"exclude": [ "exclude": [
"node_modules" "node_modules",
"build/**/*"
] ]
} }