* fix: allow WAV direct play by aliasing pcm and wav codecs
WAV files were being transcoded to FLAC even when the browser declared
native WAV support. The backend normalizes ffprobe's pcm_s16le (and
similar PCM variants) to the internal codec name "pcm", while browsers
advertise WAV support as audioCodecs:["wav"] in their client profile.
The direct-play codec check compared these literally and rejected the
match with "audio codec not supported", forcing a needless FLAC
transcode.
Added {"pcm", "wav"} to codecAliasGroups so the matcher treats them
as equivalent. The container check runs first, so AIFF files (which also
normalize to codec "pcm" but use container "aiff") cannot
accidentally match a WAV direct-play profile.
* feat: include profile details in direct-play rejection reasons
The transcodeReason array returned by getTranscodeDecision previously
contained one generic string per failed DirectPlayProfile (e.g., five
copies of "container not supported"), making it hard to correlate a
reason with the profile that rejected the stream.
Each rejection reason now embeds the offending source value (in single
quotes) along with a compact representation of the full profile that
rejected it, rendered as [container/codec]. For example, clients with
two distinct ogg-container profiles (opus and vorbis) produced two
identical rejection strings; they now read "container 'wav' not
supported by profile [ogg/opus]" and "container 'wav' not supported
by profile [ogg/vorbis]", making each entry in the transcodeReason
array unique and self-describing.
A small describeProfile helper renders profiles as [container/codec]
(or [container] when no codec is constrained).
* refactor(stream): address code review — narrow pcm/wav match, tighten tests
Responds to reviewer feedback on the initial PR:
- Replace the symmetric pcm↔wav codec alias with a contextual
isPCMInWAVMatch check in checkDirectPlayProfile. The alias
unconditionally equated the two names in matchesCodec, which would
let AIFF sources (also normalized to codec "pcm") falsely satisfy
a codec-only ["wav"] direct-play profile that omitted containers.
The new check additionally requires src.Container == "wav" before
bridging the names, closing the false-positive path.
- Tighten the rejection-reason test assertions to verify the new
formatted output (source value + profile descriptor) instead of
just matching loose substrings like "container", preventing
unrelated rejections from satisfying the expectations.
- Add coverage for the WAV→wav-codec acceptance path and for the
AIFF-in-wav-codec-profile rejection path to pin down the contract
of isPCMInWAVMatch.
* refactor(codec): rename isPCMInWAVMatch to matchesPCMWAVBridge for clarity
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: rename core/transcode directory to core/stream
* refactor: update all imports from core/transcode to core/stream
* refactor: rename exported symbols to fit core/stream package name
* refactor: simplify MediaStreamer interface to single NewStream method
Remove the two-method interface (NewStream + DoStream) in favor of a
single NewStream(ctx, mf, req) method. Callers are now responsible for
fetching the MediaFile before calling NewStream. This removes the
implicit DB lookup from the streamer, making it a pure streaming
concern.
* refactor: update all callers from DoStream to NewStream
* chore: update wire_gen.go and stale comment for core/stream rename
* refactor: update wire command to handle GO_BUILD_TAGS correctly
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: distinguish not-found from internal errors in public stream handler
* refactor: remove unused ID field from stream.Request
* refactor: simplify ResolveRequestFromToken to receive *model.MediaFile
Move MediaFile fetching responsibility to callers, making the method
focused on token validation and request resolution. Remove ErrMediaNotFound
(no longer produced). Update GetTranscodeStream handler to fetch the
media file before calling ResolveRequestFromToken.
* refactor: extend tokenTTL from 12 to 48 hours
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-09 22:22:58 -04:00
Renamed from core/transcode/decider_test.go (Browse further)