Merge branch 'autoskip' into refactor-chromecast

This commit is contained in:
Uruk
2026-01-19 22:15:17 +01:00
9 changed files with 611 additions and 53 deletions

View File

@@ -134,6 +134,9 @@ export enum VideoPlayer {
MPV = 0,
}
// Segment skip behavior options
export type SegmentSkipMode = "none" | "ask" | "auto";
// Audio transcoding mode - controls how surround audio is handled
// This controls server-side transcoding behavior for audio streams.
// MPV decodes via FFmpeg and supports most formats, but mobile devices
@@ -181,6 +184,12 @@ export type Settings = {
maxAutoPlayEpisodeCount: MaxAutoPlayEpisodeCount;
autoPlayEpisodeCount: number;
autoPlayNextEpisode: boolean;
// Media segment skip preferences
skipIntro: SegmentSkipMode;
skipOutro: SegmentSkipMode;
skipRecap: SegmentSkipMode;
skipCommercial: SegmentSkipMode;
skipPreview: SegmentSkipMode;
// Playback speed settings
defaultPlaybackSpeed: number;
playbackSpeedPerMedia: Record<string, number>;
@@ -266,6 +275,12 @@ export const defaultValues: Settings = {
maxAutoPlayEpisodeCount: { key: "3", value: 3 },
autoPlayEpisodeCount: 0,
autoPlayNextEpisode: true,
// Media segment skip defaults
skipIntro: "ask",
skipOutro: "ask",
skipRecap: "ask",
skipCommercial: "ask",
skipPreview: "ask",
// Playback speed defaults
defaultPlaybackSpeed: 1.0,
playbackSpeedPerMedia: {},

View File

@@ -74,10 +74,16 @@ export const getSegmentsForItem = (
): {
introSegments: MediaTimeSegment[];
creditSegments: MediaTimeSegment[];
recapSegments: MediaTimeSegment[];
commercialSegments: MediaTimeSegment[];
previewSegments: MediaTimeSegment[];
} => {
return {
introSegments: item.introSegments || [],
creditSegments: item.creditSegments || [],
recapSegments: item.recapSegments || [],
commercialSegments: item.commercialSegments || [],
previewSegments: item.previewSegments || [],
};
};
@@ -95,6 +101,9 @@ const fetchMediaSegments = async (
): Promise<{
introSegments: MediaTimeSegment[];
creditSegments: MediaTimeSegment[];
recapSegments: MediaTimeSegment[];
commercialSegments: MediaTimeSegment[];
previewSegments: MediaTimeSegment[];
} | null> => {
try {
const response = await api.axiosInstance.get<MediaSegmentsResponse>(
@@ -102,13 +111,22 @@ const fetchMediaSegments = async (
{
headers: getAuthHeaders(api),
params: {
includeSegmentTypes: ["Intro", "Outro"],
includeSegmentTypes: [
"Intro",
"Outro",
"Recap",
"Commercial",
"Preview",
],
},
},
);
const introSegments: MediaTimeSegment[] = [];
const creditSegments: MediaTimeSegment[] = [];
const recapSegments: MediaTimeSegment[] = [];
const commercialSegments: MediaTimeSegment[] = [];
const previewSegments: MediaTimeSegment[] = [];
response.data.Items.forEach((segment) => {
const timeSegment: MediaTimeSegment = {
@@ -124,13 +142,27 @@ const fetchMediaSegments = async (
case "Outro":
creditSegments.push(timeSegment);
break;
// Optionally handle other types like Recap, Commercial, Preview
case "Recap":
recapSegments.push(timeSegment);
break;
case "Commercial":
commercialSegments.push(timeSegment);
break;
case "Preview":
previewSegments.push(timeSegment);
break;
default:
break;
}
});
return { introSegments, creditSegments };
return {
introSegments,
creditSegments,
recapSegments,
commercialSegments,
previewSegments,
};
} catch (_error) {
// Return null to indicate we should try legacy endpoints
return null;
@@ -146,6 +178,9 @@ const fetchLegacySegments = async (
): Promise<{
introSegments: MediaTimeSegment[];
creditSegments: MediaTimeSegment[];
recapSegments: MediaTimeSegment[];
commercialSegments: MediaTimeSegment[];
previewSegments: MediaTimeSegment[];
}> => {
const introSegments: MediaTimeSegment[] = [];
const creditSegments: MediaTimeSegment[] = [];
@@ -184,7 +219,13 @@ const fetchLegacySegments = async (
console.error("Failed to fetch legacy segments", error);
}
return { introSegments, creditSegments };
return {
introSegments,
creditSegments,
recapSegments: [],
commercialSegments: [],
previewSegments: [],
};
};
export const fetchAndParseSegments = async (
@@ -193,6 +234,9 @@ export const fetchAndParseSegments = async (
): Promise<{
introSegments: MediaTimeSegment[];
creditSegments: MediaTimeSegment[];
recapSegments: MediaTimeSegment[];
commercialSegments: MediaTimeSegment[];
previewSegments: MediaTimeSegment[];
}> => {
// Try new API first (Jellyfin 10.11+)
const newSegments = await fetchMediaSegments(itemId, api);