Commit graph

3 commits

Author SHA1 Message Date
BoulderBadgeDad
b6cb244cbd HiFi preview: abort the source, don't cascade to a lower-tier preview — #895
The log from a fresh run showed detection working but a second bug: rejecting the
lossless preview ('decoded 30s of 180s — rejecting') just dropped to the SAME track's
'high' (lossy m4a) tier — the same 30s clip — which the bitrate check can't see (m4a,
not FLAC), so it was accepted. A preview at any tier means the SOURCE only has a
preview of the track; lower tiers are the same clip. So on preview detection (manifest
OR post-download) we now return None to FAIL HiFi entirely, letting the orchestrator's
hybrid fallback try the next SOURCE (soulseek/youtube) instead of landing a lower-tier
preview. (A genuinely-missing tier still falls through to the next tier as before.)

Integration test drives the post-download abort end-to-end and pins 'no tier cascade'.
2026-06-21 17:09:43 -07:00
BoulderBadgeDad
4bce1932ba HiFi: catch faked-header previews (full length claimed, ~30s real audio) — #895
The first fix (#895) only caught manifests that HONESTLY declared a short length. The
real-world fakes are nastier: every length header is faked to FULL — HLS #EXTINF, the
m4a moov, AND the demuxed FLAC's STREAMINFO total_samples — while the file holds only
~30s of real audio. So the manifest-sum and mutagen-length checks both read 'full' and
passed it through. Measured 23 issue files: every one decoded to ~30s with a claimed
full length; size/claimed gave an impossible 55-362 kbps 'lossless', size/30s gave a
plausible ~600-1100 kbps.

Detect it two independent ways (post-download), so it fires even when every header lies:
- decoded real length via ffmpeg (-f null) vs the largest claimed length — the ground
  truth when a decoder is present (production demuxes with ffmpeg, so it is);
- for lossless, an impossibly-low implied bitrate (< 30% of raw PCM) — needs no decoder,
  catches all 23 on its own.

Pure is_fake_lossless_bitrate / is_preview_download / parse_ffmpeg_time helpers with seam
tests pinned to the real #895 file numbers. Reference is max(expected, container-claimed)
so the file's own faked claim becomes the bar its real audio must clear.
2026-06-21 16:56:46 -07:00
BoulderBadgeDad
1249160ff5 HiFi: reject preview manifests/files instead of landing a 30s fake
Fixes #895https://github.com/Nezreka/SoulSync/issues/895

HiFi (Tidal via hifi-api) sometimes serves a PREVIEW HLS manifest — only ~30s of
segments — for a full-length track. SoulSync downloaded exactly what the manifest
contained, and the only validation was a 100KB size floor (a 30s lossless preview is
~3-4MB, so it passed as 'complete') → a junk file that shows full length but plays ~30s.

Add two duration guards, both keyed off the track's real length (from get_track_info):
- Pre-download: sum the manifest's #EXTINF segment durations; if far short of the
  expected track length, it's a preview → skip that tier, fall through to the next
  source without wasting the download. (The parser discarded #EXTINF before.)
- Post-download: probe the finished file's real length (mutagen) and reject if short —
  backs up legacy/direct (no-EXTINF) downloads and catches any truncation.

Conservative: unknown/zero durations never reject. Pure sum_hls_segment_seconds /
is_short_audio helpers with seam tests.
2026-06-21 16:33:32 -07:00