fix(casting): report the real PlayMethod to Jellyfin

This commit is contained in:
Uruk
2026-05-22 02:20:51 +02:00
parent b38064e2da
commit 0cc3a8469d
3 changed files with 29 additions and 5 deletions

View File

@@ -60,6 +60,13 @@ export const useCasting = (item: BaseItemDto | null) => {
| undefined
)?.playSessionId ?? mediaStatus?.mediaInfo?.contentId;
const playMethod =
(
mediaStatus?.mediaInfo?.customData as
| { playMethod?: "Transcode" | "DirectPlay" }
| undefined
)?.playMethod ?? "Transcode";
// Detect which protocol is active - use CastState for reliable detection
const chromecastConnected = castState === CastState.CONNECTED;
// Future: Add detection for other protocols here
@@ -143,8 +150,7 @@ export const useCasting = (item: BaseItemDto | null) => {
playbackStartInfo: {
ItemId: item.Id,
PositionTicks: Math.floor(currentState.progress * 10000),
PlayMethod:
activeProtocol === "chromecast" ? "DirectStream" : "DirectPlay",
PlayMethod: playMethod,
VolumeLevel: Math.floor(currentState.volume * 100),
IsMuted: currentState.volume === 0,
PlaySessionId: playSessionId,
@@ -183,8 +189,7 @@ export const useCasting = (item: BaseItemDto | null) => {
ItemId: item.Id,
PositionTicks: progressTicks,
IsPaused: !s.isPlaying,
PlayMethod:
activeProtocol === "chromecast" ? "DirectStream" : "DirectPlay",
PlayMethod: playMethod,
VolumeLevel: Math.floor(s.volume * 100),
IsMuted: s.volume === 0,
PlaySessionId: playSessionId,
@@ -198,7 +203,15 @@ export const useCasting = (item: BaseItemDto | null) => {
// Report progress on a fixed interval, reading latest state from ref
const interval = setInterval(reportProgress, 10000);
return () => clearInterval(interval);
}, [api, item?.Id, user?.Id, isConnected, activeProtocol, playSessionId]);
}, [
api,
item?.Id,
user?.Id,
isConnected,
activeProtocol,
playSessionId,
playMethod,
]);
// Play/Pause controls
const play = useCallback(async () => {

View File

@@ -75,6 +75,11 @@ const attemptLoad = async (
throw new Error("getStreamUrl returned no URL");
}
const playMethod: "Transcode" | "DirectPlay" = data.mediaSource
?.TranscodingUrl
? "Transcode"
: "DirectPlay";
await client.loadMedia({
mediaInfo: buildCastMediaInfo({
item,
@@ -82,6 +87,7 @@ const attemptLoad = async (
api,
playSessionId: data.sessionId ?? undefined,
selection,
playMethod,
}),
startTime: startPositionMs / 1000,
});

View File

@@ -26,6 +26,7 @@ export const buildCastMediaInfo = ({
isLive = false,
playSessionId,
selection,
playMethod,
}: {
item: BaseItemDto;
streamUrl: string;
@@ -38,6 +39,8 @@ export const buildCastMediaInfo = ({
playSessionId?: string;
/** Active track / quality / version selection, embedded in customData. */
selection?: CastSelection;
/** "Transcode" when the stream is a server transcode, else "DirectPlay". */
playMethod?: "Transcode" | "DirectPlay";
}) => {
if (!item.Id) {
throw new Error("Missing item.Id for media load — cannot build contentId");
@@ -94,9 +97,11 @@ export const buildCastMediaInfo = ({
const slimCustomData: Partial<BaseItemDto> & {
playSessionId?: string;
selection?: CastSelection;
playMethod?: "Transcode" | "DirectPlay";
} = {
playSessionId,
selection,
playMethod,
Id: item.Id,
Name: item.Name,
Type: item.Type,