// lib/metadata/metadata_model.dart import 'dart:typed_data'; /// 从音频文件读取的原始元数据 class RawMetadata { final String title; final String artist; final String album; final List genres; final List performers; final int year; final int trackNumber; final int trackTotal; final int discNumber; final int totalDisc; final Duration? duration; final Uint8List? artwork; const RawMetadata({ this.title = '', this.artist = '', this.album = '', this.genres = const [], this.performers = const [], this.year = 0, this.trackNumber = 0, this.trackTotal = 0, this.discNumber = 0, this.totalDisc = 0, this.duration, this.artwork, }); bool get isEmpty => title.isEmpty && artist.isEmpty && album.isEmpty && genres.isEmpty && performers.isEmpty && year == 0; bool get isNotEmpty => !isEmpty; } /// 标准化后的元数据 class NormalizedMetadata { final String title; final String artist; final String album; final List genres; final List performers; final int year; final int trackNumber; final int trackTotal; final int discNumber; final int totalDisc; final Duration? duration; final Uint8List? artwork; /// 字段来源:true 表示来自标签,false 表示从文件名/路径推断。 /// 置信度模型需要区分这两者——"标签里的标题"和"文件名当标题"价值完全不同。 final bool titleFromTag; final bool artistFromTag; final bool albumFromTag; const NormalizedMetadata({ this.title = '', this.artist = '', this.album = '', this.genres = const [], this.performers = const [], this.year = 0, this.trackNumber = 0, this.trackTotal = 0, this.discNumber = 0, this.totalDisc = 0, this.duration, this.artwork, this.titleFromTag = false, this.artistFromTag = false, this.albumFromTag = false, }); bool get isEmpty => title.isEmpty && artist.isEmpty && album.isEmpty && genres.isEmpty && performers.isEmpty && year == 0; bool get isNotEmpty => !isEmpty; } /// 候选元数据 class CandidateMetadata { final NormalizedMetadata metadata; final double confidence; final Map evidence; const CandidateMetadata({ required this.metadata, required this.confidence, this.evidence = const {}, }); } /// 最终确认的元数据 class FinalMetadata { final String title; final String artist; final String album; final String genre; final List genres; final List performers; final int year; final int trackNumber; final int trackTotal; final int discNumber; final int totalDisc; final Duration? duration; final Uint8List? artwork; final String source; const FinalMetadata({ this.title = '', this.artist = '', this.album = '', this.genre = '', this.genres = const [], this.performers = const [], this.year = 0, this.trackNumber = 0, this.trackTotal = 0, this.discNumber = 0, this.totalDisc = 0, this.duration, this.artwork, this.source = 'unknown', }); bool get isEmpty => title.isEmpty && artist.isEmpty && album.isEmpty && genre.isEmpty && genres.isEmpty && performers.isEmpty && year == 0; bool get isNotEmpty => !isEmpty; }