Fix playback not working for offline content

This commit is contained in:
Alex Kim
2025-07-15 00:44:06 +10:00
parent 270c12c2f2
commit c010e73097
4 changed files with 14 additions and 15 deletions

View File

@@ -550,7 +550,7 @@ export default function page() {
source={{ source={{
uri: stream?.url || "", uri: stream?.url || "",
autoplay: true, autoplay: true,
isNetwork: true, isNetwork: !offline,
startPosition, startPosition,
externalSubtitles, externalSubtitles,
initOptions, initOptions,

View File

@@ -143,7 +143,7 @@ extension VLCPlayerWrapper: VLCMediaPlayerDelegate {
guard let vlcPlayerView = self.playerView.superview as? VlcPlayerView, guard let vlcPlayerView = self.playerView.superview as? VlcPlayerView,
!vlcPlayerView.initialSeekPerformed, !vlcPlayerView.initialSeekPerformed,
vlcPlayerView.startPosition > 0, vlcPlayerView.startPosition > 0,
vlcPlayerView.isTranscoding, vlcPlayerView.shouldPerformInitialSeek,
player.isSeekable else { return } player.isSeekable else { return }
vlcPlayerView.initialSeekPerformed = true vlcPlayerView.initialSeekPerformed = true
// Use a logger from the VlcPlayerView if available, or create a new one // Use a logger from the VlcPlayerView if available, or create a new one
@@ -167,7 +167,9 @@ class VlcPlayerView: ExpoView {
private var externalSubtitles: [[String: String]]? private var externalSubtitles: [[String: String]]?
var hasSource = false var hasSource = false
var initialSeekPerformed = false var initialSeekPerformed = false
var isTranscoding: Bool = false // A flag variable determinging if we should perform the initial seek. Its either transcoding or offline playback. that makes
var shouldPerformInitialSeek: Bool = false
// MARK: - Initialization // MARK: - Initialization
required init(appContext: AppContext? = nil) { required init(appContext: AppContext? = nil) {
@@ -265,12 +267,11 @@ class VlcPlayerView: ExpoView {
return return
} }
if uri.contains("m3u8") {
self.isTranscoding = true
}
let autoplay = source["autoplay"] as? Bool ?? false let autoplay = source["autoplay"] as? Bool ?? false
let isNetwork = source["isNetwork"] as? Bool ?? false let isNetwork = source["isNetwork"] as? Bool ?? false
// Set shouldPeformIntial based on isTranscoding and is not a network stream
self.shouldPerformInitialSeek = uri.contains("m3u8") || !isNetwork
self.onVideoLoadStart?(["target": self.reactTag ?? NSNull()]) self.onVideoLoadStart?(["target": self.reactTag ?? NSNull()])
let media: VLCMedia! let media: VLCMedia!
@@ -295,7 +296,7 @@ class VlcPlayerView: ExpoView {
if autoplay { if autoplay {
logger.info("Playing...") logger.info("Playing...")
// The Video is not transcoding so it its safe to seek to the start position. // The Video is not transcoding so it its safe to seek to the start position.
if !self.isTranscoding { if !self.shouldPerformInitialSeek {
self.vlc.player.time = VLCTime(number: NSNumber(value: self.startPosition * 1000)) self.vlc.player.time = VLCTime(number: NSNumber(value: self.startPosition * 1000))
} }
self.play() self.play()

View File

@@ -1,12 +1,10 @@
import generateDeviceProfile from "@/utils/profiles/native";
import type { Api } from "@jellyfin/sdk"; import type { Api } from "@jellyfin/sdk";
import type { import type {
BaseItemDto, BaseItemDto,
MediaSourceInfo, MediaSourceInfo,
PlaybackInfoResponse,
} from "@jellyfin/sdk/lib/generated-client/models"; } from "@jellyfin/sdk/lib/generated-client/models";
import { getMediaInfoApi } from "@jellyfin/sdk/lib/utils/api"; import { getMediaInfoApi } from "@jellyfin/sdk/lib/utils/api";
import { Alert } from "react-native"; import generateDeviceProfile from "@/utils/profiles/native";
export const getStreamUrl = async ({ export const getStreamUrl = async ({
api, api,
@@ -33,7 +31,7 @@ export const getStreamUrl = async ({
subtitleStreamIndex?: number; subtitleStreamIndex?: number;
height?: number; height?: number;
mediaSourceId?: string | null; mediaSourceId?: string | null;
download?: bool; download?: boolean;
deviceId?: string | null; deviceId?: string | null;
}): Promise<{ }): Promise<{
url: string | null; url: string | null;
@@ -73,8 +71,8 @@ export const getStreamUrl = async ({
} }
sessionId = res.data.PlaySessionId || null; sessionId = res.data.PlaySessionId || null;
mediaSource = res.data.MediaSources[0]; mediaSource = res.data.MediaSources?.[0];
let transcodeUrl = mediaSource.TranscodingUrl; let transcodeUrl = mediaSource?.TranscodingUrl;
if (transcodeUrl) { if (transcodeUrl) {
if (download) { if (download) {
@@ -125,7 +123,7 @@ export const getStreamUrl = async ({
return { return {
url: directPlayUrl, url: directPlayUrl,
sessionId: sessionId || playSessionId, sessionId: sessionId || playSessionId || null,
mediaSource, mediaSource,
}; };
}; };

View File

@@ -62,7 +62,7 @@ export const generateDeviceProfile = async () => {
DirectPlayProfiles: [ DirectPlayProfiles: [
{ {
Type: MediaTypes.Video, Type: MediaTypes.Video,
Container: "mp4,mkv,avi,mov,flv,ts,m2ts,webm,ogv,3gp,hls", Container: "mkv,avi,mov,flv,ts,m2ts,webm,ogv,3gp,hls",
VideoCodec: VideoCodec:
"h264,hevc,mpeg4,divx,xvid,wmv,vc1,vp8,vp9,av1,avi,mpeg,mpeg2video", "h264,hevc,mpeg4,divx,xvid,wmv,vc1,vp8,vp9,av1,avi,mpeg,mpeg2video",
AudioCodec: "aac,ac3,eac3,mp3,flac,alac,opus,vorbis,wma,dts", AudioCodec: "aac,ac3,eac3,mp3,flac,alac,opus,vorbis,wma,dts",