diff --git a/ui/v2.5/package.json b/ui/v2.5/package.json index d287b8437..c1ce15750 100644 --- a/ui/v2.5/package.json +++ b/ui/v2.5/package.json @@ -64,6 +64,7 @@ "slick-carousel": "^1.8.1", "string.prototype.replaceall": "^1.0.7", "thehandy": "^1.0.3", + "ua-parser-js": "^1.0.34", "universal-cookie": "^4.0.4", "video.js": "^7.21.3", "videojs-contrib-dash": "^5.1.1", @@ -89,6 +90,7 @@ "@types/react-helmet": "^6.1.6", "@types/react-router-bootstrap": "^0.24.5", "@types/react-router-hash-link": "^2.4.5", + "@types/ua-parser-js": "^0.7.36", "@types/video.js": "^7.3.51", "@types/videojs-mobile-ui": "^0.8.0", "@types/videojs-seek-buttons": "^2.1.0", diff --git a/ui/v2.5/src/components/ScenePlayer/ScenePlayer.tsx b/ui/v2.5/src/components/ScenePlayer/ScenePlayer.tsx index bb04eec3f..c553fa3cf 100644 --- a/ui/v2.5/src/components/ScenePlayer/ScenePlayer.tsx +++ b/ui/v2.5/src/components/ScenePlayer/ScenePlayer.tsx @@ -11,6 +11,7 @@ import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from "video.js"; import "videojs-contrib-dash"; import "videojs-mobile-ui"; import "videojs-seek-buttons"; +import { UAParser } from "ua-parser-js"; import "./live"; import "./PlaylistButtons"; import "./source-selector"; @@ -487,24 +488,36 @@ export const ScenePlayer: React.FC = ({ }; player.mobileUi(mobileUiOptions); + function isDirect(src: URL) { + return ( + src.pathname.endsWith("/stream") || + src.pathname.endsWith("/stream.mpd") || + src.pathname.endsWith("/stream.m3u8") + ); + } + const { duration } = file; const sourceSelector = player.sourceSelector(); + const isSafari = UAParser().browser.name?.includes("Safari"); sourceSelector.setSources( - scene.sceneStreams.map((stream) => { - const src = new URL(stream.url); - const isDirect = - src.pathname.endsWith("/stream") || - src.pathname.endsWith("/stream.mpd") || - src.pathname.endsWith("/stream.m3u8"); + scene.sceneStreams + .filter((stream) => { + const src = new URL(stream.url); + const isFileTranscode = !isDirect(src); - return { - src: stream.url, - type: stream.mime_type ?? undefined, - label: stream.label ?? undefined, - offset: !isDirect, - duration, - }; - }) + return !(isFileTranscode && isSafari); + }) + .map((stream) => { + const src = new URL(stream.url); + + return { + src: stream.url, + type: stream.mime_type ?? undefined, + label: stream.label ?? undefined, + offset: !isDirect(src), + duration, + }; + }) ); function getDefaultLanguageCode() { diff --git a/ui/v2.5/yarn.lock b/ui/v2.5/yarn.lock index 9c82c29b8..8725ca14e 100644 --- a/ui/v2.5/yarn.lock +++ b/ui/v2.5/yarn.lock @@ -2430,6 +2430,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== +"@types/ua-parser-js@^0.7.36": + version "0.7.36" + resolved "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz" + integrity sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ== + "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" @@ -7678,6 +7683,11 @@ ua-parser-js@^1.0.2: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.33.tgz#f21f01233e90e7ed0f059ceab46eb190ff17f8f4" integrity sha512-RqshF7TPTE0XLYAqmjlu5cLLuGdKrNu9O1KLA/qp39QtbZwuzwv1dT46DZSopoUMsYgXpB3Cv8a03FI8b74oFQ== +ua-parser-js@^1.0.34: + version "1.0.34" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.34.tgz#b33f41c415325839f354005d25a2f588be296976" + integrity sha512-K9mwJm/DaB6mRLZfw6q8IMXipcrmuT6yfhYmwhAkuh+81sChuYstYA+znlgaflUPaYUa3odxKPKGw6Vw/lANew== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"