mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-08-02 09:08:35 +02:00
feat(metadata): show average bitrate for lossless files in the track screen
This commit is contained in:
@@ -144,6 +144,13 @@ func ReadFileMetadata(filePath string) (string, error) {
|
||||
}
|
||||
if quality.SampleRate > 0 && quality.TotalSamples > 0 {
|
||||
result["duration"] = int(quality.TotalSamples / int64(quality.SampleRate))
|
||||
// Average bitrate from file size: helps spot lossy audio
|
||||
// repackaged as "24-bit" FLAC (real hi-res sits well above
|
||||
// ~1500 kbps, upconverted files far below).
|
||||
durationSec := float64(quality.TotalSamples) / float64(quality.SampleRate)
|
||||
if info, statErr := os.Stat(filePath); statErr == nil && info.Size() > 0 && durationSec > 0 {
|
||||
result["bitrate"] = int(float64(info.Size()) * 8 / durationSec / 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,6 +171,10 @@ func ReadFileMetadata(filePath string) (string, error) {
|
||||
}
|
||||
if quality.Bitrate > 0 && !isLosslessLibraryFormat(fmt.Sprint(result["format"])) {
|
||||
result["bitrate"] = quality.Bitrate
|
||||
} else if quality.Duration > 0 {
|
||||
if info, statErr := os.Stat(filePath); statErr == nil && info.Size() > 0 {
|
||||
result["bitrate"] = int(float64(info.Size()) * 8 / float64(quality.Duration) / 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if isMp3 {
|
||||
|
||||
@@ -706,6 +706,27 @@ extension _TrackMetadataCards on _TrackMetadataScreenState {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!_isBitrateFormatLabel(fileExtension) &&
|
||||
_audioBitrate != null &&
|
||||
_audioBitrate! > 0)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.tertiaryContainer,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Text(
|
||||
'${_audioBitrate}kbps',
|
||||
style: TextStyle(
|
||||
color: colorScheme.onTertiaryContainer,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
|
||||
@@ -315,11 +315,11 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen>
|
||||
final formatChanged =
|
||||
resolvedFormat != null &&
|
||||
resolvedFormat != normalizeAudioFormatValue(storedFormat);
|
||||
final resolvedBitrate = _isBitrateFormatValue(resolvedFormat)
|
||||
? _readPlausibleBitrateKbps(
|
||||
metadata['bitrate'] ?? metadata['bit_rate'],
|
||||
)
|
||||
: null;
|
||||
// Lossless files carry an average bitrate too (computed by the backend
|
||||
// from file size / duration) — useful for spotting fake 24-bit rips.
|
||||
final resolvedBitrate = _readPlausibleBitrateKbps(
|
||||
metadata['bitrate'] ?? metadata['bit_rate'],
|
||||
);
|
||||
final resolvedDuration = readPositiveInt(metadata['duration']);
|
||||
final resolvedAlbum = metadata['album']?.toString();
|
||||
final resolvedTitle = metadata['title']?.toString();
|
||||
|
||||
Reference in New Issue
Block a user