diff --git a/app/(auth)/vlc-player.tsx b/app/(auth)/vlc-player.tsx
index 69f0213d..f4ee96d9 100644
--- a/app/(auth)/vlc-player.tsx
+++ b/app/(auth)/vlc-player.tsx
@@ -1,5 +1,4 @@
import { Controls } from "@/components/video-player/Controls";
-import { VideoDebugInfo } from "@/components/vlc/VideoDebugInfo";
import { useAndroidNavigationBar } from "@/hooks/useAndroidNavigationBar";
import { useOrientation } from "@/hooks/useOrientation";
import { useOrientationSettings } from "@/hooks/useOrientationSettings";
@@ -24,7 +23,6 @@ import { getPlaystateApi } from "@jellyfin/sdk/lib/utils/api";
import * as Haptics from "expo-haptics";
import { useFocusEffect } from "expo-router";
import { useAtomValue } from "jotai";
-import { set } from "lodash";
import React, {
useCallback,
useEffect,
@@ -32,13 +30,9 @@ import React, {
useRef,
useState,
} from "react";
-import { Alert, Dimensions, Pressable, StatusBar, View } from "react-native";
+import { Dimensions, Pressable, StatusBar, View } from "react-native";
import { useSharedValue } from "react-native-reanimated";
-import Video, {
- OnProgressData,
- SelectedTrackType,
- VideoRef,
-} from "react-native-video";
+import { SelectedTrackType } from "react-native-video";
export default function page() {
const { playSettings, playUrl, playSessionId } = usePlaySettings();
@@ -276,6 +270,8 @@ export default function page() {
};
}, []);
+ const [isVideoLoaded, setIsVideoLoaded] = useState(false);
+
return (
{
+ setIsVideoLoaded(true);
console.log("onVideoLoadEnd");
}}
/>
@@ -340,6 +337,7 @@ export default function page() {
setShowControls={setShowControls}
setIgnoreSafeAreas={setIgnoreSafeAreas}
ignoreSafeAreas={ignoreSafeAreas}
+ isVideoLoaded={isVideoLoaded}
/>
);
diff --git a/components/video-player/Controls.tsx b/components/video-player/Controls.tsx
index 65e20efd..b299d49d 100644
--- a/components/video-player/Controls.tsx
+++ b/components/video-player/Controls.tsx
@@ -59,6 +59,7 @@ interface Props {
togglePlay: (ticks: number) => void;
setShowControls: (shown: boolean) => void;
offline?: boolean;
+ isVideoLoaded?: boolean;
}
export const Controls: React.FC = ({
@@ -74,6 +75,7 @@ export const Controls: React.FC = ({
setShowControls,
ignoreSafeAreas,
setIgnoreSafeAreas,
+ isVideoLoaded,
offline = false,
}) => {
const [settings] = useSettings();
@@ -247,14 +249,6 @@ export const Controls: React.FC = ({
MediaStream | undefined
>(undefined);
- const allSubtitleTracks = useMemo(() => {
- const subs = item.MediaStreams?.filter(
- (stream) => stream.Type === "Subtitle"
- );
- console.log("allSubtitleTracks", subs);
- return subs;
- }, [item]);
-
const [audioTracks, setAudioTracks] = useState(null);
const [subtitleTracks, setSubtitleTracks] = useState(
null
@@ -273,7 +267,55 @@ export const Controls: React.FC = ({
};
fetchTracks();
- }, [videoRef]);
+ }, [videoRef, isVideoLoaded]);
+
+ type EmbeddedSubtitle = {
+ name: string;
+ index: number;
+ isExternal: false;
+ };
+
+ type ExternalSubtitle = {
+ name: string;
+ index: number;
+ isExternal: true;
+ deliveryUrl: string;
+ };
+
+ const allSubtitleTracks = useMemo(() => {
+ const embeddedSubs =
+ subtitleTracks?.map((s) => ({
+ name: s.name,
+ index: s.index,
+ isExternal: false,
+ deliveryUrl: undefined,
+ })) || [];
+
+ const externalSubs =
+ item.MediaStreams?.filter(
+ (stream) => stream.Type === "Subtitle" && stream.IsExternal
+ ).map((s) => ({
+ name: s.DisplayTitle!,
+ index: s.Index!,
+ isExternal: s.DeliveryMethod === "External",
+ deliveryUrl: s.DeliveryUrl,
+ })) || [];
+
+ // Create a Set of embedded subtitle names for quick lookup
+ const embeddedSubNames = new Set(embeddedSubs.map((sub) => sub.name));
+
+ // Filter out external subs that have the same name as embedded subs
+ const uniqueExternalSubs = externalSubs.filter(
+ (sub) => !embeddedSubNames.has(sub.name)
+ );
+
+ console.log([...embeddedSubs, ...uniqueExternalSubs]);
+ // Combine embedded and unique external subs
+ return [...embeddedSubs, ...uniqueExternalSubs] as (
+ | EmbeddedSubtitle
+ | ExternalSubtitle
+ )[];
+ }, [item, isVideoLoaded, subtitleTracks]);
return (
= ({
loop={true}
sideOffset={10}
>
- {
videoRef.current?.setSubtitleTrack(-1);
}}
>
-
+
None
-
- {subtitleTracks?.map((sub, idx: number) => (
- {
- // if(sub. === 'External') {
- // videoRef.current?.setSubtitleURL(
- // `https://fredflix.se/Providers/Subtitles/Subtitles/`
- // );
- // }
+ */}
+ {allSubtitleTracks.length > 0
+ ? allSubtitleTracks?.map((sub, idx: number) => (
+ {
+ if (sub.isExternal) {
+ videoRef.current?.setSubtitleURL(sub.deliveryUrl);
+ console.log(
+ "Setting external subtitle:",
+ sub.deliveryUrl
+ );
+ return;
+ }
- videoRef.current?.setSubtitleTrack(-1);
- console.log(sub);
- }}
- >
-
-
- {sub.name}
-
-
- ))}
+ console.log("Settings embedded subtitle", sub.name);
+ videoRef.current?.setSubtitleTrack(sub.index);
+ console.log(sub);
+ }}
+ >
+
+
+ {sub.name}
+
+
+ ))
+ : null}
diff --git a/modules/vlc-player/ios/VlcPlayerView.swift b/modules/vlc-player/ios/VlcPlayerView.swift
index d6ac186c..07565d55 100644
--- a/modules/vlc-player/ios/VlcPlayerView.swift
+++ b/modules/vlc-player/ios/VlcPlayerView.swift
@@ -557,7 +557,7 @@ extension VlcPlayerView: VLCMediaPlayerDelegate {
}
// Dermine if the media has finished loading
- if currentState == .buffering && !self.isMediaReady {
+ if player.isPlaying && !self.isMediaReady {
self.isMediaReady = true
self.onVideoLoadEnd?(stateInfo)
}
diff --git a/utils/profiles/native.js b/utils/profiles/native.js
index 472f8bcc..3aa7d8b8 100644
--- a/utils/profiles/native.js
+++ b/utils/profiles/native.js
@@ -260,23 +260,27 @@ export default {
SubtitleProfiles: [
{
Format: "pgssub",
- Method: "encode",
+ Method: "embed",
+ },
+ {
+ Format: "subrip",
+ Method: "embed",
},
{
Format: "dvdsub",
- Method: "encode",
+ Method: "embed",
},
{
Format: "dvbsub",
- Method: "encode",
+ Method: "embed",
},
{
Format: "xsub",
- Method: "encode",
+ Method: "embed",
},
{
Format: "vtt",
- Method: "hls",
+ Method: "embed",
},
{
Format: "ttml",