From 500005afa8789f8d5db8d592a3585af1887ce0fd Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Sat, 30 Nov 2024 10:18:09 +0100 Subject: [PATCH] fix: burn in subs for downloads --- components/DownloadItem.tsx | 3 +- .../video-player/controls/DropdownView.tsx | 27 ++-- components/video-player/controls/types.ts | 5 +- utils/profiles/download.js | 138 ++++++++++++++++++ 4 files changed, 158 insertions(+), 15 deletions(-) create mode 100644 utils/profiles/download.js diff --git a/components/DownloadItem.tsx b/components/DownloadItem.tsx index 19765708..71409048 100644 --- a/components/DownloadItem.tsx +++ b/components/DownloadItem.tsx @@ -7,6 +7,7 @@ import { getDefaultPlaySettings } from "@/utils/jellyfin/getDefaultPlaySettings" import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl"; import { saveDownloadItemInfoToDiskTmp } from "@/utils/optimize-server"; import native from "@/utils/profiles/native"; +import download from "@/utils/profiles/download"; import Ionicons from "@expo/vector-icons/Ionicons"; import { BottomSheetBackdrop, @@ -107,7 +108,7 @@ export const DownloadItem: React.FC = ({ item, ...props }) => { maxStreamingBitrate: maxBitrate.value, mediaSourceId: selectedMediaSource.Id, subtitleStreamIndex: selectedSubtitleStream, - deviceProfile: native, + deviceProfile: download, }); if (!res) { diff --git a/components/video-player/controls/DropdownView.tsx b/components/video-player/controls/DropdownView.tsx index 4621758a..63a96f01 100644 --- a/components/video-player/controls/DropdownView.tsx +++ b/components/video-player/controls/DropdownView.tsx @@ -15,9 +15,13 @@ import { useLocalSearchParams, useRouter } from "expo-router"; interface DropdownViewProps { showControls: boolean; + offline?: boolean; // used to disable external subs for downloads } -const DropdownView: React.FC = ({ showControls }) => { +const DropdownView: React.FC = ({ + showControls, + offline = false, +}) => { const router = useRouter(); const api = useAtomValue(apiAtom); const ControlContext = useControlContext(); @@ -54,12 +58,15 @@ const DropdownView: React.FC = ({ showControls }) => { deliveryUrl: s.DeliveryUrl, })) || []; - // Combine embedded and unique external subs - return [...embeddedSubs, ...externalSubs] as ( - | EmbeddedSubtitle - | ExternalSubtitle - )[]; - }, [item, isVideoLoaded, subtitleTracks, mediaSource?.MediaStreams]); + // Combine embedded subs with external subs only if not offline + if (!offline) { + return [...embeddedSubs, ...externalSubs] as ( + | EmbeddedSubtitle + | ExternalSubtitle + )[]; + } + return embeddedSubs as EmbeddedSubtitle[]; + }, [item, isVideoLoaded, subtitleTracks, mediaSource?.MediaStreams, offline]); const { subtitleIndex, audioIndex, bitrateValue } = useLocalSearchParams<{ itemId: string; @@ -271,9 +278,7 @@ const DropdownView: React.FC = ({ showControls }) => { value={selectedSubtitleIndex === sub.index} key={`subtitle-item-${idx}`} onValueChange={() => { - console.log("Set sub index: ", sub.index); - if (selectedSubtitleIndex === sub?.index.toString()) - return; + if (selectedSubtitleIndex === sub?.index) return; setSelectedSubtitleIndex(sub.index); if (sub.IsTextSubtitleStream && isOnTextSubtitle) { setSubtitleTrack && setSubtitleTrack(sub.index); @@ -325,7 +330,7 @@ const DropdownView: React.FC = ({ showControls }) => { key={`audio-item-${idx}`} value={selectedAudioIndex === track.index} onValueChange={() => { - if (selectedAudioIndex === track.index.toString()) return; + if (selectedAudioIndex === track.index) return; setSelectedAudioIndex(track.index); ChangeTranscodingAudio(track.index); }} diff --git a/components/video-player/controls/types.ts b/components/video-player/controls/types.ts index b66ecd8e..ac739049 100644 --- a/components/video-player/controls/types.ts +++ b/components/video-player/controls/types.ts @@ -1,7 +1,6 @@ type EmbeddedSubtitle = { name: string; index: number; - isExternal: boolean; }; type ExternalSubtitle = { @@ -15,6 +14,6 @@ type TranscodedSubtitle = { name: string; index: number; IsTextSubtitleStream: boolean; -} +}; -export { EmbeddedSubtitle, ExternalSubtitle, TranscodedSubtitle }; \ No newline at end of file +export { EmbeddedSubtitle, ExternalSubtitle, TranscodedSubtitle }; diff --git a/utils/profiles/download.js b/utils/profiles/download.js new file mode 100644 index 00000000..4f0d4d4d --- /dev/null +++ b/utils/profiles/download.js @@ -0,0 +1,138 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +import MediaTypes from "../../constants/MediaTypes"; + +/** + * Device profile for Native video player + */ +export default { + Name: "1. Vlc Player", + MaxStaticBitrate: 20_000_000, + MaxStreamingBitrate: 20_000_000, + CodecProfiles: [ + { + Type: MediaTypes.Video, + Codec: "h264,h265,hevc,mpeg4,divx,xvid,wmv,vc1,vp8,vp9,av1", + }, + { + Type: MediaTypes.Audio, + Codec: "aac,ac3,eac3,mp3,flac,alac,opus,vorbis,pcm,wma", + }, + ], + DirectPlayProfiles: [ + { + Type: MediaTypes.Video, + Container: "mp4,mkv,avi,mov,flv,ts,m2ts,webm,ogv,3gp,hls", + VideoCodec: + "h264,hevc,mpeg4,divx,xvid,wmv,vc1,vp8,vp9,av1,avi,mpeg,mpeg2video", + AudioCodec: "aac,ac3,eac3,mp3,flac,alac,opus,vorbis,wma", + }, + { + Type: MediaTypes.Audio, + Container: "mp3,aac,flac,alac,wav,ogg,wma", + AudioCodec: + "mp3,aac,flac,alac,opus,vorbis,wma,pcm,mpa,wav,ogg,oga,webma,ape", + }, + ], + TranscodingProfiles: [ + { + Type: MediaTypes.Video, + Context: "Streaming", + Protocol: "hls", + Container: "ts", + VideoCodec: "h264, hevc", + AudioCodec: "aac,mp3,ac3", + CopyTimestamps: false, + EnableSubtitlesInManifest: true, + }, + { + Type: MediaTypes.Audio, + Context: "Streaming", + Protocol: "http", + Container: "mp3", + AudioCodec: "mp3", + MaxAudioChannels: "2", + }, + ], + SubtitleProfiles: [ + // Official foramts + { Format: "vtt", Method: "Embed" }, + { Format: "vtt", Method: "Encode" }, + + { Format: "webvtt", Method: "Embed" }, + { Format: "webvtt", Method: "Encode" }, + + { Format: "srt", Method: "Embed" }, + { Format: "srt", Method: "Encode" }, + + { Format: "subrip", Method: "Embed" }, + { Format: "subrip", Method: "Encode" }, + + { Format: "ttml", Method: "Embed" }, + { Format: "ttml", Method: "Encode" }, + + { Format: "dvbsub", Method: "Embed" }, + { Format: "dvdsub", Method: "Encode" }, + + { Format: "ass", Method: "Embed" }, + { Format: "ass", Method: "Encode" }, + + { Format: "idx", Method: "Embed" }, + { Format: "idx", Method: "Encode" }, + + { Format: "pgs", Method: "Embed" }, + { Format: "pgs", Method: "Encode" }, + + { Format: "pgssub", Method: "Embed" }, + { Format: "pgssub", Method: "Encode" }, + + { Format: "ssa", Method: "Embed" }, + { Format: "ssa", Method: "Encode" }, + + // Other formats + { Format: "microdvd", Method: "Embed" }, + { Format: "microdvd", Method: "Encode" }, + + { Format: "mov_text", Method: "Embed" }, + { Format: "mov_text", Method: "Encode" }, + + { Format: "mpl2", Method: "Embed" }, + { Format: "mpl2", Method: "Encode" }, + + { Format: "pjs", Method: "Embed" }, + { Format: "pjs", Method: "Encode" }, + + { Format: "realtext", Method: "Embed" }, + { Format: "realtext", Method: "Encode" }, + + { Format: "scc", Method: "Embed" }, + { Format: "scc", Method: "Encode" }, + + { Format: "smi", Method: "Embed" }, + { Format: "smi", Method: "Encode" }, + + { Format: "stl", Method: "Embed" }, + { Format: "stl", Method: "Encode" }, + + { Format: "sub", Method: "Embed" }, + { Format: "sub", Method: "Encode" }, + + { Format: "subviewer", Method: "Embed" }, + { Format: "subviewer", Method: "Encode" }, + + { Format: "teletext", Method: "Embed" }, + { Format: "teletext", Method: "Encode" }, + + { Format: "text", Method: "Embed" }, + { Format: "text", Method: "Encode" }, + + { Format: "vplayer", Method: "Embed" }, + { Format: "vplayer", Method: "Encode" }, + + { Format: "xsub", Method: "Embed" }, + { Format: "xsub", Method: "Encode" }, + ], +};