Deduce bit depth, sample rate, and bitrate from file sizes; add comprehensive parser tests
This commit is contained in:
@@ -196,6 +196,7 @@ func (p *GenericParser) fillFromTorrent(r *release.Release, torrentData []byte)
|
||||
}
|
||||
|
||||
p.fillFromTitle(r, info.Name)
|
||||
p.deduceFromFileSize(r)
|
||||
|
||||
log.Trace().
|
||||
Str("hash", r.InfoHash).
|
||||
@@ -205,6 +206,9 @@ func (p *GenericParser) fillFromTorrent(r *release.Release, torrentData []byte)
|
||||
Bool("cover", r.HasCoverArt).
|
||||
Bool("cue", r.HasCueSheet).
|
||||
Bool("log", r.HasRipLog).
|
||||
Int("bit_depth", r.BitDepth).
|
||||
Int("sample_rate", r.SampleRate).
|
||||
Str("bitrate", r.Bitrate).
|
||||
Msg("filled from torrent")
|
||||
}
|
||||
|
||||
@@ -267,6 +271,75 @@ func (p *GenericParser) fillFromTitle(r *release.Release, title string) {
|
||||
Msg("filled from title")
|
||||
}
|
||||
|
||||
func (p *GenericParser) deduceFromFileSize(r *release.Release) {
|
||||
if r.AudioFileCount == 0 || r.TotalAudioSize == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
avgFileSize := r.TotalAudioSize / int64(r.AudioFileCount)
|
||||
avgFileSizeMB := float64(avgFileSize) / (1024 * 1024)
|
||||
|
||||
switch {
|
||||
case r.Format.IsLossless():
|
||||
if r.BitDepth > 0 && r.SampleRate > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Average FLAC file size per ~4 min track:
|
||||
// 16/44.1 ≈ 25-35 MB 24/48 ≈ 40-60 MB
|
||||
// 24/96 ≈ 80-120 MB 24/192 ≈ 160-240 MB
|
||||
switch {
|
||||
case avgFileSizeMB >= 130:
|
||||
p.setIfMissing(r, 24, 192000)
|
||||
case avgFileSizeMB >= 65:
|
||||
p.setIfMissing(r, 24, 96000)
|
||||
case avgFileSizeMB >= 38:
|
||||
p.setIfMissing(r, 24, 48000)
|
||||
default:
|
||||
p.setIfMissing(r, 16, 44100)
|
||||
}
|
||||
|
||||
log.Trace().
|
||||
Float64("avg_file_mb", avgFileSizeMB).
|
||||
Int("deduced_bit_depth", r.BitDepth).
|
||||
Int("deduced_sample_rate", r.SampleRate).
|
||||
Msg("deduced lossless quality from file size")
|
||||
|
||||
case r.Format == release.FormatMP3:
|
||||
if r.Bitrate != "" {
|
||||
return
|
||||
}
|
||||
|
||||
// Average MP3 file size per ~4 min track:
|
||||
// 128 kbps ≈ 3.5-4 MB 192 kbps ≈ 5-6 MB
|
||||
// 256 kbps ≈ 7-8 MB 320 kbps ≈ 9-10 MB
|
||||
switch {
|
||||
case avgFileSizeMB >= 8.5:
|
||||
r.Bitrate = "320 kbps"
|
||||
case avgFileSizeMB >= 6.5:
|
||||
r.Bitrate = "256 kbps"
|
||||
case avgFileSizeMB >= 4.5:
|
||||
r.Bitrate = "192 kbps"
|
||||
default:
|
||||
r.Bitrate = "128 kbps"
|
||||
}
|
||||
|
||||
log.Trace().
|
||||
Float64("avg_file_mb", avgFileSizeMB).
|
||||
Str("deduced_bitrate", r.Bitrate).
|
||||
Msg("deduced mp3 bitrate from file size")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *GenericParser) setIfMissing(r *release.Release, bitDepth int, sampleRate int) {
|
||||
if r.BitDepth == 0 {
|
||||
r.BitDepth = bitDepth
|
||||
}
|
||||
if r.SampleRate == 0 {
|
||||
r.SampleRate = sampleRate
|
||||
}
|
||||
}
|
||||
|
||||
var trackNumberPrefix = regexp.MustCompile(`^\d{1,3}[\s.\-]+`)
|
||||
|
||||
func cleanTrackName(name string) string {
|
||||
|
||||
Reference in New Issue
Block a user