Universal audio ignores transcodingProtocol=hls and answers with audio instead of a playlist #186
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
GET /Audio/{itemId}/universal?transcodingProtocol=hlsasks for a playlist.Upstream answers with one; we answer with raw audio.
Upstream's route
(
upstream/Jellyfin.Api/Controllers/UniversalAudioController.cs:182-229) buildsan
HlsAudioRequestDtoand returnsDynamicHlsHelper.GetMasterHlsPlaylist,Content-Type: application/x-mpegURL. The segment container is restricted totsormp4— anything else the client names falls back tots— and theaudio codec becomes
copywhere the only reason to transcode wasContainerNotSupported.We do not read
transcodingProtocolat all(
crates/ephyra-http/src/routes/streaming/audio.rs), so every non-direct-playverdict takes the progressive branch and answers
200withContent-Type: audio/mpegand a body of audio bytes. A client that asked for aplaylist gets something it cannot parse.
The default is
http(
UniversalAudioController.cs:298,Protocol = transcodingProtocol ?? http),so the common path is right and this is the explicit-request case. The master
playlist itself is already written —
crates/ephyra-http/src/routes/streaming/hls.rsserves
/Audio/{itemId}/master.m3u8— so this is mostly a matter of reading theparameter and handing the request to it with the fields upstream fills in.
How to know it is done
A request naming
transcodingProtocol=hlscomes back as a master playlist, andthe harness agrees with upstream on its body. The progressive default is
unchanged.
House rules
Tests run under
cargo nextest; upstream's source is the checkout inupstream/at the pin.Done in
879ee69, withdc9354eafter a review.The route reads
transcodingProtocol.hlsand not a direct play is answeredwith a master playlist from the routes that already serve one: the segments cut
into
tsormp4— the request's container where it is one of those, else theone the negotiation settled, else
ts— and the audio codeccopywhere thecontainer was the whole complaint. The variant URL carries the request's own
query with
SegmentContainerandTranscodeReasonsappended where the clientdid not send them.
One thing that came with it: the variant URL names the codec the encoder will
really produce rather than the one the client asked for. Upstream rewrites that
in
DynamicHlsHelperfor every master playlist, so ours had been getting itwrong on the video route too — a request for
audioCodec=aac,mp3named thewhole list where upstream names
aac.Measured
Both servers over the anchor. Before:
upstream 200 application/vnd.apple.mpegurlagainst
ours 500. After, byte for byte, 254–344 bytes each:and two video
master.m3u8shapes, which the codec rewrite now also reaches,agree the same way.
One shape still disagrees, and it is not this issue's: a request naming no
audioCodecat all. Upstream infers one from the request path — which carriesno extension here, so what it infers is the path — and ours never passes a path
to the encoder to infer from. Filed as #189.