mirror of
https://github.com/streamyfin/streamyfin.git
synced 2025-08-20 18:37:18 +02:00
fix: dolby vision on supported devices, specifically profile 5 (#660)
This commit is contained in:
@@ -17,7 +17,7 @@ import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
|||||||
import { useSettings } from "@/utils/atoms/settings";
|
import { useSettings } from "@/utils/atoms/settings";
|
||||||
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
|
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
|
||||||
import { writeToLog } from "@/utils/log";
|
import { writeToLog } from "@/utils/log";
|
||||||
import native from "@/utils/profiles/native";
|
import generateDeviceProfile from "@/utils/profiles/native";
|
||||||
import { msToTicks, ticksToSeconds } from "@/utils/time";
|
import { msToTicks, ticksToSeconds } from "@/utils/time";
|
||||||
import {
|
import {
|
||||||
type BaseItemDto,
|
type BaseItemDto,
|
||||||
@@ -159,6 +159,7 @@ export default function page() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchStreamData = async () => {
|
const fetchStreamData = async () => {
|
||||||
|
const native = await generateDeviceProfile();
|
||||||
try {
|
try {
|
||||||
let result: Stream | null = null;
|
let result: Stream | null = null;
|
||||||
if (offline && !Platform.isTV) {
|
if (offline && !Platform.isTV) {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { getPrimaryImageUrl } from "@/utils/jellyfin/image/getPrimaryImageUrl";
|
|||||||
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
|
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
|
||||||
import { chromecast } from "@/utils/profiles/chromecast";
|
import { chromecast } from "@/utils/profiles/chromecast";
|
||||||
import { chromecasth265 } from "@/utils/profiles/chromecasth265";
|
import { chromecasth265 } from "@/utils/profiles/chromecasth265";
|
||||||
import ios from "@/utils/profiles/ios";
|
|
||||||
import { runtimeTicksToMinutes } from "@/utils/time";
|
import { runtimeTicksToMinutes } from "@/utils/time";
|
||||||
import { useActionSheet } from "@expo/react-native-action-sheet";
|
import { useActionSheet } from "@expo/react-native-action-sheet";
|
||||||
import { Feather, Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
import { Feather, Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Bitrate } from "@/components/BitrateSelector";
|
import type { Bitrate } from "@/components/BitrateSelector";
|
||||||
import { settingsAtom } from "@/utils/atoms/settings";
|
import { settingsAtom } from "@/utils/atoms/settings";
|
||||||
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
|
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
|
||||||
import native from "@/utils/profiles/native";
|
import generateDeviceProfile from "@/utils/profiles/native";
|
||||||
import type {
|
import type {
|
||||||
BaseItemDto,
|
BaseItemDto,
|
||||||
MediaSourceInfo,
|
MediaSourceInfo,
|
||||||
@@ -84,6 +84,7 @@ export const PlaySettingsProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const native = await generateDeviceProfile();
|
||||||
const data = await getStreamUrl({
|
const data = await getStreamUrl({
|
||||||
api,
|
api,
|
||||||
deviceProfile: native,
|
deviceProfile: native,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import native from "@/utils/profiles/native";
|
import generateDeviceProfile from "@/utils/profiles/native";
|
||||||
import type { Api } from "@jellyfin/sdk";
|
import type { Api } from "@jellyfin/sdk";
|
||||||
import type {
|
import type {
|
||||||
BaseItemDto,
|
BaseItemDto,
|
||||||
@@ -15,7 +15,7 @@ export const getStreamUrl = async ({
|
|||||||
startTimeTicks = 0,
|
startTimeTicks = 0,
|
||||||
maxStreamingBitrate,
|
maxStreamingBitrate,
|
||||||
sessionData,
|
sessionData,
|
||||||
deviceProfile = native,
|
deviceProfile = generateDeviceProfile(),
|
||||||
audioStreamIndex = 0,
|
audioStreamIndex = 0,
|
||||||
subtitleStreamIndex = undefined,
|
subtitleStreamIndex = undefined,
|
||||||
mediaSourceId,
|
mediaSourceId,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { getOrSetDeviceId } from "@/providers/JellyfinProvider";
|
import { getOrSetDeviceId } from "@/providers/JellyfinProvider";
|
||||||
import type { Settings } from "@/utils/atoms/settings";
|
import type { Settings } from "@/utils/atoms/settings";
|
||||||
import ios from "@/utils/profiles/ios";
|
|
||||||
import native from "@/utils/profiles/native";
|
|
||||||
import old from "@/utils/profiles/old";
|
import old from "@/utils/profiles/old";
|
||||||
import type { Api } from "@jellyfin/sdk";
|
import type { Api } from "@jellyfin/sdk";
|
||||||
import { DeviceProfile } from "@jellyfin/sdk/lib/generated-client";
|
import { DeviceProfile } from "@jellyfin/sdk/lib/generated-client";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Settings } from "@/utils/atoms/settings";
|
import type { Settings } from "@/utils/atoms/settings";
|
||||||
import native from "@/utils/profiles/native";
|
import generateDeviceProfile from "@/utils/profiles/native";
|
||||||
import type { Api } from "@jellyfin/sdk";
|
import type { Api } from "@jellyfin/sdk";
|
||||||
import type { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import { getAuthHeaders } from "../jellyfin";
|
import { getAuthHeaders } from "../jellyfin";
|
||||||
@@ -43,7 +43,7 @@ export const postCapabilities = async ({
|
|||||||
],
|
],
|
||||||
supportsMediaControl: true,
|
supportsMediaControl: true,
|
||||||
id: sessionId,
|
id: sessionId,
|
||||||
DeviceProfile: native,
|
DeviceProfile: generateDeviceProfile(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers: getAuthHeaders(api),
|
headers: getAuthHeaders(api),
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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. Native iOS Video Profile",
|
|
||||||
MaxStaticBitrate: 100000000,
|
|
||||||
MaxStreamingBitrate: 120000000,
|
|
||||||
MusicStreamingTranscodingBitrate: 384000,
|
|
||||||
CodecProfiles: [
|
|
||||||
{
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
Codec: "h264,h265,hevc,mpeg4,divx,xvid,wmv,vc1,vp8,vp9,av1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
Codec: "aac,mp3,flac,alac,opus,vorbis,pcm,wma",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
DirectPlayProfiles: [
|
|
||||||
{
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
Container: "mp4,mkv,avi,mov,flv,ts,m2ts,webm,ogv,3gp",
|
|
||||||
VideoCodec: "h264,h265,hevc,mpeg4,divx,xvid,wmv,vc1,vp8,vp9,av1",
|
|
||||||
AudioCodec: "aac,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",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TranscodingProfiles: [
|
|
||||||
{
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
Context: "Streaming",
|
|
||||||
Protocol: "hls",
|
|
||||||
Container: "ts",
|
|
||||||
VideoCodec: "h264",
|
|
||||||
AudioCodec: "aac,mp3,ac3",
|
|
||||||
MaxAudioChannels: "8",
|
|
||||||
MinSegments: "2",
|
|
||||||
BreakOnNonKeyFrames: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
Context: "Streaming",
|
|
||||||
Protocol: "http",
|
|
||||||
Container: "mp3",
|
|
||||||
AudioCodec: "mp3",
|
|
||||||
MaxAudioChannels: "2",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
ResponseProfiles: [
|
|
||||||
{
|
|
||||||
Container: "mkv",
|
|
||||||
MimeType: "video/x-matroska",
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Container: "mp4",
|
|
||||||
MimeType: "video/mp4",
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
SubtitleProfiles: [
|
|
||||||
{ Format: "srt", Method: "Embed" },
|
|
||||||
{ Format: "srt", Method: "External" },
|
|
||||||
{ Format: "srt", Method: "Encode" },
|
|
||||||
{ Format: "ass", Method: "Embed" },
|
|
||||||
{ Format: "ass", Method: "External" },
|
|
||||||
{ Format: "ass", Method: "Encode" },
|
|
||||||
{ Format: "ssa", Method: "Embed" },
|
|
||||||
{ Format: "ssa", Method: "External" },
|
|
||||||
{ Format: "ssa", Method: "Encode" },
|
|
||||||
{ Format: "sub", Method: "Embed" },
|
|
||||||
{ Format: "sub", Method: "External" },
|
|
||||||
{ Format: "sub", Method: "Encode" },
|
|
||||||
{ Format: "vtt", Method: "Embed" },
|
|
||||||
{ Format: "vtt", Method: "External" },
|
|
||||||
{ Format: "vtt", Method: "Encode" },
|
|
||||||
{ Format: "ttml", Method: "Embed" },
|
|
||||||
{ Format: "ttml", Method: "External" },
|
|
||||||
{ Format: "ttml", Method: "Encode" },
|
|
||||||
{ Format: "pgs", Method: "Embed" },
|
|
||||||
{ Format: "pgs", Method: "External" },
|
|
||||||
{ Format: "pgs", Method: "Encode" },
|
|
||||||
{ Format: "dvdsub", Method: "Embed" },
|
|
||||||
{ Format: "dvdsub", Method: "External" },
|
|
||||||
{ Format: "dvdsub", Method: "Encode" },
|
|
||||||
{ Format: "dvbsub", Method: "Embed" },
|
|
||||||
{ Format: "dvbsub", Method: "External" },
|
|
||||||
{ Format: "dvbsub", Method: "Encode" },
|
|
||||||
{ Format: "xsub", Method: "Embed" },
|
|
||||||
{ Format: "xsub", Method: "External" },
|
|
||||||
{ Format: "xsub", Method: "Encode" },
|
|
||||||
{ Format: "mov_text", Method: "Embed" },
|
|
||||||
{ Format: "mov_text", Method: "External" },
|
|
||||||
{ Format: "mov_text", Method: "Encode" },
|
|
||||||
{ Format: "scc", Method: "Embed" },
|
|
||||||
{ Format: "scc", Method: "External" },
|
|
||||||
{ Format: "scc", Method: "Encode" },
|
|
||||||
{ Format: "smi", Method: "Embed" },
|
|
||||||
{ Format: "smi", Method: "External" },
|
|
||||||
{ Format: "smi", Method: "Encode" },
|
|
||||||
{ Format: "teletext", Method: "Embed" },
|
|
||||||
{ Format: "teletext", Method: "External" },
|
|
||||||
{ Format: "teletext", Method: "Encode" },
|
|
||||||
{ Format: "microdvd", Method: "Embed" },
|
|
||||||
{ Format: "microdvd", Method: "External" },
|
|
||||||
{ Format: "microdvd", Method: "Encode" },
|
|
||||||
{ Format: "mpl2", Method: "Embed" },
|
|
||||||
{ Format: "mpl2", Method: "External" },
|
|
||||||
{ Format: "mpl2", Method: "Encode" },
|
|
||||||
{ Format: "pjs", Method: "Embed" },
|
|
||||||
{ Format: "pjs", Method: "External" },
|
|
||||||
{ Format: "pjs", Method: "Encode" },
|
|
||||||
{ Format: "realtext", Method: "Embed" },
|
|
||||||
{ Format: "realtext", Method: "External" },
|
|
||||||
{ Format: "realtext", Method: "Encode" },
|
|
||||||
{ Format: "stl", Method: "Embed" },
|
|
||||||
{ Format: "stl", Method: "External" },
|
|
||||||
{ Format: "stl", Method: "Encode" },
|
|
||||||
{ Format: "subrip", Method: "Embed" },
|
|
||||||
{ Format: "subrip", Method: "External" },
|
|
||||||
{ Format: "subrip", Method: "Encode" },
|
|
||||||
{ Format: "subviewer", Method: "Embed" },
|
|
||||||
{ Format: "subviewer", Method: "External" },
|
|
||||||
{ Format: "subviewer", Method: "Encode" },
|
|
||||||
{ Format: "text", Method: "Embed" },
|
|
||||||
{ Format: "text", Method: "External" },
|
|
||||||
{ Format: "text", Method: "Encode" },
|
|
||||||
{ Format: "vplayer", Method: "Embed" },
|
|
||||||
{ Format: "vplayer", Method: "External" },
|
|
||||||
{ Format: "vplayer", Method: "Encode" },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import MediaTypes from "../../constants/MediaTypes";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
Name: "Expo Base Video Profile",
|
|
||||||
MaxStaticBitrate: 100000000,
|
|
||||||
MaxStreamingBitrate: 120000000,
|
|
||||||
MusicStreamingTranscodingBitrate: 384000,
|
|
||||||
CodecProfiles: [
|
|
||||||
{
|
|
||||||
Codec: "h264",
|
|
||||||
Conditions: [
|
|
||||||
{
|
|
||||||
Condition: "NotEquals",
|
|
||||||
IsRequired: false,
|
|
||||||
Property: "IsAnamorphic",
|
|
||||||
Value: "true",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: "EqualsAny",
|
|
||||||
IsRequired: false,
|
|
||||||
Property: "VideoProfile",
|
|
||||||
Value: "high|main|baseline|constrained baseline",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: "LessThanEqual",
|
|
||||||
IsRequired: false,
|
|
||||||
Property: "VideoLevel",
|
|
||||||
Value: "51",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: "NotEquals",
|
|
||||||
IsRequired: false,
|
|
||||||
Property: "IsInterlaced",
|
|
||||||
Value: "true",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Codec: "hevc",
|
|
||||||
Conditions: [
|
|
||||||
{
|
|
||||||
Condition: "NotEquals",
|
|
||||||
IsRequired: false,
|
|
||||||
Property: "IsAnamorphic",
|
|
||||||
Value: "true",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: "EqualsAny",
|
|
||||||
IsRequired: false,
|
|
||||||
Property: "VideoProfile",
|
|
||||||
Value: "main|main 10",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: "LessThanEqual",
|
|
||||||
IsRequired: false,
|
|
||||||
Property: "VideoLevel",
|
|
||||||
Value: "183",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Condition: "NotEquals",
|
|
||||||
IsRequired: false,
|
|
||||||
Property: "IsInterlaced",
|
|
||||||
Value: "true",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
ContainerProfiles: [],
|
|
||||||
DirectPlayProfiles: [],
|
|
||||||
ResponseProfiles: [
|
|
||||||
{
|
|
||||||
Container: "m4v",
|
|
||||||
MimeType: "video/mp4",
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
SubtitleProfiles: [
|
|
||||||
{
|
|
||||||
Format: "vtt",
|
|
||||||
Method: "Hls",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TranscodingProfiles: [],
|
|
||||||
};
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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";
|
|
||||||
|
|
||||||
import BaseProfile from "./base";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Device profile for Expo Video player on iOS 13+
|
|
||||||
*/
|
|
||||||
export default {
|
|
||||||
...BaseProfile,
|
|
||||||
Name: "Expo iOS Video Profile",
|
|
||||||
DirectPlayProfiles: [
|
|
||||||
{
|
|
||||||
AudioCodec: "aac,mp3,ac3,eac3,flac,alac",
|
|
||||||
Container: "mp4,m4v",
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
VideoCodec: "hevc,h264",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "aac,mp3,ac3,eac3,flac,alac",
|
|
||||||
Container: "mov",
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
VideoCodec: "hevc,h264",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Container: "mp3",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Container: "aac",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "aac",
|
|
||||||
Container: "m4a",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "aac",
|
|
||||||
Container: "m4b",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Container: "flac",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Container: "alac",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "alac",
|
|
||||||
Container: "m4a",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "alac",
|
|
||||||
Container: "m4b",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Container: "wav",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TranscodingProfiles: [
|
|
||||||
{
|
|
||||||
AudioCodec: "aac",
|
|
||||||
BreakOnNonKeyFrames: true,
|
|
||||||
Container: "aac",
|
|
||||||
Context: "Streaming",
|
|
||||||
MaxAudioChannels: "6",
|
|
||||||
MinSegments: "2",
|
|
||||||
Protocol: "hls",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "aac",
|
|
||||||
Container: "aac",
|
|
||||||
Context: "Streaming",
|
|
||||||
MaxAudioChannels: "6",
|
|
||||||
Protocol: "http",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "mp3",
|
|
||||||
Container: "mp3",
|
|
||||||
Context: "Streaming",
|
|
||||||
MaxAudioChannels: "6",
|
|
||||||
Protocol: "http",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "wav",
|
|
||||||
Container: "wav",
|
|
||||||
Context: "Streaming",
|
|
||||||
MaxAudioChannels: "6",
|
|
||||||
Protocol: "http",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "mp3",
|
|
||||||
Container: "mp3",
|
|
||||||
Context: "Static",
|
|
||||||
MaxAudioChannels: "6",
|
|
||||||
Protocol: "http",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "aac",
|
|
||||||
Container: "aac",
|
|
||||||
Context: "Static",
|
|
||||||
MaxAudioChannels: "6",
|
|
||||||
Protocol: "http",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "wav",
|
|
||||||
Container: "wav",
|
|
||||||
Context: "Static",
|
|
||||||
MaxAudioChannels: "6",
|
|
||||||
Protocol: "http",
|
|
||||||
Type: MediaTypes.Audio,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "aac,mp3",
|
|
||||||
BreakOnNonKeyFrames: true,
|
|
||||||
Container: "ts",
|
|
||||||
Context: "Streaming",
|
|
||||||
MaxAudioChannels: "6",
|
|
||||||
MinSegments: "2",
|
|
||||||
Protocol: "hls",
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
VideoCodec: "h264",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AudioCodec: "aac,mp3,ac3,eac3,flac,alac",
|
|
||||||
Container: "mp4",
|
|
||||||
Context: "Static",
|
|
||||||
Protocol: "http",
|
|
||||||
Type: MediaTypes.Video,
|
|
||||||
VideoCodec: "h264",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { Platform } from "react-native";
|
||||||
|
import DeviceInfo from "react-native-device-info";
|
||||||
/**
|
/**
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -5,17 +7,52 @@
|
|||||||
*/
|
*/
|
||||||
import MediaTypes from "../../constants/MediaTypes";
|
import MediaTypes from "../../constants/MediaTypes";
|
||||||
|
|
||||||
|
// Helper function to detect Dolby Vision support
|
||||||
|
const supportsDolbyVision = async () => {
|
||||||
|
if (Platform.OS === "ios") {
|
||||||
|
const deviceModel = await DeviceInfo.getModel();
|
||||||
|
// iPhone 12 and newer generally support Dolby Vision
|
||||||
|
const modelNumber = Number.parseInt(deviceModel.replace(/iPhone/, ""), 10);
|
||||||
|
return !Number.isNaN(modelNumber) && modelNumber >= 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Platform.OS === "android") {
|
||||||
|
const apiLevel = await DeviceInfo.getApiLevel();
|
||||||
|
const isHighEndDevice =
|
||||||
|
(await DeviceInfo.getTotalMemory()) > 4 * 1024 * 1024 * 1024; // >4GB RAM
|
||||||
|
// Very rough approximation - Android 10+ on higher-end devices may support it
|
||||||
|
return apiLevel >= 29 && isHighEndDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generateDeviceProfile = async () => {
|
||||||
|
const dolbyVisionSupported = await supportsDolbyVision();
|
||||||
/**
|
/**
|
||||||
* Device profile for Native video player
|
* Device profile for Native video player
|
||||||
*/
|
*/
|
||||||
export default {
|
const profile = {
|
||||||
Name: "1. Vlc Player",
|
Name: "1. Vlc Player",
|
||||||
MaxStaticBitrate: 999_999_999,
|
MaxStaticBitrate: 999_999_999,
|
||||||
MaxStreamingBitrate: 999_999_999,
|
MaxStreamingBitrate: 999_999_999,
|
||||||
CodecProfiles: [
|
CodecProfiles: [
|
||||||
{
|
{
|
||||||
Type: MediaTypes.Video,
|
Type: MediaTypes.Video,
|
||||||
Codec: "h264,h265,hevc,mpeg4,divx,xvid,wmv,vc1,vp8,vp9,av1",
|
Codec: "h264,mpeg4,divx,xvid,wmv,vc1,vp8,vp9,av1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: MediaTypes.Video,
|
||||||
|
Codec: "hevc,h265",
|
||||||
|
Conditions: [
|
||||||
|
{
|
||||||
|
Condition: "LessThanEqual",
|
||||||
|
Property: "VideoLevel",
|
||||||
|
Value: "153",
|
||||||
|
IsRequired: false,
|
||||||
|
},
|
||||||
|
// We'll add Dolby Vision condition below if not supported
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: MediaTypes.Audio,
|
Type: MediaTypes.Audio,
|
||||||
@@ -134,3 +171,26 @@ export default {
|
|||||||
{ Format: "xsub", Method: "External" },
|
{ Format: "xsub", Method: "External" },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add Dolby Vision restriction if not supported
|
||||||
|
if (!dolbyVisionSupported) {
|
||||||
|
const hevcProfile = profile.CodecProfiles.find(
|
||||||
|
(p) => p.Type === MediaTypes.Video && p.Codec.includes("hevc"),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hevcProfile) {
|
||||||
|
hevcProfile.Conditions.push({
|
||||||
|
Condition: "NotEquals",
|
||||||
|
Property: "VideoRangeType",
|
||||||
|
Value: "DOVI", //no dolby vision at all
|
||||||
|
IsRequired: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return profile;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async () => {
|
||||||
|
return await generateDeviceProfile();
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user