Fix CRT shader: use plain &crtShader=true query param in TranscodingUrl
Some checks failed
Push & Release 🌍 / Automation 🎛️ (push) Has been cancelled
Push & Release 🌍 / Unstable release 🚀⚠️ (push) Has been cancelled
Push & Release 🌍 / Quality checks 👌🧪 (push) Has been cancelled
Push & Release 🌍 / GitHub CodeQL 🔬 (push) Has been cancelled
Push & Release 🌍 / Deploy 🚀 (push) Has been cancelled

Previous approach used streamOptions[crtShader]=true (wrong format).
ParseStreamOptions on the server reads IQueryCollection directly and
stores keys verbatim — so streamOptions[crtShader] becomes the key,
not crtShader, and TryGetValue("crtShader") always returns false.

Plain &crtShader=true works because ParseStreamOptions adds any
lowercase-starting query param directly to the StreamOptions dict.

Also remove the dead PlaybackInfoDto.StreamOptions code — that DTO
has no StreamOptions field, so it was silently ignored.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mani
2026-02-25 22:23:24 +01:00
parent d14f15a2f8
commit 3dd1de3d9c

View File

@@ -470,9 +470,6 @@ async function getPlaybackInfo(player, apiClient, item, deviceProfile, mediaSour
if (options.allowAudioStreamCopy != null) {
query.AllowAudioStreamCopy = options.allowAudioStreamCopy;
}
if (options.streamOptions) {
query.StreamOptions = options.streamOptions;
}
if (mediaSourceId) {
query.MediaSourceId = mediaSourceId;
}
@@ -1750,14 +1747,6 @@ export class PlaybackManager {
const currentPlayOptions = currentItem.playOptions || getDefaultPlayOptions();
const crtStreamOptions = (function () {
const pd = getPlayerData(player);
if (!pd.enableCrtShader) return undefined;
const opts = { crtShader: 'true' };
if (pd.crtShadowMask != null) opts.crtShadowMask = String(pd.crtShadowMask);
return opts;
})();
const options = {
maxBitrate,
startPosition: ticks,
@@ -1767,8 +1756,7 @@ export class PlaybackManager {
enableDirectPlay: params.EnableDirectPlay,
enableDirectStream: params.EnableDirectStream,
allowVideoStreamCopy: params.AllowVideoStreamCopy,
allowAudioStreamCopy: params.AllowAudioStreamCopy,
streamOptions: crtStreamOptions
allowAudioStreamCopy: params.AllowAudioStreamCopy
};
getPlaybackInfo(player, apiClient, currentItem, deviceProfile, currentMediaSource.Id, liveStreamId, options).then(function (result) {
@@ -2890,7 +2878,17 @@ export class PlaybackManager {
playMethod = mediaSource.SupportsDirectPlay ? 'DirectPlay' : 'DirectStream';
} else if (mediaSource.SupportsTranscoding) {
const transcodingUrl = mediaSource.TranscodingUrl;
let transcodingUrl = mediaSource.TranscodingUrl;
// Append CRT shader options as plain query params so ParseStreamOptions
// on the server picks them up (key must start lowercase, no streamOptions[] wrapper).
if (getPlayerData(player).enableCrtShader) {
transcodingUrl += '&crtShader=true';
const maskVal = getPlayerData(player).crtShadowMask;
if (maskVal !== undefined && maskVal !== null) {
transcodingUrl += '&crtShadowMask=' + maskVal;
}
}
mediaUrl = apiClient.getUrl(transcodingUrl);