From d3ec0cab9beef02a9e9bbe43f0cc3c189ad76786 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 31 Mar 2024 19:12:41 +0200 Subject: [PATCH 1/5] Relax same codec check to not care about h264 level --- transcoder/src/filestream.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/transcoder/src/filestream.go b/transcoder/src/filestream.go index dd8c2a03..984cafb1 100644 --- a/transcoder/src/filestream.go +++ b/transcoder/src/filestream.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "os" + "strings" "sync" ) @@ -90,10 +91,12 @@ func (fs *FileStream) GetMaster() string { } aspectRatio := float32(fs.Info.Video.Width) / float32(fs.Info.Video.Height) - transmux_codec := "avc1.640028" + // codec is the prefix + the level, the level is not part of the codec we want to compare for the same_codec check bellow + transmux_prefix := "avc1.6400" + transmux_codec := transmux_prefix + "28" for _, quality := range Qualities { - same_codec := fs.Info.Video.MimeCodec != nil && *fs.Info.Video.MimeCodec == transmux_codec + same_codec := fs.Info.Video.MimeCodec != nil && strings.HasPrefix(*fs.Info.Video.MimeCodec, transmux_prefix) inc_lvl := quality.Height() < fs.Info.Video.Quality.Height() || (quality.Height() == fs.Info.Video.Quality.Height() && !same_codec) From 61a8b07f4bcd84b6e677612140a5e7b01c20c5a2 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 31 Mar 2024 22:57:24 +0200 Subject: [PATCH 2/5] Fix login links no working on mobile --- front/packages/ui/src/login/login.tsx | 4 ++-- front/packages/ui/src/login/oidc.tsx | 4 ++-- front/packages/ui/src/login/register.tsx | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/front/packages/ui/src/login/login.tsx b/front/packages/ui/src/login/login.tsx index 9814638d..546151f7 100644 --- a/front/packages/ui/src/login/login.tsx +++ b/front/packages/ui/src/login/login.tsx @@ -46,7 +46,7 @@ export const LoginPage: QueryPage<{ apiUrl?: string; error?: string }> = ({ useEffect(() => { if (!apiUrl && Platform.OS !== "web") router.replace("/server-url", undefined, { - experimental: { nativeBehavior: "stack-replace", isNestedNavigator: true }, + experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false }, }); }, [apiUrl, router]); @@ -74,7 +74,7 @@ export const LoginPage: QueryPage<{ apiUrl?: string; error?: string }> = ({ setError(error); if (error) return; router.replace("/", undefined, { - experimental: { nativeBehavior: "stack-replace", isNestedNavigator: true }, + experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false }, }); }} {...css({ diff --git a/front/packages/ui/src/login/oidc.tsx b/front/packages/ui/src/login/oidc.tsx index 7de3fdce..43b38772 100644 --- a/front/packages/ui/src/login/oidc.tsx +++ b/front/packages/ui/src/login/oidc.tsx @@ -106,7 +106,7 @@ export const OidcCallbackPage: QueryPage<{ function onError(error: string) { router.replace({ pathname: "/login", query: { error, apiUrl } }, undefined, { - experimental: { nativeBehavior: "stack-replace", isNestedNavigator: true }, + experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false }, }); } async function run() { @@ -114,7 +114,7 @@ export const OidcCallbackPage: QueryPage<{ if (loginError) onError(loginError); else { router.replace("/", undefined, { - experimental: { nativeBehavior: "stack-replace", isNestedNavigator: true }, + experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false }, }); } } diff --git a/front/packages/ui/src/login/register.tsx b/front/packages/ui/src/login/register.tsx index 0ba1d287..81af64ee 100644 --- a/front/packages/ui/src/login/register.tsx +++ b/front/packages/ui/src/login/register.tsx @@ -45,7 +45,7 @@ export const RegisterPage: QueryPage<{ apiUrl?: string }> = ({ apiUrl }) => { useEffect(() => { if (!apiUrl && Platform.OS !== "web") router.replace("/server-url", undefined, { - experimental: { nativeBehavior: "stack-replace", isNestedNavigator: true }, + experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false }, }); }, [apiUrl, router]); @@ -85,7 +85,7 @@ export const RegisterPage: QueryPage<{ apiUrl?: string }> = ({ apiUrl }) => { setError(error); if (error) return; router.replace("/", undefined, { - experimental: { nativeBehavior: "stack-replace", isNestedNavigator: true }, + experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false }, }); }} {...css({ From a8d29b5b2688c62c7ecd9c896a886a2bce96a47f Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 31 Mar 2024 23:00:12 +0200 Subject: [PATCH 3/5] Fix authorization tokens usage on the android player --- front/packages/models/src/login.ts | 26 ++++++++++++++++++++++ front/packages/ui/src/player/video.tsx | 13 +++-------- front/packages/ui/src/player/video.web.tsx | 2 +- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/front/packages/models/src/login.ts b/front/packages/models/src/login.ts index 17cf5c9c..9b910179 100644 --- a/front/packages/models/src/login.ts +++ b/front/packages/models/src/login.ts @@ -24,6 +24,7 @@ import { Account, Token, TokenP, getCurrentApiUrl } from "./accounts"; import { UserP } from "./resources"; import { addAccount, getCurrentAccount, removeAccounts, updateAccount } from "./account-internal"; import { Platform } from "react-native"; +import { useEffect, useRef, useState } from "react"; type Result = | { ok: true; value: A; error?: undefined } @@ -137,6 +138,31 @@ export const getTokenWJ = async ( export const getToken = async (): Promise => (await getTokenWJ())[0]; +export const useToken = () => { + const account = getCurrentAccount(); + const refresher = useRef(null); + const [token, setToken] = useState( + account ? `${account.token.token_type} ${account.token.access_token}` : null, + ); + + useEffect(() => { + async function run() { + const nToken = await getTokenWJ(); + setToken(nToken[0]); + if (refresher.current) clearTimeout(refresher.current); + if (nToken[1]) + refresher.current = setTimeout(run, nToken[1].expire_at.getTime() - Date.now()); + } + run(); + return () => { + if (refresher.current) clearTimeout(refresher.current); + }; + }, [account]); + + if (!token) return null; + return token; +}; + export const logout = () => { removeAccounts((x) => x.selected); }; diff --git a/front/packages/ui/src/player/video.tsx b/front/packages/ui/src/player/video.tsx index 4bd497ff..59ce0d4e 100644 --- a/front/packages/ui/src/player/video.tsx +++ b/front/packages/ui/src/player/video.tsx @@ -33,7 +33,7 @@ declare module "react-native-video" { export * from "react-native-video"; -import { Audio, Subtitle, getToken } from "@kyoo/models"; +import { Audio, Subtitle, getToken, useToken } from "@kyoo/models"; import { IconButton, Menu } from "@kyoo/primitives"; import { ComponentProps, forwardRef, useEffect, useRef } from "react"; import { atom, useAtom, useAtomValue, useSetAtom } from "jotai"; @@ -67,20 +67,13 @@ const Video = forwardRef(function Video( ref, ) { const { css } = useYoshiki(); - const token = useRef(null); + const token = useToken(); const setInfo = useSetAtom(infoAtom); const [video, setVideo] = useAtom(videoAtom); const audio = useAtomValue(audioAtom); const subtitle = useAtomValue(subtitleAtom); const mode = useAtomValue(playModeAtom); - useEffect(() => { - async function run() { - token.current = await getToken(); - } - run(); - }, [source]); - useEffect(() => { if (mode === PlayMode.Hls) setVideo(-1); }, [mode, setVideo]); @@ -92,7 +85,7 @@ const Video = forwardRef(function Video( source={{ ...source, headers: { - Authorization: `Bearer: ${token.current}`, + ...(token ? { Authorization: token } : {}), "X-CLIENT-ID": clientId, }, }} diff --git a/front/packages/ui/src/player/video.web.tsx b/front/packages/ui/src/player/video.web.tsx index c3f1fd02..a0454ab3 100644 --- a/front/packages/ui/src/player/video.web.tsx +++ b/front/packages/ui/src/player/video.web.tsx @@ -70,7 +70,7 @@ const initHls = (): Hls => { hls = new Hls({ xhrSetup: async (xhr) => { const token = await getToken(); - if (token) xhr.setRequestHeader("Authorization", `Bearer: ${token}`); + if (token) xhr.setRequestHeader("Authorization", token); xhr.setRequestHeader("X-CLIENT-ID", client_id); }, autoStartLoad: false, From 0008aa95c20f8cc95b218a318a4516a155d508a2 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 31 Mar 2024 23:08:06 +0200 Subject: [PATCH 4/5] Sort qualites on android --- front/packages/ui/src/player/video.tsx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/front/packages/ui/src/player/video.tsx b/front/packages/ui/src/player/video.tsx index 59ce0d4e..c1b09476 100644 --- a/front/packages/ui/src/player/video.tsx +++ b/front/packages/ui/src/player/video.tsx @@ -174,17 +174,19 @@ export const QualitiesMenu = (props: CustomMenu) => { /> {/* TODO: Support video tracks when the play mode is not hls. */} {/* @ts-expect-error They forgot to type this. */} - {info?.videoTracks.map((x) => ( - { - setPlayMode(PlayMode.Hls); - setVideo(x.height); - }} - /> - ))} + {info?.videoTracks + .sort((a: any, b: any) => b.height - a.height) + .map((x: any, i: number) => ( + { + setPlayMode(PlayMode.Hls); + setVideo(x.height); + }} + /> + ))} ); }; From e16fdc1036265acc6cb111e504434f46434e6180 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 31 Mar 2024 23:24:29 +0200 Subject: [PATCH 5/5] Fix authorization tokens usage on android images --- front/packages/models/src/login.ts | 5 +++++ front/packages/primitives/src/image/image.tsx | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/front/packages/models/src/login.ts b/front/packages/models/src/login.ts index 9b910179..e9799a12 100644 --- a/front/packages/models/src/login.ts +++ b/front/packages/models/src/login.ts @@ -138,6 +138,11 @@ export const getTokenWJ = async ( export const getToken = async (): Promise => (await getTokenWJ())[0]; +export const getCurrentToken = () => { + const account = getCurrentAccount(); + return account ? `${account.token.token_type} ${account.token.access_token}` : null; +}; + export const useToken = () => { const account = getCurrentAccount(); const refresher = useRef(null); diff --git a/front/packages/primitives/src/image/image.tsx b/front/packages/primitives/src/image/image.tsx index 5c0c60d5..667b9de0 100644 --- a/front/packages/primitives/src/image/image.tsx +++ b/front/packages/primitives/src/image/image.tsx @@ -25,6 +25,7 @@ import { Blurhash } from "react-native-blurhash"; import { percent, useYoshiki } from "yoshiki/native"; import { Props, ImageLayout } from "./base-image"; import { Skeleton } from "../skeleton"; +import { getCurrentToken } from "@kyoo/models"; export const Image = ({ src, @@ -60,6 +61,7 @@ export const Image = ({ } quality ??= "high"; + const token = getCurrentToken(); return ( {state !== "finished" && ( @@ -72,6 +74,11 @@ export const Image = ({