基础实现代码框架先上,后面慢慢改逻辑

This commit is contained in:
2026-08-23 19:24:16 +08:00
parent 6c4e77ca00
commit 9a60441e04
9 changed files with 446 additions and 1 deletions
+85
View File
@@ -0,0 +1,85 @@
// lib/metadata/metadata_normalizer.dart
import 'metadata_model.dart';
class MetadataNormalizer {
/// 标准化原始数据(清洗空格、推断、fallback)
NormalizedMetadata normalize(RawMetadata raw,
{String fileName = '', String filePath = ''}) {
// 1. 修剪空格
final title = raw.title.trim();
final artist = raw.artist.trim();
final album = raw.album.trim();
final albumArtist = raw.albumArtist.trim();
// 2. 如果 title 为空,尝试从文件名推断
final finalTitle =
title.isNotEmpty ? title : _inferTitleFromFileName(fileName);
// 3. 如果 artist 为空,尝试从路径推断或使用默认值
final finalArtist =
artist.isNotEmpty ? artist : _inferArtistFromPath(filePath);
return NormalizedMetadata(
title: finalTitle,
artist: finalArtist,
album: album,
albumArtist: albumArtist,
composer: raw.composer.trim(),
genre: raw.genre.trim(),
year: raw.year,
trackNumber: raw.trackNumber,
discNumber: raw.discNumber,
artwork: raw.artwork,
);
}
String _inferTitleFromFileName(String fileName) {
// 去掉扩展名
final dotIndex = fileName.lastIndexOf('.');
if (dotIndex > 0) {
return fileName.substring(0, dotIndex).trim();
}
return fileName.trim();
}
String _inferArtistFromPath(String filePath) {
// 简单推断:尝试从路径中的文件夹名获取
final parts = filePath.split(RegExp(r'[/\\]'));
if (parts.length >= 2) {
// 倒数第二个文件夹可能是艺术家
final candidate = parts[parts.length - 2].trim();
if (candidate.isNotEmpty && !candidate.contains(' ')) {
return candidate;
}
}
return '未知艺术家';
}
/// 评估候选元数据(第一阶段:直接接受,不纠错)
CandidateMetadata evaluate(
NormalizedMetadata normalized, List<Map<String, dynamic>> history) {
// 第一阶段:置信度固定为 0.8(文件名+标签混合)
return CandidateMetadata(
metadata: normalized,
confidence: 0.8,
evidence: {'normalized': 0.8},
);
}
/// 决策是否修正(第一阶段:直接接受)
FinalMetadata decide(CandidateMetadata candidate, {double threshold = 0.6}) {
return FinalMetadata(
title: candidate.metadata.title,
artist: candidate.metadata.artist,
album: candidate.metadata.album,
albumArtist: candidate.metadata.albumArtist,
composer: candidate.metadata.composer,
genre: candidate.metadata.genre,
year: candidate.metadata.year,
trackNumber: candidate.metadata.trackNumber,
discNumber: candidate.metadata.discNumber,
artwork: candidate.metadata.artwork,
source: 'normalized',
);
}
}