The audio negotiation never answers DirectStream, so a remux picks the wrong container #187
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?
The audio negotiation only ever answers
DirectPlayor nothing(
crates/ephyra-app/src/streaming/playback/verdict.rs:260-313). Upstream has athird answer for audio, and reaches it often.
StreamBuilder.BuildAudioItem(
upstream/MediaBrowser.Model/Dlna/StreamBuilder.cs:483-500) returnsDirectStreamwhenever the only reason direct play failed wasContainerNotSupported— a codec the client takes, in a container it does not.It does not honour
EnableDirectStream=falsefor audio, so the branch is notone a client can decline.
Two things follow that we get wrong:
The container.
StreamBuilder.cs:157setsitem.TranscodingContainer = remuxContainer— the matched direct-playprofile's container where that is
tsormp4, andtranscodingContainer ?? "ts"otherwise./Audio/{id}/universalthen transcodes into that, not intothe transcoding profile's container. So a codec-compatible, container-
incompatible source asked for with no
transcodingContaineris.tsupstreamand
.mp3here.What the client is told.
PlaybackInforeports the play method for a sourceit cannot hand over directly; ours never says
DirectStreamfor audio.jellyfin-web masks the first half by always sending
transcodingContainer,which is why this has not shown up in the click-through.
How to know it is done
A source whose codec a profile takes and whose container it does not is
negotiated as
DirectStream, and the harness agrees with upstream on both thePlaybackInfobody and the container/universalpicks for it.House rules
Tests run under
cargo nextest; upstream's source is the checkout inupstream/at the pin. Anything touching the negotiation gets reviewed.Done in
879ee69, withdc9354eafter a review.audio_verdictnow answersDirectStreamwhere the container was the onlycomplaint, in upstream's own shape: the direct-play profile search, then a
profile that names the codec in a container this file is not in, then the
bitrate check on each branch, then the exactly-
ContainerNotSupportedgate.The container it hands over in is
item.TranscodingContainer ?? "ts", overriddenby the matched profile's where that is one a segmented stream can carry, and the
HLS codec restriction is applied where the request asked for segments.
One thing came with it that the issue did not name: a file whose container no
profile takes is blamed for its codecs as well — the video one included,
which a music file has none of. That is upstream's
GetTranscodeReasonsFromDirectPlayProfile, and it is what a transcoding URLcarries.
Measured
Both servers over the anchor,
POST /Items/{flac}/PlaybackInfowith a profilethat takes
flacinwebm, before → after:and a plain transcode's reasons, before → after:
Whole-body
PlaybackInfodiffs agree on three profiles — the remux, a directplay, and what jellyfin-web posts — with nothing left but the session id and the
token each server draws for itself.