use direct stream for resume

This commit is contained in:
2026-06-06 22:21:48 +03:00
parent c9f6d92a7f
commit 253af91f46
2 changed files with 18 additions and 1 deletions
+17 -1
View File
@@ -622,6 +622,15 @@ export function useSimilarItems(itemId?: string, limit = 12) {
* has to load first so the first PlaybackInfo request includes the * has to load first so the first PlaybackInfo request includes the
* saved StartTimeTicks - otherwise the video streams from 0 and * saved StartTimeTicks - otherwise the video streams from 0 and
* reloads mid-playback when the second query returns. * reloads mid-playback when the second query returns.
*
* `requireDirectStream` is used for resume: the direct-play
* /Videos/{id}/stream endpoint with `static=true` returns the file
* from byte 0 even when StartTimeTicks is passed, because Chromium
* / WebView2 don't send a Range header for the initial GET. The
* direct-stream path has the server read the file from the start
* position itself and stream the bytes, so the response naturally
* starts at the saved offset. Direct-stream is not transcoding -
* it's just server-side file I/O with no encoding work.
*/ */
export function usePlaybackInfo( export function usePlaybackInfo(
itemId?: string, itemId?: string,
@@ -629,6 +638,7 @@ export function usePlaybackInfo(
audioStreamIndex?: number, audioStreamIndex?: number,
maxStreamingBitrate?: number, maxStreamingBitrate?: number,
enabled: boolean = true, enabled: boolean = true,
requireDirectStream: boolean = false,
) { ) {
const api = useApi() const api = useApi()
const audioPassthrough = usePreferencesStore(s => s.audioPassthrough) const audioPassthrough = usePreferencesStore(s => s.audioPassthrough)
@@ -640,6 +650,7 @@ export function usePlaybackInfo(
startTimeTicks, startTimeTicks,
audioStreamIndex, audioStreamIndex,
maxStreamingBitrate, maxStreamingBitrate,
requireDirectStream,
], ],
queryFn: async () => { queryFn: async () => {
if (!api || !itemId) return null if (!api || !itemId) return null
@@ -657,7 +668,12 @@ export function usePlaybackInfo(
AudioStreamIndex: audioStreamIndex, AudioStreamIndex: audioStreamIndex,
DeviceProfile: await browserDeviceProfile(audioPassthrough) as any, DeviceProfile: await browserDeviceProfile(audioPassthrough) as any,
AutoOpenLiveStream: true, AutoOpenLiveStream: true,
EnableDirectPlay: true, // For resume, prefer direct-stream so the server starts the
// read at StartTimeTicks. Direct-play can't honour start
// time on the initial GET. Otherwise let the server pick
// direct-play for the no-resume case so the browser plays
// the file as-is.
EnableDirectPlay: !requireDirectStream,
EnableDirectStream: true, EnableDirectStream: true,
EnableTranscoding: true, EnableTranscoding: true,
AllowVideoStreamCopy: true, AllowVideoStreamCopy: true,
+1
View File
@@ -331,6 +331,7 @@ export default function PlayerPage() {
streamAudioIndex ?? undefined, streamAudioIndex ?? undefined,
maxBitrate, maxBitrate,
playbackInfoReady, playbackInfoReady,
startTimeTicks !== undefined,
) )
const resolvedSource = playbackInfo?.MediaSources?.[0] const resolvedSource = playbackInfo?.MediaSources?.[0]
const streamUrl = (() => { const streamUrl = (() => {